aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIain Sandoe <iain@sandoe.co.uk>2019-12-02 09:46:51 +0000
committerIain Sandoe <iain@sandoe.co.uk>2019-12-02 09:46:51 +0000
commit9d5bec7646fdc120087e39ba6ac01b5c299bf8aa (patch)
tree00f30fd30ba8b51d3af1a92679caff966f093489
parentbf31886696cb7906760c6d7d24fab82d5bb646ba (diff)
parent02e688f0e850db35366a26a525e2876f93ffafd6 (diff)
c++-coroutines - merge trunk r278894.
2019-12-02 Iain Sandoe <iain@sandoe.co.uk> Merge trunk r278894. git-svn-id: https://gcc.gnu.org/svn/gcc/branches/c++-coroutines@278895 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--ChangeLog12
-rw-r--r--ChangeLog.coroutines4
-rwxr-xr-xconfigure6
-rw-r--r--configure.ac6
-rw-r--r--gcc/ChangeLog775
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/REVISION2
-rw-r--r--gcc/attribs.c15
-rw-r--r--gcc/auto-inc-dec.c7
-rw-r--r--gcc/builtin-types.def15
-rw-r--r--gcc/builtins.c19
-rw-r--r--gcc/c-family/ChangeLog36
-rw-r--r--gcc/c-family/c-attribs.c60
-rw-r--r--gcc/c-family/c-common.c24
-rw-r--r--gcc/c-family/c-cppbuiltin.c4
-rw-r--r--gcc/c-family/c-format.c2
-rw-r--r--gcc/c-family/c-lex.c7
-rw-r--r--gcc/c/ChangeLog55
-rw-r--r--gcc/c/c-decl.c121
-rw-r--r--gcc/c/c-parser.c177
-rw-r--r--gcc/c/c-tree.h12
-rw-r--r--gcc/c/c-typeck.c8
-rw-r--r--gcc/c/gimple-parser.c4
-rw-r--r--gcc/cfganal.c2
-rw-r--r--gcc/cgraph.c27
-rw-r--r--gcc/cgraph.h11
-rw-r--r--gcc/cgraphclones.c30
-rw-r--r--gcc/cgraphunit.c92
-rw-r--r--gcc/combine.c12
-rw-r--r--gcc/config/aarch64/aarch64-protos.h3
-rw-r--r--gcc/config/aarch64/aarch64-sve-builtins.cc49
-rw-r--r--gcc/config/aarch64/aarch64.c12
-rw-r--r--gcc/config/avr/avr.md2
-rw-r--r--gcc/config/elfos.h11
-rw-r--r--gcc/config/gcn/gcn.c6
-rw-r--r--gcc/config/gcn/mkoffload.c11
-rw-r--r--gcc/config/i386/sse.md4
-rw-r--r--gcc/config/m68k/m68k-protos.h19
-rw-r--r--gcc/config/m68k/m68k.c895
-rw-r--r--gcc/config/m68k/m68k.h32
-rw-r--r--gcc/config/m68k/m68k.md2515
-rw-r--r--gcc/config/m68k/predicates.md32
-rw-r--r--gcc/config/nios2/nios2.c16
-rw-r--r--gcc/config/nios2/nios2.h6
-rw-r--r--gcc/config/rs6000/rs6000-call.c14
-rw-r--r--gcc/config/rs6000/rs6000.c29
-rw-r--r--gcc/config/rs6000/rs6000.md165
-rw-r--r--gcc/config/s390/linux.h2
-rw-r--r--gcc/cp/ChangeLog194
-rw-r--r--gcc/cp/call.c17
-rw-r--r--gcc/cp/class.c56
-rw-r--r--gcc/cp/constexpr.c82
-rw-r--r--gcc/cp/constraint.cc228
-rw-r--r--gcc/cp/cp-gimplify.c16
-rw-r--r--gcc/cp/cp-tree.h23
-rw-r--r--gcc/cp/cvt.c6
-rw-r--r--gcc/cp/cxx-pretty-print.c6
-rw-r--r--gcc/cp/decl.c16
-rw-r--r--gcc/cp/decl2.c7
-rw-r--r--gcc/cp/error.c9
-rw-r--r--gcc/cp/mangle.c11
-rw-r--r--gcc/cp/parser.c302
-rw-r--r--gcc/cp/pt.c624
-rw-r--r--gcc/cp/semantics.c43
-rw-r--r--gcc/cp/tree.c19
-rw-r--r--gcc/cp/typeck.c107
-rw-r--r--gcc/cp/typeck2.c2
-rw-r--r--gcc/dbgcnt.c3
-rw-r--r--gcc/doc/extend.texi35
-rw-r--r--gcc/doc/install.texi4
-rw-r--r--gcc/doc/invoke.texi7
-rw-r--r--gcc/doc/sourcebuild.texi4
-rw-r--r--gcc/doc/tm.texi25
-rw-r--r--gcc/doc/tm.texi.in4
-rw-r--r--gcc/dwarf2out.c3
-rw-r--r--gcc/fold-const-call.c46
-rw-r--r--gcc/fortran/ChangeLog28
-rw-r--r--gcc/fortran/arith.c4
-rw-r--r--gcc/fortran/dependency.c12
-rw-r--r--gcc/fortran/io.c19
-rw-r--r--gcc/fortran/simplify.c8
-rw-r--r--gcc/gcc.c2
-rw-r--r--gcc/gimple-fold.c14
-rw-r--r--gcc/gimple-match-head.c18
-rw-r--r--gcc/gimple-ssa-sprintf.c4
-rw-r--r--gcc/ipa-cp.c241
-rw-r--r--gcc/ipa-devirt.c32
-rw-r--r--gcc/ipa-fnsummary.c5
-rw-r--r--gcc/ipa-fnsummary.h17
-rw-r--r--gcc/ipa-icf.c3
-rw-r--r--gcc/ipa-inline-analysis.c4
-rw-r--r--gcc/ipa-inline-transform.c51
-rw-r--r--gcc/ipa-inline.c31
-rw-r--r--gcc/ipa-prop.h2
-rw-r--r--gcc/ipa-utils.c64
-rw-r--r--gcc/jit/ChangeLog5
-rw-r--r--gcc/jit/jit-builtins.c3
-rw-r--r--gcc/lra.c7
-rw-r--r--gcc/lto-cgraph.c13
-rw-r--r--gcc/lto-streamer.h2
-rw-r--r--gcc/lto/ChangeLog6
-rw-r--r--gcc/lto/lto-lang.c9
-rw-r--r--gcc/lto/lto-symtab.c7
-rw-r--r--gcc/match.pd32
-rw-r--r--gcc/optabs-tree.c19
-rw-r--r--gcc/optabs-tree.h2
-rw-r--r--gcc/output.h1
-rw-r--r--gcc/params.opt8
-rw-r--r--gcc/predict.c2
-rw-r--r--gcc/profile-count.c35
-rw-r--r--gcc/profile-count.h43
-rw-r--r--gcc/real.c24
-rw-r--r--gcc/realmpfr.c9
-rw-r--r--gcc/realmpfr.h12
-rw-r--r--gcc/recog.c22
-rw-r--r--gcc/recog.h1
-rw-r--r--gcc/rtl.h1
-rw-r--r--gcc/rtlanal.c58
-rw-r--r--gcc/symtab.c22
-rw-r--r--gcc/target.def32
-rw-r--r--gcc/target.h29
-rw-r--r--gcc/targhooks.c10
-rw-r--r--gcc/targhooks.h2
-rw-r--r--gcc/testsuite/ChangeLog332
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr67595.C2
-rw-r--r--gcc/testsuite/g++.dg/concepts/pr84330.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-4.C11
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum23.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum38.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-71.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist26.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist28.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist29.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist33.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-attr1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr92524.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/var-templ64.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/bool-increment1.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/class-deduction46.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/class-deduction-alias1.C27
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/class-deduction-alias2.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-alias.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-alias3.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-alias4.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat3.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-requires2.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-requires20.C65
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/explicit11.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C4
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/base-operand-non-pointer-1.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/bitfield3.C4
-rw-r--r--gcc/testsuite/g++.dg/expr/bitfield4.C4
-rw-r--r--gcc/testsuite/g++.dg/expr/bitfield5.C4
-rw-r--r--gcc/testsuite/g++.dg/expr/bitfield6.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/bool1.C8
-rw-r--r--gcc/testsuite/g++.dg/expr/bool2.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/bool3.C8
-rw-r--r--gcc/testsuite/g++.dg/expr/bool4.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/lval3.C2
-rw-r--r--gcc/testsuite/g++.dg/expr/string-2.C2
-rw-r--r--gcc/testsuite/g++.dg/gomp/openmp-simd-2.C2
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr92697.C51
-rw-r--r--gcc/testsuite/g++.dg/lto/inline-crossmodule-1.h15
-rw-r--r--gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C11
-rw-r--r--gcc/testsuite/g++.dg/lto/inline-crossmodule-1_1.C8
-rw-r--r--gcc/testsuite/g++.dg/lto/pr91574_0.C23
-rw-r--r--gcc/testsuite/g++.dg/lto/pr92476_0.C20
-rw-r--r--gcc/testsuite/g++.dg/lto/pr92476_1.C13
-rw-r--r--gcc/testsuite/g++.dg/lto/pr92609_0.C88
-rw-r--r--gcc/testsuite/g++.dg/lto/pr92609_1.C58
-rw-r--r--gcc/testsuite/g++.dg/opt/pr92644.C6
-rw-r--r--gcc/testsuite/g++.dg/other/error18.C2
-rw-r--r--gcc/testsuite/g++.dg/other/ptrmem5.C2
-rw-r--r--gcc/testsuite/g++.dg/pr53055.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wenum-compare.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wpointer-arith-1.C4
-rw-r--r--gcc/testsuite/g++.dg/warn/inline3.C20
-rw-r--r--gcc/testsuite/g++.old-deja/g++.benjamin/14664-1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.benjamin/14664-2.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/init12.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900212_01.C16
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900213_02.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900215_02.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900324_04.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.bugs/900428_02.C16
-rw-r--r--gcc/testsuite/g++.old-deja/g++.ext/array1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/rfg14.C10
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/rfg17.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/badarrow.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/deref1.C8
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/overload11.C20
-rw-r--r--gcc/testsuite/gcc.dg/c2x-no-dfp-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/fltconst-pedantic-dfp.c3
-rw-r--r--gcc/testsuite/gcc.dg/gnu2x-attrs-1.c3
-rw-r--r--gcc/testsuite/gcc.dg/gnu2x-attrs-2.c33
-rw-r--r--gcc/testsuite/gcc.dg/gnu2x-builtins-no-dfp-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/ipa/ipa-clone-2.c47
-rw-r--r--gcc/testsuite/gcc.dg/pr92510.c16
-rw-r--r--gcc/testsuite/gcc.dg/strcmpopt_8.c177
-rw-r--r--gcc/testsuite/gcc.dg/strcmpopt_9.c34
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr92690.c38
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr92704.c24
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr92715.c17
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-10.c10
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c3
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/inline-12.c22
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr92712-1.c21
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr92712-2.c66
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr92712-3.c36
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-43.c17
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr92596.c14
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr92677.c26
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr92710.c12
-rw-r--r--gcc/testsuite/gcc.dg/vect/slp-reduc-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bool-cmp-2.c10
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c217
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c217
-rw-r--r--gcc/testsuite/gcc.target/arm/asm-flag-4.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/pr32219-2.c9
-rw-r--r--gcc/testsuite/gcc.target/i386/pr90007.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92645-2.c34
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92645-3.c37
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92645-4.c56
-rw-r--r--gcc/testsuite/gcc.target/i386/pr92645.c36
-rw-r--r--gcc/testsuite/gcc.target/nios2/pr92499-1.c48
-rw-r--r--gcc/testsuite/gcc.target/nios2/pr92499-2.c45
-rw-r--r--gcc/testsuite/gcc.target/nios2/pr92499-3.c23
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr72804.c19
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr92398.h17
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr92398.p9+.c12
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr92398.p9-.c10
-rw-r--r--gcc/testsuite/gfortran.dg/dec-comparison.f903
-rw-r--r--gcc/testsuite/gfortran.dg/dependency_56.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_zero_width.f9020
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/common-block-3.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/goacc/pr84963.f902
-rw-r--r--gcc/testsuite/gfortran.dg/loop_versioning_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/loop_versioning_10.f902
-rw-r--r--gcc/testsuite/gfortran.dg/loop_versioning_6.f906
-rw-r--r--gcc/testsuite/gfortran.dg/pr91003.f9033
-rw-r--r--gcc/testsuite/gfortran.dg/pr92629.f9011
-rw-r--r--gcc/testsuite/gfortran.dg/spread_size_limit_2.f9011
-rw-r--r--gcc/testsuite/lib/target-supports.exp32
-rw-r--r--gcc/testsuite/objc.dg/attributes/gnu2x-attr-syntax-1.m5
-rw-r--r--gcc/tree-cfg.c6
-rw-r--r--gcc/tree-core.h3
-rw-r--r--gcc/tree-if-conv.c9
-rw-r--r--gcc/tree-inline.c49
-rw-r--r--gcc/tree-ssa-forwprop.c246
-rw-r--r--gcc/tree-ssa-phiopt.c9
-rw-r--r--gcc/tree-ssa-sccvn.c13
-rw-r--r--gcc/tree-ssa-strlen.c72
-rw-r--r--gcc/tree-vect-generic.c16
-rw-r--r--gcc/tree-vect-loop.c43
-rw-r--r--gcc/tree-vect-patterns.c282
-rw-r--r--gcc/tree-vect-slp.c90
-rw-r--r--gcc/tree-vect-stmts.c340
-rw-r--r--gcc/tree-vectorizer.h30
-rw-r--r--gcc/tree.c84
-rw-r--r--gcc/tree.h4
-rw-r--r--gcc/ubsan.c6
-rw-r--r--gcc/varasm.c17
-rw-r--r--gcc/varpool.c5
-rw-r--r--libcc1/ChangeLog5
-rw-r--r--libcc1/libcp1plugin.cc3
-rw-r--r--libgfortran/ChangeLog14
-rw-r--r--libgfortran/io/format.c14
-rw-r--r--libgfortran/io/write_float.def2
-rw-r--r--libgomp/ChangeLog21
-rw-r--r--libgomp/testsuite/lib/libgomp.exp21
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-20.C54
-rw-r--r--libgomp/testsuite/libgomp.c++/udr-21.C54
-rw-r--r--libgomp/testsuite/libgomp.fortran/target-print-1-nvptx.f9011
-rw-r--r--libgomp/testsuite/libgomp.fortran/target-print-1.f906
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/declare-5.f9090
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/print-1-nvptx.f9011
-rw-r--r--libgomp/testsuite/libgomp.oacc-fortran/print-1.f906
-rw-r--r--libobjc/ChangeLog4
-rw-r--r--libobjc/Makefile.in2
-rw-r--r--libsanitizer/ChangeLog7
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp8
-rw-r--r--libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h15
-rw-r--r--libstdc++-v3/ChangeLog117
-rw-r--r--libstdc++-v3/acinclude.m43
-rwxr-xr-xlibstdc++-v3/configure3
-rw-r--r--libstdc++-v3/include/bits/c++config2
-rw-r--r--libstdc++-v3/include/bits/fs_path.h359
-rw-r--r--libstdc++-v3/include/bits/iterator_concepts.h5
-rw-r--r--libstdc++-v3/include/bits/stl_iterator.h695
-rw-r--r--libstdc++-v3/include/debug/array5
-rw-r--r--libstdc++-v3/include/debug/helper_functions.h4
-rw-r--r--libstdc++-v3/include/debug/safe_iterator.h4
-rw-r--r--libstdc++-v3/include/experimental/bits/fs_path.h369
-rw-r--r--libstdc++-v3/include/std/ostream94
-rw-r--r--libstdc++-v3/python/libstdcxx/v6/printers.py138
-rw-r--r--libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc160
-rw-r--r--libstdc++-v3/testsuite/24_iterators/counted_iterator/1.cc101
-rw-r--r--libstdc++-v3/testsuite/24_iterators/move_iterator/cust.cc50
-rw-r--r--libstdc++-v3/testsuite/24_iterators/move_iterator/sentinel.cc91
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/char/deleted.cc43
-rw-r--r--libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/wchar_t/deleted.cc43
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path-char8_t.cc60
-rw-r--r--libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path.cc17
-rw-r--r--libstdc++-v3/testsuite/experimental/feat-char8_t.cc4
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path-char8_t.cc52
-rw-r--r--libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path.cc8
-rw-r--r--libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc2
-rw-r--r--libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc53
317 files changed, 10923 insertions, 4222 deletions
diff --git a/ChangeLog b/ChangeLog
index 47672e4fae6..cedd89b9be8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2019-11-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR middle-end/92463
+ * configure.ac: Use MPFR_RNDN instead of GMP's MP_RNDN.
+ * configure: Regenerate
+
2019-11-20 Janne Blomqvist <jb@gcc.gnu.org>
* configure.ac: Use https for gcc.gnu.org.
@@ -14,9 +20,9 @@
2019-11-11 Janne Blomqvist <jb@gcc.gnu.org>
- PR fortran/91828
- * configure.ac: Bump minimum MPFR to 3.1.0, recommended to 3.1.6+.
- * configure: Regenerated.
+ PR fortran/91828
+ * configure.ac: Bump minimum MPFR to 3.1.0, recommended to 3.1.6+.
+ * configure: Regenerated.
2019-10-21 Jason Merrill <jason@redhat.com>
diff --git a/ChangeLog.coroutines b/ChangeLog.coroutines
index 4bc887a5224..16fb1bf359d 100644
--- a/ChangeLog.coroutines
+++ b/ChangeLog.coroutines
@@ -1,3 +1,7 @@
+2019-12-02 Iain Sandoe <iain@sandoe.co.uk>
+
+ Merge trunk r278894.
+
2019-12-01 Iain Sandoe <iain@sandoe.co.uk>
gcc/
diff --git a/configure b/configure
index 00f7487e2e9..f6027397ced 100755
--- a/configure
+++ b/configure
@@ -5865,9 +5865,9 @@ main ()
int t;
mpfr_init (n);
mpfr_init (x);
- mpfr_atan2 (n, n, x, GMP_RNDN);
- mpfr_erfc (n, x, GMP_RNDN);
- mpfr_subnormalize (x, t, GMP_RNDN);
+ mpfr_atan2 (n, n, x, MPFR_RNDN);
+ mpfr_erfc (n, x, MPFR_RNDN);
+ mpfr_subnormalize (x, t, MPFR_RNDN);
mpfr_clear(n);
mpfr_clear(x);
mpc_init2 (c, 53);
diff --git a/configure.ac b/configure.ac
index 29e25f13278..50e2fa135b1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1641,9 +1641,9 @@ if test -d ${srcdir}/gcc && test "x$have_gmp" = xno; then
int t;
mpfr_init (n);
mpfr_init (x);
- mpfr_atan2 (n, n, x, GMP_RNDN);
- mpfr_erfc (n, x, GMP_RNDN);
- mpfr_subnormalize (x, t, GMP_RNDN);
+ mpfr_atan2 (n, n, x, MPFR_RNDN);
+ mpfr_erfc (n, x, MPFR_RNDN);
+ mpfr_subnormalize (x, t, MPFR_RNDN);
mpfr_clear(n);
mpfr_clear(x);
mpc_init2 (c, 53);
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 5364edc92f6..9b324211554 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,771 @@
+2019-12-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/92712
+ * match.pd ((A * B) +- A -> (B +- 1) * A,
+ A +- (A * B) -> (1 +- B) * A): Allow optimizing signed integers
+ even when we don't know anything about range of A, but do know
+ something about range of B and the simplification won't introduce
+ new UB.
+
+2019-12-02 Feng Xue <fxue@os.amperecomputing.com>
+
+ PR ipa/92133
+ * doc/invoke.texi (ipa-cp-max-recursive-depth): Document new option.
+ (ipa-cp-min-recursive-probability): Likewise.
+ * params.opt (ipa-cp-max-recursive-depth): New.
+ (ipa-cp-min-recursive-probability): Likewise.
+ * ipa-cp.c (ipcp_lattice<valtype>::add_value): Add two new parameters
+ val_p and unlimited.
+ (self_recursively_generated_p): New function.
+ (get_val_across_arith_op): Likewise.
+ (propagate_vals_across_arith_jfunc): Add constant propagation for
+ self-recursive function.
+ (incorporate_penalties): Do not penalize pure self-recursive function.
+ (good_cloning_opportunity_p): Dump node_is_self_scc flag.
+ (propagate_constants_topo): Set node_is_self_scc flag for cgraph node.
+ (get_info_about_necessary_edges): Relax hotness check for edge to
+ self-recursive function.
+ * ipa-prop.h (ipa_node_params): Add new field node_is_self_scc.
+
+2019-12-01 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR target/92499
+
+ * config/nios2/nios2.c (nios2_in_small_data_p): Do not consider
+ objects of flexible types to be small if they have internal linkage
+ or are declared extern.
+ * config/nios2/nios2.h (ASM_OUTPUT_ALIGNED_LOCAL): Replace with...
+ (ASM_OUTPUT_ALIGNED_DECL_LOCAL): ...this. Use targetm.in_small_data_p
+ instead of the size of the object initializer.
+ * tree.c (flexible_array_type_p): Move from C front end, and
+ generalize to handle fields in non-C structures.
+ * tree.h (flexible_array_type_p): Declare.
+
+2019-11-30 Jan Hubicka <hubicka@ucw.cz>
+
+ * profile-count.h (profile_count::operator<): Use IPA value for
+ comparsion.
+ (profile_count::operator>): Likewise.
+ (profile_count::operator<=): Likewise.
+ (profile_count::operator>=): Likewise.
+ * predict.c (maybe_hot_count_p): Do not convert to gcov_type.
+
+2019-11-30 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-inline.c (compute_max_insns): Return int64_t.
+ (inline_small_functions): Simplify.
+
+2019-11-30 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-cfg.c (execute_fixup_cfg): Update also max_bb_count when
+ scaling happen.
+
+2019-11-30 Jan Hubicka <hubicka@ucw.cz>
+
+ * cgraph.h (symtab_node): Add symver flag.
+ * cgraphunit.c (process_symver_attribute): New.
+ (process_common_attributes): Use process_symver_attribute.
+ * lto-cgraph.c (lto_output_node): Stream symver.
+ (lto_output_varpool_node): Stream symver.
+ (input_overwrite_node): Stream symver.
+ (input_varpool_node): Stream symver.
+ * output.h (do_assemble_symver): Decalre.
+ * symtab.c (symtab_node::dump_base): Dump symver.
+ (symtab_node::verify_base): Verify symver.
+ (symtab_node::resolve_alias): Handle symver.
+ * varasm.c (do_assemble_symver): New function.
+ * varpool.c (varpool_node::assemble_aliases): Use it.
+ * doc/extend.texi: (symver attribute): Document.
+ * config/elfos.h (ASM_OUTPUT_SYMVER_DIRECTIVE): New.
+
+2019-11-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ * target.h (type_context_kind): New enum.
+ (verify_type_context): Declare.
+ * target.def (verify_type_context): New target hook.
+ * doc/tm.texi.in (TARGET_VERIFY_TYPE_CONTEXT): Likewise.
+ * doc/tm.texi: Regenerate.
+ * tree.c (verify_type_context): New function.
+ * config/aarch64/aarch64-protos.h (aarch64_sve::verify_type_context):
+ Declare.
+ * config/aarch64/aarch64-sve-builtins.cc (verify_type_context):
+ New function.
+ * config/aarch64/aarch64.c (aarch64_verify_type_context): Likewise.
+ (TARGET_VERIFY_TYPE_CONTEXT): Define.
+
+2019-11-30 Jan Hubicka <hubicka@ucw.cz>
+
+ * cgraph.c (cgraph_node::dump): Dump unit_id and merged_extern_inline.
+ * cgraph.h (cgraph_node): Add unit_id and
+ merged_extern_inline.
+ (symbol_table): Add max_unit.
+ (symbol_table::symbol_table): Initialize it.
+ * cgraphclones.c (duplicate_thunk_for_node): Copy unit_id.
+ merged_comdat, merged_extern_inline.
+ (cgraph_node::create_clone): Likewise.
+ (cgraph_node::create_version_clone): Likewise.
+ * ipa-fnsummary.c (dump_ipa_call_summary): Dump info about cross module
+ calls.
+ * ipa-fnsummary.h (cross_module_call_p): New inline function.
+ * ipa-inline-analyssi.c (simple_edge_hints): Use it.
+ * ipa-inline.c (inline_small_functions): Likewise.
+ * lto-symtab.c (lto_cgraph_replace_node): Record merged_extern_inline;
+ copy merged_comdat and merged_extern_inline.
+ * lto-cgraph.c (lto_output_node): Stream out merged_comdat,
+ merged_extern_inline and unit_id.
+ (input_overwrite_node): Stream in these.
+ (input_cgraph_1): Set unit_base.
+ * lto-streamer.h (lto_file_decl_data): Add unit_base.
+ * symtab.c (symtab_node::make_decl_local): Record former_comdat.
+
+2019-11-30 Maciej W. Rozycki <macro@wdc.com>
+
+ * gcc.c (process_command): Only warn about an ineffective `-x'
+ option if any input files have actually been supplied.
+
+2019-11-30 Maciej W. Rozycki <macro@wdc.com>
+
+ * doc/install.texi (Options specification): Remove the list of
+ target library subdirectories supporting
+ `--enable-version-specific-runtime-libs'. Document defaults for
+ the option.
+
+2019-11-29 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/92283
+ * lra.c (lra): Update reg notes after inheritance sub-pass and
+ before constraint sub-pass.
+
+2019-11-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/91003
+ * tree-vect-slp.c (vect_mask_constant_operand_p): Pass in the
+ operand number, avoid handling the non-condition operands of
+ COND_EXPRs as comparisons.
+ (vect_get_constant_vectors): Pass down the operand number.
+ (vect_get_slp_defs): Likewise.
+
+2019-11-29 Frederik Harwath <frederik@codesourcery.com>
+
+ * gimple-match-head.c (maybe_resimplify_conditional_op): Use
+ generic_expr_could_trap_p to check if the condition of COND_EXPR or
+ VEC_COND_EXPR can trap.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/92677
+ * tree-vect-loop.c (vect_dissolve_slp_only_groups): Set the gap
+ to zero when dissolving a group of strided accesses.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/92596
+ * tree-vect-stmts.c (vectorizable_call): Punt on hybrid mask/nonmask
+ operations.
+ (vectorizable_operation): Likewise, instead of relying on
+ vect_get_mask_type_for_stmt to do this.
+ (vect_get_vector_types_for_stmt): Always return a vector type
+ immediately, rather than deferring the choice for boolean results.
+ Use a vector mask type instead of a normal vector if
+ vect_use_mask_type_p.
+ (vect_get_mask_type_for_stmt): Delete.
+ * tree-vect-loop.c (vect_determine_vf_for_stmt_1): Remove
+ mask_producers argument and special boolean_type_node handling.
+ (vect_determine_vf_for_stmt): Remove mask_producers argument and
+ update calls to vect_determine_vf_for_stmt_1. Remove doubled call.
+ (vect_determine_vectorization_factor): Update call accordingly.
+ * tree-vect-slp.c (vect_build_slp_tree_1): Remove special
+ boolean_type_node handling.
+ (vect_slp_analyze_node_operations_1): Likewise.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (stmt_vec_info::mask_precision): New field.
+ (vect_use_mask_type_p): New function.
+ * tree-vect-patterns.c (vect_init_pattern_stmt): Copy the
+ mask precision to the pattern statement.
+ (append_pattern_def_seq): Add a scalar_type_for_mask parameter
+ and use it to initialize the new stmt's mask precision.
+ (search_type_for_mask_1): Delete.
+ (search_type_for_mask): Replace with...
+ (integer_type_for_mask): ...this new function. Use the information
+ cached in the stmt_vec_info.
+ (vect_recog_bool_pattern): Update accordingly.
+ (build_mask_conversion): Pass the scalar type associated with the
+ mask type to append_pattern_def_seq.
+ (vect_recog_mask_conversion_pattern): Likewise. Call
+ integer_type_for_mask instead of search_type_for_mask.
+ (vect_convert_mask_for_vectype): Call integer_type_for_mask instead
+ of search_type_for_mask.
+ (possible_vector_mask_operation_p): New function.
+ (vect_determine_mask_precision): Likewise.
+ (vect_determine_stmt_precisions): Call it.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vectorizer.h (get_mask_type_for_scalar_type): Replace
+ the slp_tree parameter with a group size parameter.
+ (vect_get_mask_type_for_stmt): Likewise.
+ * tree-vect-stmts.c (get_mask_type_for_scalar_type): Likewise.
+ (vect_get_mask_type_for_stmt): Likewise.
+ * tree-vect-slp.c (vect_slp_analyze_node_operations_1): Update
+ call accordingly.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ * tree-vect-stmts.c (vectorizable_operation): Punt early
+ on codes that are handled elsewhere.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ * doc/sourcebuild.texi (vect_bool_cmp): Document.
+ * tree-vect-patterns.c (search_type_for_mask_1): If neither
+ operand to a boolean comparison is a natural vector mask,
+ handle both operands like normal integers instead.
+
+2019-11-29 Richard Biener <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (vn_walk_cb_data::push_partial_def): Bail
+ out early for too large objects.
+
+2019-11-29 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/92476
+ * ipa-cp.c (set_single_call_flag): Set node_calling_single_call in
+ the summary only if the summary exists.
+ (find_more_scalar_values_for_callers_subset): Check node_dead in
+ the summary only if the summary exists.
+ (ipcp_store_bits_results): Ignore nodes without lattices.
+ (ipcp_store_vr_results): Likewise.
+ * cgraphclones.c: Include ipa-fnsummary.h and ipa-prop.h and the
+ header files required by them.
+ (cgraph_node::expand_all_artificial_thunks): Analyze expanded thunks.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/92710
+ * tree-vect-stmts.c (vectorizable_simd_clone_call): Reject
+ vector mask arguments.
+
+2019-11-29 Jan Hubicka <hubicka@ucw.cz>
+
+ * profile-count.c (profile_count::to_cgraph_frequency,
+ profile_count::to_sreal_scale): Check for compaibility of counts.
+ * profile-count.h (compatible_p): Make public; add checking for
+ global0 versus global types.
+ * cgraph.c (cgraph_node::verify_node): Verify count compatibility.
+
+2019-11-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92715
+ * tree-ssa-forwprop.c (simplify_vector_constructor): Bail
+ out for uniform vectors and source vectors with less elements
+ than the destination.
+
+2019-11-29 Martin Liska <mliska@suse.cz>
+
+ PR lto/91574
+ * ipa-devirt.c (types_same_for_odr): Check for existence
+ of TYPE_NAMEs first.
+
+2019-11-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92704
+ * tree-if-conv.c (combine_blocks): Deal with virtual PHIs
+ in loops performing only loads.
+
+2019-11-29 Julian Brown <julian@codesourcery.com>
+
+ * builtin-types.def (BT_DFLOAT32_PTR, BT_DFLOAT64_PTR,
+ BT_DFLOAT128_PTR) Remove.
+ * tree-core.h (TI_DFLOAT32_PTR_TYPE, TI_DFLOAT64_PTR_TYPE,
+ TI_DFLOAT128_PTR_TYPE): Remove.
+ * tree.c (build_common_type_nodes): Remove dfloat32_ptr_type_node,
+ dfloat64_ptr_type_node and dfloat128_ptr_type_node initialisation.
+ * tree.h (dfloat32_ptr_type_node, dfloat64_ptr_type_node,
+ dfloat128_ptr_type_node): Remove macros.
+
+2019-11-28 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (*movsi_internal1): Fix formatting. Improve
+ formatting.
+ (*movdi_internal64): Ditto.
+
+2019-11-28 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/92602
+ * config/rs6000/rs6000.md (bswap<mode>2_load for HSI): Change the
+ indexed_or_indirect_operand to be memory_operand.
+ (bswap<mode>2_store for HSI): Ditto.
+ (bswapdi2_load): Ditto.
+ (bswapdi2_store): Ditto.
+
+2019-11-28 Martin Liska <mliska@suse.cz>
+
+ PR debug/46558
+ * dbgcnt.c (dbg_cnt_list_all_counters): Mark table
+ headers for translation.
+
+2019-11-28 Martin Liska <mliska@suse.cz>
+
+ PR lto/92609
+ * ipa-devirt.c (warn_types_mismatch): Use TYPE_MAIN_VARIANT
+ consistently.
+
+2019-11-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-inline.c (want_early_inline_function_p): Remove leftover optimize
+ checks.
+
+2019-11-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * profile-count.c (profile_count::combine_with_ipa_count): Return
+ uninitialized count if called on ininitialized count.
+
+2019-11-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-inline-transform.c (inline_transform): Scale profile before
+ redirecting.
+
+2019-11-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * profile-count.h (profile_count::max): Work on profiles of different
+ type.
+ (profile_count::apply_scale): Be sure that ret is not local or global0
+ type if num is global.
+
+2019-11-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * profile-count.h (profile_count::max): Work on profiles of different
+ type.
+ (profile_count::apply_scale): Be sure that ret is not local or global0
+ type if num is global.
+
+2019-11-28 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/92697
+ * cgraph.c (cgraph_node_cannot_be_local_p_1): Return true for
+ ifunc_resolvers.
+ * symtab.c (symtab_node::dump_base): Dump ifunc_resolver flag.
+ Removed trailig whitespace.
+
+2019-11-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * profile-count.h (profile_count::combine_with_ipa_count_within):
+ Declare.
+ * profile-count.c (profile_count::combine_with_ipa_count_within):
+ New.
+ * cgraphclones.c (cgraph_edge::clone, cgraph_node::create_clone): Use
+ it.
+
+2019-11-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-utils.c (ipa_merge_profiles): Be sure that all type transtions
+ of counters are done same way.
+
+2019-11-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-cp.c (update_profiling_info): Fix scaling.
+
+2019-11-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92645
+ * tree-inline.c (remap_gimple_stmt): When the return value
+ is not wanted, elide GIMPLE_RETURN.
+
+2019-11-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92645
+ * tree-ssa-forwprop.c (get_bit_field_ref_def): Also handle
+ conversions inside a mode class. Remove restriction on
+ preserving the element size.
+ (simplify_vector_constructor): Deal with the above and for
+ identity permutes also try using VEC_UNPACK_[FLOAT_]LO_EXPR
+ and VEC_PACK_TRUNC_EXPR.
+
+2019-11-28 Georg-Johann Lay <avr@gjlay.de>
+
+ Must use push insn to pass varargs arguments of DFmode because
+ otherwise the middle-end generates wrong code.
+
+ PR target/92055
+ * config/avr/avr.md (MPUSH) [DF, DC]: Add modes to mode iterator.
+
+2019-11-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/92691
+ * tree-ssa-strlen.c (handle_store): Clarify return value meaning
+ in function comment.
+ (strlen_check_and_optimize_call): Likewise. For handle_printf_call
+ calls, return !handle_printf_call rather than always returning true.
+ (check_and_optimize_stmt): Describe return value meaning in function
+ comment. Formatting fix.
+
+2019-11-28 Jan Hubicka <hubicka@ucw.cz>
+
+ * profile-count.c (profile_count::to_sreal_scale): Handle correctly
+ combination of globa0 and global counters..
+
+2019-11-28 Kewen Lin <linkw@gcc.gnu.org>
+
+ PR target/92566
+ * gcc/config/rs6000/rs6000.c (rs6000_preferred_simd_mode): Check
+ by VECTOR_UNIT_NONE_P instead.
+
+2019-11-28 Hongtao Liu <hongtao.liu@inte.com>
+
+ * gcc/config/i386/sse.md (avx512f_maskcmp<mode>3):
+ Refine VF to VF_AVX512VL.
+
+2019-11-27 Michael Meissner <meissner@linux.ibm.com>
+
+ * config/rs6000/rs6000.md (movsi_internal): Reformat.
+ (movdi_internal64): Reformat.
+
+2019-11-27 Peter Bergner <bergner@linux.ibm.com>
+
+ PR bootstrap/92661
+ * config/rs6000/rs6000-call.c: (def_builtin): Do not define the
+ builtin if we don't have an actual type.
+ (builtin_function_type): If the builtin function uses a DFP type
+ and decimal float has been disabled, then return NULL_TREE.
+
+2019-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/92510
+ * combine.c (gen_lowpart_for_combine): Only transform lowpart subreg
+ of comparison into a comparison with different mode if both imode and
+ omode are scalar integral modes.
+
+2019-11-27 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/90007
+ * recog.c (constrain_operands): Permit hard registers too for
+ memory when LRA is used.
+
+2019-11-27 Bernd Schmidt <bernds_cb1@t-online.de>
+
+ * config/m68k/m68k.c (m68k_output_compare_fp): Restore differences
+ between Coldfire and regular m68k.
+ * config/m68k/m68k.md (cmp1_cf_constraints): Disallow constants.
+
+2019-11-27 Richard Biener <rguenther@suse.de>
+
+ * target.def (TARGET_VECTORIZE_BUILTIN_CONVERSION): Remove.
+ * targhooks.c (default_builtin_vectorized_conversion): Likewise.
+ * targhooks.h (default_builtin_vectorized_conversion): Likewise.
+ * optabs-tree.c (supportable_convert_operation): Do not call
+ targetm.vectorize.builtin_conversion. Remove unused decl parameter.
+ * optabs-tree.h (supportable_convert_operation): Adjust.
+ * doc/tm.texi.in (TARGET_VECTORIZE_BUILTIN_CONVERSION): Remove.
+ * doc/tm.texi: Regenerate.
+ * tree-ssa-forwprop.c (simplify_vector_constructor): Adjust.
+ * tree-vect-generic.c (expand_vector_conversion): Likewise.
+ * tree-vect-stmts.c (vect_gen_widened_results_half): Remove
+ unused decl parameter and adjust.
+ (vect_create_vectorized_promotion_stmts): Likewise.
+ (vectorizable_conversion): Adjust.
+
+2019-11-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92690
+ * tree-ssa-forwprop.c (simplify_vector_constructor): Avoid
+ converting elements not originally converted.
+
+2019-11-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR middle-end/92463
+ * builtins.c (do_mpfr_ckconv, do_mpc_ckconv, do_mpfr_remquo,
+ do_mpfr_lgamma_r, do_mpc_arg2): Use MPFR_RNDx instead of GMP_RNDx,
+ mpfr_rnd_t instead of mp_rnd_t.
+ * fold-const-call.c (do_mpfr_ckconv, do_mpfr_arg1, do_mpfr_sincos,
+ do_mpfr_arg2, do_mpfr_arg3, do_mpc_arg1, do_mpc_arg2): Likewise.
+ * gimple-ssa-sprintf.c (format_floating_max, format_floating):
+ Use mpfr_exp_t instead of mp_exp_t.
+ * real.c (real_from_string, dconst_e_ptr, dconst_sqrt2_ptr): Use
+ MPFR_RNDx instead of GMP_RNDx.
+ * realmpfr.c (real_from_mpfr, mpfr_from_real): Use mpfr_rnd_t and
+ mpfr_exp_t instead mp_rnd_t and mp_exp_t, respectively.
+ * realmpfr.h (real_from_mpfr, mpfr_from_real): Use mpfr_rnd_t instead
+ of mp_rnd_t and remove MPFR_RNDx poisoning.
+ * ubsan.c (ubsan_instrument_float_cast): MPFR_RNDx instead of GMP_RNDx.
+
+2019-11-27 Kewen Lin <linkw@gcc.gnu.org>
+
+ PR tree-optimization/91790
+ * gcc/tree-vect-stmts.c (vectorizable_load): Use the adjusted
+ DR for vect_setup_realignment when first_stmt_info is different
+ from first_stmt_info_for_drptr.
+
+2019-11-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92645
+ * tree-ssa-forwprop.c (simplify_vector_constructor): Handle
+ CTORs with just a subset of the original vectors.
+
+2019-11-27 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/92674
+ * tree-inline.c (expand_call_inline): Delay purging EH/abnormal
+ edges and instead record blocks in bitmap.
+ (gimple_expand_calls_inline): Adjust.
+ (fold_marked_statements): Delay EH cleanup until all folding is
+ done.
+ (optimize_inline_calls): Do EH/abnormal cleanup for calls after
+ inlining finished.
+
+2019-11-27 Bernd Schmidt <bernds_cb1@t-online.de>
+
+ * auto-inc-dec.c (merge_in_block): Allow autoinc in jumps unless
+ LRA is enabled.
+ * combine.c (can_combine_p): Disallow autoinc in jumps unless LRA is
+ disabled.
+
+2019-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/92664
+ * dwarf2out.c (lookup_filename): Use "<stdin>" instead of "".
+
+2019-11-26 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/92683
+ * gimple-fold.c (gimple_fold_builtin_string_compare): Restore a test
+ inadvertently removed in a previous change. Rename local variable
+ for clarity.
+
+2019-11-26 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/92669
+ * cfganal.c (pre_and_rev_post_order_compute_fn): Deal with
+ NULL pre_order.
+
+2019-11-26 Robin Dapp <rdapp@linux.ibm.com>
+
+ * config/s390/linux.h: Add undef for MUSL_DYNAMIC_LINKERxx.
+
+2019-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/92644
+ * tree-ssa-phiopt.c (minmax_replacement): Add INTEGRAL_TYPE_P check
+ next to INTEGER_CST checks.
+
+2019-11-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92645
+ * tree-vect-slp.c (vect_build_slp_tree_2): For unary ops
+ do not build the operation from scalars if the operand is.
+
+2019-11-25 Tobias Burnus <tobias@codesourcery.com>
+
+ * config/gcn/mkoffload.c (COMMENT_PREFIX, struct id_map,
+ func_ids, funcs_tail, var_ids, vars_tail) Remove unused
+ definitions.
+
+2019-11-25 Martin Liska <mliska@suse.cz>
+
+ * ipa-icf.c (sem_item_optimizer::dump_cong_classes): Clean
+ up used dump message.
+
+2019-11-25 Martin Liska <mliska@suse.cz>
+
+ PR bootstrap/92653
+ * ipa-fnsummary.c (ipa_fn_summary::account_size_time): Comment out
+ too strict checking assert.
+
+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/91985
+ * builtin-types.def (BT_DFLOAT32, BT_DFLOAT64, BT_DFLOAT128)
+ (BT_DFLOAT32_PTR, BT_DFLOAT64_PTR, BT_DFLOAT128_PTR): Define to
+ error_mark_node if corresponding global tree node is NULL.
+ * tree.c (build_common_tree_nodes): Do not initialize
+ dfloat32_type_node, dfloat64_type_node or dfloat128_type_node if
+ decimal floating-point not supported.
+
+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ * attribs.c (decl_attributes): Do not ignore C++11 attributes on
+ types.
+
+2019-11-25 Bernd Schmidt <bernds_cb1@t-online.de>
+
+ * config/m68k/m68k.c (output_move_himode, output_move_qimode):
+ Replace code for non-CONST_INT constants with gcc_unreachable.
+ * config/m68k/m68k.md (cbranchdi): Don't generate individual
+ compare and test.
+ (CMPMODE): New mode_iterator.
+ (cbranchsi4, cbranchqi4, cbranchhi4): Replace expanders with
+ cbranch<mode>4.
+ (cstoresi4, cstoreqi4, cstorehi4): Replace expanders with
+ cstore<mode>4.
+ (cmp<mode>_68881): Remove 'F' constraint from first comparison
+ operand.
+ (bit test insns patterns): Use nonimmediate_operand, not
+ register_operand, for source operands that allow memory in
+ their constraints.
+ (divmodsi4, udivmodsi4, divmodhi4 and related unnamed patterns):
+ Use register_operand, not nonimmediate_operand, for the
+ destinations.
+ (DBCC): New mode_iterator.
+ (dbcc peepholes): Use it to reduce duplication.
+ (trap): Use const_true_rtx, not const1_rtx.
+ * config/m68k/predicates.md (m68k_comparison_operand): Renamed
+ from m68k_subword_comparison_operand and changed to handle
+ SImode.
+
+ PR target/91851
+ * config/m68k/m68k-protos.h (output-dbcc_and_branch): Adjust
+ declaration.
+ (m68k_init_cc): New declaration.
+ (m68k_output_compare_di, m68k_output_compare_si)
+ (m68k_output_compare_hi, m68k_output_compare_qi)
+ (m68k_output_compare_fp, m68k_output_btst, m68k_output_bftst)
+ (m68k_find_flags_value, m68k_output_scc, m68k_output_scc_float)
+ (m68k_output_branch_integer, m68k_output_branch_integer_rev.
+ m68k_output_branch_float, m68k_output_branch_float_rev):
+ Likewise.
+ (valid_dbcc_comparison_p_2, flags_in_68881)
+ (output_btst): Remove declaration.
+ * config/m68k/m68k.c (INCLDUE_STRING): Define.
+ (TARGET_ASM_FINAL_POSTSCAN_INSN): Define.
+ (valid_dbcc_comparison_p_2, flags_in_68881): Delete functions.
+ (flags_compare_op0, flags_compare_op1, flags_operand1,
+ flags_operand2, flags_valid): New static variables.
+ (m68k_find_flags_value, m68k_init_cc): New functions.
+ (handle_flags_for_move, m68k_asm_final_postscan_insn,
+ remember_compare_flags): New static functions.
+ (output_dbcc_and_branch): New argument CODE. Use it, and add
+ PLUS and MINUS to the possible codes. All callers changed.
+ (m68k_output_btst): Renamed from output_btst. Remove OPERANDS
+ and INSN arguments, add CODE arg. Return the comparison code
+ to use. All callers changed. Use CODE instead of
+ next_insn_tests_no_inequality, and replace cc_status management
+ with changing the return code.
+ (m68k_rtx_costs): Instead of testing for COMPARE, test for
+ RTX_COMPARE or RTX_COMM_COMPARE.
+ (output_move_simode, output_move_qimode): Call
+ handle_flags_for_move.
+ (notice_update_cc): Delete function.
+ (m68k_output_bftst, m68k_output_compare_di, m68k_output_compare_si,
+ m68k_output_compare_hi, m68k_output_compare_qi,
+ m68k_output_compare_fp, m68k_output_branch_integer,
+ m68k_output_branch_integer_rev, m68k_output_scc,
+ m68k_output_branch_float, m68k_output_branch_float_rev,
+ m68k_output_scc_float): New functions.
+ (output_andsi3, output_iorsi3, output_xorsi3): Call CC_STATUS_INIT
+ once at the start, and set flags_valid and flags_operand1 if the
+ flags are usable.
+ * config/m68k/m68k.h (CC_IN_68881, NOTICE_UPDATE_CC,
+ CC_OVERFLOW_UNUSABLE, CC_NO_CARRY, OUTPUT_JUMP): Remove
+ definitions.
+ (CC_STATUS_INIT): Define.
+ * config/m68k/m68k.md (flags_valid): New define_attr.
+ (tstdi, tstsi_internal_68020_cf, tstsi_internal, tsthi_internal,
+ tstqi_internal, tst<mode>_68881, tst<mode>_cf, cmpdi_internal,
+ cmpdi, unnamed cmpsi/cmphi/cmpqi patterns, cmpsi_cf,
+ cmp<mode>_68881, cmp<mode>_cf, unnamed btst patterns,
+ tst_bftst_reg, tst_bftst_reg, unnamed scc patterns, scc,
+ sls, sordered_1, sunordered_1, suneq_1, sunge_1, sungt_1,
+ sunle_1, sunlt_1, sltgt_1, fsogt_1, fsoge_1, fsolt_1, fsole_1,
+ bge0_di, blt0_di, beq, bne, bgt, bgtu, blt, bltu, bge, bgeu,
+ ble, bleu, bordered, bunordered, buneq, bunge, bungt, bunle,
+ bunlt, bltgt, beq_rev, bne_rev, bgt_rev, bgtu_rev,
+ blt_rev, bltu_rev, bge_rev, bgeu_rev, ble_rev, bleu_rev,
+ bordered_rev, bunordered_rev, buneq_rev, bunge_rv, bungt_rev,
+ bunle_rev, bunlt_rev, bltgt_rev, ctrapdi4, ctrapsi4, ctraphi4,
+ ctrapqi4, conditional_trap): Delete patterns.
+ (cbranchdi4_insn): New pattern.
+ (cbranchdi4): Don't generate cc0 patterns. When testing LT or GE,
+ test high part only. When testing EQ or NE, generate beq0_di
+ and bne0_di patterns directly.
+ (cstoredi4): When testing LT or GE, test high part only.
+ (both sets of cbranch<mode>4, cstore<mode>4): Don't generate cc0
+ patterns.
+ (scc0_constraints, cmp1_constraints, cmp2_constraints,
+ scc0_cf_constraints, cmp1_cf_constraints, cmp2_cf_constraints,
+ cmp2_cf_predicate): New define_mode_attrs.
+ (cbranch<mode>4_insn, cbranch<mode>4_insn_rev,
+ cbranch<mode>4_insn_cf, cbranch<mode>4_insn_cf_rev,
+ cstore<mode>4_insn, cstore<mode>4_insn_cf for integer modes)
+ New patterns.
+ (cbranch<mode>4_insn_68881, cbranch<mode>4_insn_rev_68881):
+ (cbranch<mode>4_insn_cf, cbranch<mode>4_insn_rev_cf,
+ cstore<mode>4_insn_68881, cstore<mode>4_insn_cf for FP):
+ New patterns.
+ (cbranchsi4_btst_mem_insn, cbranchsi4_btst_reg_insn,
+ cbranchsi4_btst_mem_insn_1, cbranchsi4_btst_reg_insn_1):
+ Likewise.
+ (BTST): New define_mode_iterator.
+ (btst_predicate, btst_constraint, btst_range): New
+ define_mode_attrs.
+ (cbranch_bftst<mode>_insn, cstore_bftst<mode>_insn): New
+ patterns.
+ (movsi_m68k_movsi_m68k2, movsi_cf, unnamed movstrict patterns,
+ unnamed movhi and movqi patterns, unnamed movsf, movdf and movxf
+ patterns): Set attr "flags_valid".
+ (truncsiqi2, trunchiqi2, truncsihi2): Remove manual CC_STATUS
+ management. Set attr "flags_valid".
+ (extendsidi2, extendplussidi, unnamed float_extendsfdf pattern,
+ extendsfdf2_cf, fix_truncdfsi2, fix_truncdfhi2, fix_truncdfqi2,
+ addi_sexthishl32, adddi_dilshr32, adddi_dilshr32_cf,
+ addi_dishl32, subdi_sexthishl32, subdi_dishl32, subdi3): Remove
+ manual CC_STATUS management.
+ (addsi3_internal, addhi3, addqi3, subsi3, subhi3, subqi3,
+ unnamed strict_lowpart subhi and subqi patterns): Set attr
+ "flags_valid".
+ (unnamed strict_lowpart addhi3 and addqi3 patterns): Likewise.
+ Remove code to operate on address regs and assert the case
+ does not occur.
+ (unnamed mulsidi patterns, divmodhi4, udivmodhi4): Remove
+ manual CC_STATUS_INIT.
+ (andsi3_internal, andhi3, andqi3, iorsi3_internal, iorhi3, iorqi3,
+ xorsi3_internal, xorhi3, xorqi3, negsi2_internal,
+ negsi2_5200, neghi2, negqi2, one_cmplsi2_internal, one_cmplhi2,
+ one_cmplqi2, unnamed strict_lowpart patterns
+ for andhi, andqi, iorhi, iorqi, xorhi, xorqi, neghi, negqi,
+ one_cmplhi and one_cmplqi): Set attr "flags_valid".
+ (iorsi_zext_ashl16, iorsi_zext): Remove manual CC_STATUS_INIT.
+ (ashldi_sexthi, ashlsi_16, ashlsi_17_24): Remove manual
+ CC_STATUS_INIT.
+ (ashlsi3, ashlhi3, ashlqi3, ashrsi3, ashrhi3, ashrqi3, lshrsi3,
+ lshrhi3, shrqi3, rotlsi3, rotlhi3, rotlhi3_lowpart, rotlqi3,
+ rotlqi3_lowpart, rotrsi3, rotrhi3, rotrhi_lowpart, rotrqi3,
+ unnamed strict_low_part patterns for HI and
+ QI versions): Set attr "flags_valid".
+ (bsetmemqi, bsetmemqi_ext, bsetdreg, bchgdreg, bclrdreg,
+ bclrmemqi, extzv_8_16_reg, extzv_bfextu_mem, insv_bfchg_mem,
+ insv_bfclr_mem, insv_bfset_mem, extv_bfextu_reg,
+ insv_bfclr_reg, insv_bfset_reg, dbne_hi, dbne_si, dbge_hi,
+ dbge_si, extendsfxf2, extenddfxf2, ): Remove manual cc_status management.
+ (various unnamed peepholes): Adjust compare/branch sequences
+ for new cbranch patterns.
+ (dbcc peepholes): Likewise, and output the comparison here
+ as well.
+ * config/m68k/predicates.md (valid_dbcc_comparison_p): Delete.
+ (fp_src_operand): Allow constant zero.
+ (address_reg_operand): New predicate.
+
+ * rtl.h (inequality_comparisons_p): Remove declaration.
+ * recog.h (next_insn_tests_no_inequality): Likewise.
+ * rtlanal.c (inequality_comparisons_p): Delete function.
+ * recog.c (next_insn_tests_no_inequality): Likewise.
+
+2019-11-25 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-slp.c (vect_detect_hybrid_slp_stmts): Add assertion.
+ (vect_detect_hybrid_slp): Swap lane and instance iteration,
+ properly re-building the visited hash-map for each lane.
+
+2019-11-25 Tobias Burnus <tobias@codesourcery.com>
+
+ * config/gcn/gcn.c (gcn_expand_scalar_to_vector_address,
+ gcn_md_reorg): Remove unused variables.
+ (gcn_emutls_var_init): Add missing (but unreachable) return
+ to silence warning.
+ (gcn_hsa_declare_function_name): Add gcc_unreachable to ensure
+ target != TARGET_GCN3 or TARGET_GCN3 will fail instead of use
+ an uninitialized variable.
+
2019-11-25 Martin Jambor <mjambor@suse.cz>
PR ipa/92109
@@ -79,11 +847,6 @@
(vector_uneq<mode> for VEC_F): Likewise.
(vector_unordered<mode> for VEC_F): Likewise.
-2019-11-24 Jerry DeLisle <jvdelisle@gcc.ngu.org>
-
- PR fortran/92100
- gfortran.dg/streamio_18.f90: New test.
-
2019-11-24 Bernd Schmidt <bernds_cb1@t-online.de>
* config/i386/i386.c (ix86_rtx_costs): Handle care of a PLUS in a
@@ -3789,7 +4552,7 @@
(lto_free_file_name_hash): New function.
* lto-streamer.h (lto_free_file_name_hash): New.
-2019-11-07 Feng Xue <fxue@os.amperecomputing.com>
+2019-11-07 Feng Xue <fxue@os.amperecomputing.com>
PR tree-optimization/89134
* doc/invoke.texi (min-loop-cond-split-prob): Document new --params.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 4cdaeb11554..c42bb22ba20 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20191125
+20191202
diff --git a/gcc/REVISION b/gcc/REVISION
index bca44c88115..561ca1554db 100644
--- a/gcc/REVISION
+++ b/gcc/REVISION
@@ -1 +1 @@
-[c++-coroutines revision 278875]
+[c++-coroutines revision 278884]
diff --git a/gcc/attribs.c b/gcc/attribs.c
index de34918919b..0519f075ece 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -593,21 +593,6 @@ decl_attributes (tree *node, tree attributes, int flags,
}
gcc_assert (is_attribute_p (spec->name, name));
- if (TYPE_P (*node)
- && cxx11_attr_p
- && !(flags & ATTR_FLAG_TYPE_IN_PLACE))
- {
- /* This is a c++11 attribute that appertains to a
- type-specifier, outside of the definition of, a class
- type. Ignore it. */
- auto_diagnostic_group d;
- if (warning (OPT_Wattributes, "attribute ignored"))
- inform (input_location,
- "an attribute that appertains to a type-specifier "
- "is ignored");
- continue;
- }
-
if (spec->decl_required && !DECL_P (*anode))
{
if (flags & ((int) ATTR_FLAG_DECL_NEXT
diff --git a/gcc/auto-inc-dec.c b/gcc/auto-inc-dec.c
index bdb6efab520..1b224cc9777 100644
--- a/gcc/auto-inc-dec.c
+++ b/gcc/auto-inc-dec.c
@@ -1441,10 +1441,9 @@ merge_in_block (int max_reg, basic_block bb)
continue;
}
- /* This continue is deliberate. We do not want the uses of the
- jump put into reg_next_use because it is not considered safe to
- combine a preincrement with a jump. */
- if (JUMP_P (insn))
+ /* Reload should handle auto-inc within a jump correctly, while LRA
+ is known to have issues with autoinc. */
+ if (JUMP_P (insn) && targetm.lra_p ())
continue;
if (dump_file)
diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def
index 6b4875ea0a1..49f5451def7 100644
--- a/gcc/builtin-types.def
+++ b/gcc/builtin-types.def
@@ -136,12 +136,15 @@ DEF_PRIMITIVE_TYPE (BT_WINT, wint_type_node)
DEF_PRIMITIVE_TYPE (BT_STRING, string_type_node)
DEF_PRIMITIVE_TYPE (BT_CONST_STRING, const_string_type_node)
-DEF_PRIMITIVE_TYPE (BT_DFLOAT32, dfloat32_type_node)
-DEF_PRIMITIVE_TYPE (BT_DFLOAT64, dfloat64_type_node)
-DEF_PRIMITIVE_TYPE (BT_DFLOAT128, dfloat128_type_node)
-DEF_PRIMITIVE_TYPE (BT_DFLOAT32_PTR, dfloat32_ptr_type_node)
-DEF_PRIMITIVE_TYPE (BT_DFLOAT64_PTR, dfloat64_ptr_type_node)
-DEF_PRIMITIVE_TYPE (BT_DFLOAT128_PTR, dfloat128_ptr_type_node)
+DEF_PRIMITIVE_TYPE (BT_DFLOAT32, (dfloat32_type_node
+ ? dfloat32_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_DFLOAT64, (dfloat64_type_node
+ ? dfloat64_type_node
+ : error_mark_node))
+DEF_PRIMITIVE_TYPE (BT_DFLOAT128, (dfloat128_type_node
+ ? dfloat128_type_node
+ : error_mark_node))
DEF_PRIMITIVE_TYPE (BT_VALIST_REF, va_list_ref_type_node)
DEF_PRIMITIVE_TYPE (BT_VALIST_ARG, va_list_arg_type_node)
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 8296d846171..36319a97b52 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -11045,7 +11045,7 @@ do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
{
REAL_VALUE_TYPE rr;
- real_from_mpfr (&rr, m, type, GMP_RNDN);
+ real_from_mpfr (&rr, m, type, MPFR_RNDN);
/* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR value,
check for overflow/underflow. If the REAL_VALUE_TYPE is zero
but the mpft_t is not, then we underflowed in the
@@ -11085,8 +11085,8 @@ do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
{
REAL_VALUE_TYPE re, im;
- real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), GMP_RNDN);
- real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), GMP_RNDN);
+ real_from_mpfr (&re, mpc_realref (m), TREE_TYPE (type), MPFR_RNDN);
+ real_from_mpfr (&im, mpc_imagref (m), TREE_TYPE (type), MPFR_RNDN);
/* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values,
check for overflow/underflow. If the REAL_VALUE_TYPE is zero
but the mpft_t is not, then we underflowed in the
@@ -11138,14 +11138,14 @@ do_mpfr_remquo (tree arg0, tree arg1, tree arg_quo)
{
const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
const int prec = fmt->p;
- const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
+ const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
tree result_rem;
long integer_quo;
mpfr_t m0, m1;
mpfr_inits2 (prec, m0, m1, NULL);
- mpfr_from_real (m0, ra0, GMP_RNDN);
- mpfr_from_real (m1, ra1, GMP_RNDN);
+ mpfr_from_real (m0, ra0, MPFR_RNDN);
+ mpfr_from_real (m1, ra1, MPFR_RNDN);
mpfr_clear_flags ();
mpfr_remquo (m0, &integer_quo, m0, m1, rnd);
/* Remquo is independent of the rounding mode, so pass
@@ -11218,13 +11218,13 @@ do_mpfr_lgamma_r (tree arg, tree arg_sg, tree type)
{
const struct real_format *fmt = REAL_MODE_FORMAT (TYPE_MODE (type));
const int prec = fmt->p;
- const mp_rnd_t rnd = fmt->round_towards_zero? GMP_RNDZ : GMP_RNDN;
+ const mpfr_rnd_t rnd = fmt->round_towards_zero? MPFR_RNDZ : MPFR_RNDN;
int inexact, sg;
mpfr_t m;
tree result_lg;
mpfr_init2 (m, prec);
- mpfr_from_real (m, ra, GMP_RNDN);
+ mpfr_from_real (m, ra, MPFR_RNDN);
mpfr_clear_flags ();
inexact = mpfr_lgamma (m, &sg, m, rnd);
result_lg = do_mpfr_ckconv (m, type, inexact);
@@ -11287,7 +11287,8 @@ do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
const struct real_format *const fmt =
REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
const int prec = fmt->p;
- const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
+ const mpfr_rnd_t rnd = fmt->round_towards_zero
+ ? MPFR_RNDZ : MPFR_RNDN;
const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
int inexact;
mpc_t m0, m1;
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 281d7f409b7..fa3b94232fb 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,37 @@
+2019-11-30 Jan Hubicka <hubicka@ucw.cz>
+
+ * c-attribs.c (handle_symver_attribute): New function
+ (c_common_attributes): Add symver.
+
+2019-11-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ * c-common.c (pointer_int_sum): Use verify_type_context to check
+ whether the target allows pointer arithmetic for the types involved.
+ (c_sizeof_or_alignof_type, c_alignof_expr): Use verify_type_context
+ to check whether the target allows sizeof and alignof operations
+ for the types involved.
+
+2019-11-27 Jason Merrill <jason@redhat.com>
+
+ * c-cppbuiltin.c (c_cpp_builtins): Update __cpp_deduction_guides.
+
+2019-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/61414
+ * c-attribs.c (handle_mode_attribute): Add mode attribute to
+ ENUMERAL_TYPEs.
+
+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/91985
+ * c-common.c (c_common_type_for_mode): Handle decimal
+ floating-point types being NULL_TREE.
+ * c-format.c (get_format_for_type_1): Handle specified types being
+ NULL_TREE.
+ * c-lex.c (interpret_float): Give an error for decimal
+ floating-point constants when decimal floating-point not
+ supported.
+
2019-11-23 Jakub Jelinek <jakub@redhat.com>
PR middle-end/83859
@@ -16,7 +50,7 @@
(init_dynamic_diag_info): Adjust get_pointer_to_named_type callers
to call get_named_type instead. Formatting fixes.
- Implement P1920R1, Missing feature-test macros 2017-2019.
+ Implement P1902R1, Missing feature-test macros 2017-2019.
* c-cppbuiltin.c (c_cpp_builtins): Bump __cpp_init_captures
and __cpp_generic_lambdas for -std=c++2a. Define
__cpp_designated_initializers, __cpp_constexpr_in_decltype and
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index cc006f38366..dc56e2ec62f 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -66,6 +66,7 @@ static tree handle_stack_protect_attribute (tree *, tree, tree, int, bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
static tree handle_nocf_check_attribute (tree *, tree, tree, int, bool *);
+static tree handle_symver_attribute (tree *, tree, tree, int, bool *);
static tree handle_noicf_attribute (tree *, tree, tree, int, bool *);
static tree handle_noipa_attribute (tree *, tree, tree, int, bool *);
static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
@@ -475,6 +476,8 @@ const struct attribute_spec c_common_attribute_table[] =
NULL },
{ "nocf_check", 0, 0, false, true, true, true,
handle_nocf_check_attribute, NULL },
+ { "symver", 1, -1, true, false, false, false,
+ handle_symver_attribute, NULL},
{ "copy", 1, 1, false, false, false, false,
handle_copy_attribute, NULL },
{ "noinit", 0, 0, true, false, false, false,
@@ -1866,6 +1869,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
typefm = make_signed_type (TYPE_PRECISION (typefm));
TREE_TYPE (typefm) = type;
}
+ *no_add_attrs = false;
}
else if (VECTOR_MODE_P (mode)
? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
@@ -2334,6 +2338,62 @@ handle_noplt_attribute (tree *node, tree name,
return NULL_TREE;
}
+/* Handle a "symver" attribute. */
+
+static tree
+handle_symver_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ tree symver;
+ const char *symver_str;
+
+ if (TREE_CODE (*node) != FUNCTION_DECL && TREE_CODE (*node) != VAR_DECL)
+ {
+ warning (OPT_Wattributes,
+ "%<symver%> attribute only applies to functions and variables");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ if (!decl_in_symtab_p (*node))
+ {
+ warning (OPT_Wattributes,
+ "%<symver%> attribute is only applicable to symbols");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ for (; args; args = TREE_CHAIN (args))
+ {
+ symver = TREE_VALUE (args);
+ if (TREE_CODE (symver) != STRING_CST)
+ {
+ error ("%<symver%> attribute argument not a string constant");
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+
+ symver_str = TREE_STRING_POINTER (symver);
+
+ int ats = 0;
+ for (int n = 0; (int)n < TREE_STRING_LENGTH (symver); n++)
+ if (symver_str[n] == '@')
+ ats++;
+
+ if (ats != 1 && ats != 2)
+ {
+ error ("symver attribute argument must have format %<name@nodename%>");
+ error ("%<symver%> attribute argument %qs must contain one or two "
+ "%<@%>", symver_str);
+ *no_add_attrs = true;
+ return NULL_TREE;
+ }
+ }
+
+ return NULL_TREE;
+}
+
+
/* Handle an "alias" or "ifunc" attribute; arguments as in
struct attribute_spec.handler, except that IS_ALIAS tells us
whether this is an alias as opposed to ifunc attribute. */
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 25047b814f3..f79b78b135d 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -2326,11 +2326,14 @@ c_common_type_for_mode (machine_mode mode, int unsignedp)
return build_vector_type_for_mode (inner_type, mode);
}
- if (mode == TYPE_MODE (dfloat32_type_node))
+ if (dfloat32_type_node != NULL_TREE
+ && mode == TYPE_MODE (dfloat32_type_node))
return dfloat32_type_node;
- if (mode == TYPE_MODE (dfloat64_type_node))
+ if (dfloat64_type_node != NULL_TREE
+ && mode == TYPE_MODE (dfloat64_type_node))
return dfloat64_type_node;
- if (mode == TYPE_MODE (dfloat128_type_node))
+ if (dfloat128_type_node != NULL_TREE
+ && mode == TYPE_MODE (dfloat128_type_node))
return dfloat128_type_node;
if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
@@ -3148,6 +3151,9 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
return error_mark_node;
size_exp = integer_one_node;
}
+ else if (!verify_type_context (loc, TCTX_POINTER_ARITH,
+ TREE_TYPE (result_type)))
+ size_exp = integer_one_node;
else
size_exp = size_in_bytes_loc (loc, TREE_TYPE (result_type));
@@ -3693,6 +3699,13 @@ c_sizeof_or_alignof_type (location_t loc,
"incomplete element type", op_name, type);
return error_mark_node;
}
+ else if (!verify_type_context (loc, is_sizeof ? TCTX_SIZEOF : TCTX_ALIGNOF,
+ type, !complain))
+ {
+ if (!complain)
+ return error_mark_node;
+ value = size_one_node;
+ }
else
{
if (is_sizeof)
@@ -3725,7 +3738,10 @@ c_alignof_expr (location_t loc, tree expr)
{
tree t;
- if (VAR_OR_FUNCTION_DECL_P (expr))
+ if (!verify_type_context (loc, TCTX_ALIGNOF, TREE_TYPE (expr)))
+ t = size_one_node;
+
+ else if (VAR_OR_FUNCTION_DECL_P (expr))
t = size_int (DECL_ALIGN_UNIT (expr));
else if (TREE_CODE (expr) == COMPONENT_REF
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index fc542d31cc4..fd85a3a0183 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -980,7 +980,8 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_capture_star_this=201603L");
cpp_define (pfile, "__cpp_inline_variables=201606L");
cpp_define (pfile, "__cpp_aggregate_bases=201603L");
- cpp_define (pfile, "__cpp_deduction_guides=201703L");
+ if (cxx_dialect <= cxx17)
+ cpp_define (pfile, "__cpp_deduction_guides=201703L");
cpp_define (pfile, "__cpp_noexcept_function_type=201510L");
/* Old macro, superseded by
__cpp_nontype_template_parameter_auto. */
@@ -1000,6 +1001,7 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_conditional_explicit=201806L");
cpp_define (pfile, "__cpp_consteval=201811L");
cpp_define (pfile, "__cpp_constinit=201907L");
+ cpp_define (pfile, "__cpp_deduction_guides=201907L");
cpp_define (pfile, "__cpp_nontype_template_parameter_class=201806L");
cpp_define (pfile, "__cpp_impl_destroying_delete=201806L");
cpp_define (pfile, "__cpp_constexpr_dynamic_alloc=201907L");
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index d70d1e0f9c2..519bc8f0af1 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -4390,7 +4390,7 @@ get_format_for_type_1 (const format_kind_info *fki, tree arg_type,
for (int i = 0; i < FMT_LEN_MAX; i++)
{
const format_type_detail *ftd = &spec->types[i];
- if (!ftd->type)
+ if (!ftd->type || *ftd->type == NULL_TREE)
continue;
if (matching_type_p (*ftd->type, effective_arg_type))
{
diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index d446633f814..107c4c3e931 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -877,7 +877,12 @@ interpret_float (const cpp_token *token, unsigned int flags,
/* Decode type based on width and properties. */
if (flags & CPP_N_DFLOAT)
- if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
+ if (!targetm.decimal_float_supported_p ())
+ {
+ error ("decimal floating-point not supported for this target");
+ return error_mark_node;
+ }
+ else if ((flags & CPP_N_WIDTH) == CPP_N_LARGE)
type = dfloat128_type_node;
else if ((flags & CPP_N_WIDTH) == CPP_N_SMALL)
type = dfloat32_type_node;
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index cb1ea0948dd..c04443ea6f9 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,58 @@
+2019-12-01 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR target/92499
+
+ * c-decl.c (flexible_array_type_p): Move to common code.
+
+2019-11-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ * c-decl.c (start_decl): Allow initialization of variables whose
+ size is a POLY_INT_CST.
+ (finish_decl): Use verify_type_context to check whether the target
+ allows variables with a particular type to have static or thread-local
+ storage duration. Don't raise a second error if such variables do
+ not have a constant size.
+ (grokdeclarator): Use verify_type_context to check whether the
+ target allows fields or array elements to have a particular type.
+ * c-typeck.c (pointer_diff): Use verify_type_context to test whether
+ the target allows pointer difference for the types involved.
+ (build_unary_op): Likewise for pointer increment and decrement.
+
+2019-11-29 Joseph Myers <joseph@codesourcery.com>
+
+ * c-parser.c (struct c_parser): Add members raw_tokens and
+ raw_tokens_used.
+ (c_lex_one_token): Add argument raw. Handle lexing raw tokens and
+ using previously-lexed raw tokens.
+ (c_parser_peek_nth_token_raw)
+ (c_parser_check_balanced_raw_token_sequence): New functions.
+ (c_parser_nth_token_starts_std_attributes): Use
+ c_parser_check_balanced_raw_token_sequence for Objective-C.
+
+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/91985
+ * c-decl.c (finish_declspecs): Use int instead of decimal
+ floating-point types if decimal floating-point not supported.
+
+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ * c-tree.h (struct c_declarator): Use a structure for id member.
+ * c-decl.c (grokdeclarator): Extract attributes from cdk_id
+ declarators at the start, not when handling individual declarators
+ later. Use u.id.id instead of u.id.
+ (grokfield): Use u.id.id instead of u.id.
+ (build_id_declarator): Set u.id.id and u.id.attrs.
+ (finish_declspecs): Handle postfix attributes in case of typedef
+ name or typeof used.
+ * c-parser.c (c_parser_direct_declarator)
+ (c_parser_direct_declarator_inner): Place declarator for
+ attributes inside that for function or array, not outside. Set
+ u.id.attrs for identifiers.
+ (c_parser_parameter_declaration): Use u.id.id instead of u.id.
+ * gimple-parser.c (c_parser_gimple_declaration): Use u.id.id
+ instead of u.id.
+
2019-11-22 Jakub Jelinek <jakub@redhat.com>
PR c/90677
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 7fd3cc26e87..bf1857dc3fa 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -5021,7 +5021,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
{
/* A complete type is ok if size is fixed. */
- if (TREE_CODE (TYPE_SIZE (TREE_TYPE (decl))) != INTEGER_CST
+ if (!poly_int_tree_p (TYPE_SIZE (TREE_TYPE (decl)))
|| C_DECL_VARIABLE_SIZE (decl))
{
error ("variable-sized object may not be initialized");
@@ -5304,6 +5304,15 @@ finish_decl (tree decl, location_t init_loc, tree init,
complete_flexible_array_elts (DECL_INITIAL (decl));
+ if (is_global_var (decl))
+ {
+ type_context_kind context = (DECL_THREAD_LOCAL_P (decl)
+ ? TCTX_THREAD_STORAGE
+ : TCTX_STATIC_STORAGE);
+ if (!verify_type_context (input_location, context, TREE_TYPE (decl)))
+ TREE_TYPE (decl) = error_mark_node;
+ }
+
if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node
&& COMPLETE_TYPE_P (TREE_TYPE (decl)))
layout_decl (decl, 0);
@@ -5333,7 +5342,9 @@ finish_decl (tree decl, location_t init_loc, tree init,
&& TREE_STATIC (decl))
incomplete_record_decls.safe_push (decl);
- if (is_global_var (decl) && DECL_SIZE (decl) != NULL_TREE)
+ if (is_global_var (decl)
+ && DECL_SIZE (decl) != NULL_TREE
+ && TREE_TYPE (decl) != error_mark_node)
{
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
@@ -5653,6 +5664,10 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const,
return error_mark_node;
}
+ if (TREE_STATIC (decl)
+ && !verify_type_context (loc, TCTX_STATIC_STORAGE, type))
+ return error_mark_node;
+
stmt = build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl);
complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt);
TREE_SIDE_EFFECTS (complit) = 1;
@@ -5694,39 +5709,6 @@ check_compound_literal_type (location_t loc, struct c_type_name *type_name)
"defining a type in a compound literal is invalid in C++");
}
-/* Determine whether TYPE is a structure with a flexible array member,
- or a union containing such a structure (possibly recursively). */
-
-static bool
-flexible_array_type_p (tree type)
-{
- tree x;
- switch (TREE_CODE (type))
- {
- case RECORD_TYPE:
- x = TYPE_FIELDS (type);
- if (x == NULL_TREE)
- return false;
- while (DECL_CHAIN (x) != NULL_TREE)
- x = DECL_CHAIN (x);
- if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
- && TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
- && TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
- && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
- return true;
- return false;
- case UNION_TYPE:
- for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
- {
- if (flexible_array_type_p (TREE_TYPE (x)))
- return true;
- }
- return false;
- default:
- return false;
- }
-}
-
/* Performs sanity checks on the TYPE and WIDTH of the bit-field NAME,
replacing with appropriate values if they are invalid. */
@@ -5951,6 +5933,7 @@ grokdeclarator (const struct c_declarator *declarator,
bool array_parm_static = false;
bool array_parm_vla_unspec_p = false;
tree returned_attrs = NULL_TREE;
+ tree decl_id_attrs = NULL_TREE;
bool bitfield = width != NULL;
tree element_type;
tree orig_qual_type = NULL;
@@ -6013,8 +5996,9 @@ grokdeclarator (const struct c_declarator *declarator,
case cdk_id:
loc = decl->id_loc;
- if (decl->u.id)
- name = decl->u.id;
+ if (decl->u.id.id)
+ name = decl->u.id.id;
+ decl_id_attrs = decl->u.id.attrs;
if (first_non_attr_kind == cdk_attrs)
first_non_attr_kind = decl->kind;
decl = 0;
@@ -6300,7 +6284,9 @@ grokdeclarator (const struct c_declarator *declarator,
Standard attributes applied to a function or array
declarator apply exactly to that type; standard
attributes applied to the identifier apply to the
- declaration rather than to the type. */
+ declaration rather than to the type, and are specified
+ using a cdk_id declarator rather than using
+ cdk_attrs. */
inner_decl = declarator;
while (inner_decl->kind == cdk_attrs)
inner_decl = inner_decl->declarator;
@@ -6313,16 +6299,10 @@ grokdeclarator (const struct c_declarator *declarator,
else if (inner_decl->kind == cdk_array)
attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
}
- if (cxx11_attribute_p (attrs) && inner_decl->kind == cdk_id)
- returned_attrs = chainon (returned_attrs, attrs);
- else
- {
- attrs = c_warn_type_attributes (attrs);
- returned_attrs = decl_attributes (&type,
- chainon (returned_attrs,
- attrs),
- attr_flags);
- }
+ attrs = c_warn_type_attributes (attrs);
+ returned_attrs = decl_attributes (&type,
+ chainon (returned_attrs, attrs),
+ attr_flags);
break;
}
case cdk_array:
@@ -6372,6 +6352,12 @@ grokdeclarator (const struct c_declarator *declarator,
if (type == error_mark_node)
continue;
+ if (!verify_type_context (loc, TCTX_ARRAY_ELEMENT, type))
+ {
+ type = error_mark_node;
+ continue;
+ }
+
/* If size was specified, set ITYPE to a range-type for
that size. Otherwise, ITYPE remains null. finish_decl
may figure it out from an initial value. */
@@ -6883,6 +6869,7 @@ grokdeclarator (const struct c_declarator *declarator,
}
}
*decl_attrs = chainon (returned_attrs, *decl_attrs);
+ *decl_attrs = chainon (decl_id_attrs, *decl_attrs);
/* Now TYPE has the actual type, apart from any qualifiers in
TYPE_QUALS. */
@@ -7017,7 +7004,7 @@ grokdeclarator (const struct c_declarator *declarator,
type = c_build_qualified_type (type, type_quals, orig_qual_type,
orig_qual_indirect);
decl = build_decl (declarator->id_loc,
- TYPE_DECL, declarator->u.id, type);
+ TYPE_DECL, declarator->u.id.id, type);
if (declspecs->explicit_signed_p)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
if (declspecs->inline_p)
@@ -7025,9 +7012,9 @@ grokdeclarator (const struct c_declarator *declarator,
if (declspecs->noreturn_p)
pedwarn (loc, 0,"typedef %q+D declared %<_Noreturn%>", decl);
- if (warn_cxx_compat && declarator->u.id != NULL_TREE)
+ if (warn_cxx_compat && declarator->u.id.id != NULL_TREE)
{
- struct c_binding *b = I_TAG_BINDING (declarator->u.id);
+ struct c_binding *b = I_TAG_BINDING (declarator->u.id.id);
if (b != NULL
&& b->decl != NULL_TREE
@@ -7159,7 +7146,7 @@ grokdeclarator (const struct c_declarator *declarator,
type = c_build_qualified_type (type, type_quals);
decl = build_decl (declarator->id_loc,
- PARM_DECL, declarator->u.id, type);
+ PARM_DECL, declarator->u.id.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
C_ARRAY_PARAMETER (decl) = array_parameter_p;
@@ -7218,12 +7205,16 @@ grokdeclarator (const struct c_declarator *declarator,
if (orig_qual_indirect == 0)
orig_qual_type = NULL_TREE;
}
+ if (type != error_mark_node
+ && !verify_type_context (loc, TCTX_FIELD, type))
+ type = error_mark_node;
+
type = c_build_qualified_type (type, type_quals, orig_qual_type,
orig_qual_indirect);
decl = build_decl (declarator->id_loc,
- FIELD_DECL, declarator->u.id, type);
+ FIELD_DECL, declarator->u.id.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
- if (bitfield && !declarator->u.id)
+ if (bitfield && !declarator->u.id.id)
{
TREE_NO_WARNING (decl) = 1;
DECL_PADDING_P (decl) = 1;
@@ -7259,7 +7250,7 @@ grokdeclarator (const struct c_declarator *declarator,
}
decl = build_decl (declarator->id_loc,
- FUNCTION_DECL, declarator->u.id, type);
+ FUNCTION_DECL, declarator->u.id.id, type);
decl = build_decl_attribute_variant (decl, decl_attr);
if (type_quals & TYPE_QUAL_ATOMIC)
@@ -7304,7 +7295,7 @@ grokdeclarator (const struct c_declarator *declarator,
/* Record presence of `inline' and `_Noreturn', if it is
reasonable. */
- if (flag_hosted && MAIN_NAME_P (declarator->u.id))
+ if (flag_hosted && MAIN_NAME_P (declarator->u.id.id))
{
if (declspecs->inline_p)
pedwarn (loc, 0, "cannot inline function %<main%>");
@@ -7345,8 +7336,8 @@ grokdeclarator (const struct c_declarator *declarator,
the 'extern' declaration is taken to refer to that decl.) */
if (extern_ref && current_scope != file_scope)
{
- tree global_decl = identifier_global_value (declarator->u.id);
- tree visible_decl = lookup_name (declarator->u.id);
+ tree global_decl = identifier_global_value (declarator->u.id.id);
+ tree visible_decl = lookup_name (declarator->u.id.id);
if (global_decl
&& global_decl != visible_decl
@@ -7357,7 +7348,7 @@ grokdeclarator (const struct c_declarator *declarator,
}
decl = build_decl (declarator->id_loc,
- VAR_DECL, declarator->u.id, type);
+ VAR_DECL, declarator->u.id.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -8009,7 +8000,7 @@ grokfield (location_t loc,
{
tree value;
- if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE
+ if (declarator->kind == cdk_id && declarator->u.id.id == NULL_TREE
&& width == NULL_TREE)
{
/* This is an unnamed decl.
@@ -10295,7 +10286,8 @@ build_id_declarator (tree ident)
struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
ret->kind = cdk_id;
ret->declarator = 0;
- ret->u.id = ident;
+ ret->u.id.id = ident;
+ ret->u.id.attrs = NULL_TREE;
/* Default value - may get reset to a more precise location. */
ret->id_loc = input_location;
return ret;
@@ -11468,7 +11460,7 @@ finish_declspecs (struct c_declspecs *specs)
/* Set a dummy type. */
if (TREE_CODE (specs->type) == ERROR_MARK)
specs->type = integer_type_node;
- return specs;
+ goto handle_postfix_attrs;
}
/* If none of "void", "_Bool", "char", "int", "float" or "double"
@@ -11633,7 +11625,9 @@ finish_declspecs (struct c_declspecs *specs)
case cts_dfloat128:
gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
&& !specs->signed_p && !specs->unsigned_p && !specs->complex_p);
- if (specs->typespec_word == cts_dfloat32)
+ if (!targetm.decimal_float_supported_p ())
+ specs->type = integer_type_node;
+ else if (specs->typespec_word == cts_dfloat32)
specs->type = dfloat32_type_node;
else if (specs->typespec_word == cts_dfloat64)
specs->type = dfloat64_type_node;
@@ -11729,6 +11723,7 @@ finish_declspecs (struct c_declspecs *specs)
default:
gcc_unreachable ();
}
+ handle_postfix_attrs:
if (specs->type != NULL)
{
specs->postfix_attrs = c_warn_type_attributes (specs->postfix_attrs);
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 03194b438f2..bfe56998996 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -176,6 +176,12 @@ struct GTY(()) c_parser {
/* How many look-ahead tokens are available (0 - 4, or
more if parsing from pre-lexed tokens). */
unsigned int tokens_avail;
+ /* Raw look-ahead tokens, used only for checking in Objective-C
+ whether '[[' starts attributes. */
+ vec<c_token, va_gc> *raw_tokens;
+ /* The number of raw look-ahead tokens that have since been fully
+ lexed. */
+ unsigned int raw_tokens_used;
/* True if a syntax error is being recovered from; false otherwise.
c_parser_error sets this flag. It should clear this flag when
enough tokens have been consumed to recover from the error. */
@@ -251,20 +257,39 @@ c_parser_set_error (c_parser *parser, bool err)
static GTY (()) c_parser *the_parser;
-/* Read in and lex a single token, storing it in *TOKEN. */
+/* Read in and lex a single token, storing it in *TOKEN. If RAW,
+ context-sensitive postprocessing of the token is not done. */
static void
-c_lex_one_token (c_parser *parser, c_token *token)
+c_lex_one_token (c_parser *parser, c_token *token, bool raw = false)
{
timevar_push (TV_LEX);
- token->type = c_lex_with_flags (&token->value, &token->location,
- &token->flags,
- (parser->lex_joined_string
- ? 0 : C_LEX_STRING_NO_JOIN));
- token->id_kind = C_ID_NONE;
- token->keyword = RID_MAX;
- token->pragma_kind = PRAGMA_NONE;
+ if (raw || vec_safe_length (parser->raw_tokens) == 0)
+ {
+ token->type = c_lex_with_flags (&token->value, &token->location,
+ &token->flags,
+ (parser->lex_joined_string
+ ? 0 : C_LEX_STRING_NO_JOIN));
+ token->id_kind = C_ID_NONE;
+ token->keyword = RID_MAX;
+ token->pragma_kind = PRAGMA_NONE;
+ }
+ else
+ {
+ /* Use a token previously lexed as a raw look-ahead token, and
+ complete the processing on it. */
+ *token = (*parser->raw_tokens)[parser->raw_tokens_used];
+ ++parser->raw_tokens_used;
+ if (parser->raw_tokens_used == vec_safe_length (parser->raw_tokens))
+ {
+ vec_free (parser->raw_tokens);
+ parser->raw_tokens_used = 0;
+ }
+ }
+
+ if (raw)
+ goto out;
switch (token->type)
{
@@ -434,6 +459,7 @@ c_lex_one_token (c_parser *parser, c_token *token)
default:
break;
}
+ out:
timevar_pop (TV_LEX);
}
@@ -484,6 +510,32 @@ c_parser_peek_nth_token (c_parser *parser, unsigned int n)
return &parser->tokens[n - 1];
}
+/* Return a pointer to the Nth token from PARSER, reading it in as a
+ raw look-ahead token if necessary. The N-1th token is already read
+ in. Raw look-ahead tokens remain available for when the non-raw
+ functions above are called. */
+
+c_token *
+c_parser_peek_nth_token_raw (c_parser *parser, unsigned int n)
+{
+ /* N is 1-based, not zero-based. */
+ gcc_assert (n > 0);
+
+ if (parser->tokens_avail >= n)
+ return &parser->tokens[n - 1];
+ unsigned int raw_len = vec_safe_length (parser->raw_tokens);
+ unsigned int raw_avail
+ = parser->tokens_avail + raw_len - parser->raw_tokens_used;
+ gcc_assert (raw_avail >= n - 1);
+ if (raw_avail >= n)
+ return &(*parser->raw_tokens)[parser->raw_tokens_used
+ + n - 1 - parser->tokens_avail];
+ vec_safe_reserve (parser->raw_tokens, 1);
+ parser->raw_tokens->quick_grow (raw_len + 1);
+ c_lex_one_token (parser, &(*parser->raw_tokens)[raw_len], true);
+ return &(*parser->raw_tokens)[raw_len];
+}
+
bool
c_keyword_starts_typename (enum rid keyword)
{
@@ -3857,11 +3909,7 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
inner->id_loc = c_parser_peek_token (parser)->location;
c_parser_consume_token (parser);
if (c_parser_nth_token_starts_std_attributes (parser, 1))
- {
- tree std_attrs = c_parser_std_attribute_specifier_sequence (parser);
- if (std_attrs)
- inner = build_attrs_declarator (std_attrs, inner);
- }
+ inner->u.id.attrs = c_parser_std_attribute_specifier_sequence (parser);
return c_parser_direct_declarator_inner (parser, *seen_id, inner);
}
@@ -3898,9 +3946,7 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
return NULL;
else
{
- inner
- = build_function_declarator (args,
- build_id_declarator (NULL_TREE));
+ inner = build_id_declarator (NULL_TREE);
if (!(args->types
&& args->types != error_mark_node
&& TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
@@ -3911,6 +3957,7 @@ c_parser_direct_declarator (c_parser *parser, bool type_seen_p, c_dtr_syn kind,
if (std_attrs)
inner = build_attrs_declarator (std_attrs, inner);
}
+ inner = build_function_declarator (args, inner);
return c_parser_direct_declarator_inner (parser, *seen_id,
inner);
}
@@ -4028,7 +4075,6 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
static_seen, star_seen);
if (declarator == NULL)
return NULL;
- inner = set_array_declarator_inner (declarator, inner);
if (c_parser_nth_token_starts_std_attributes (parser, 1))
{
tree std_attrs
@@ -4036,6 +4082,7 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
if (std_attrs)
inner = build_attrs_declarator (std_attrs, inner);
}
+ inner = set_array_declarator_inner (declarator, inner);
return c_parser_direct_declarator_inner (parser, id_present, inner);
}
else if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
@@ -4052,7 +4099,6 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
return NULL;
else
{
- inner = build_function_declarator (args, inner);
if (!(args->types
&& args->types != error_mark_node
&& TREE_CODE (TREE_VALUE (args->types)) == IDENTIFIER_NODE)
@@ -4063,6 +4109,7 @@ c_parser_direct_declarator_inner (c_parser *parser, bool id_present,
if (std_attrs)
inner = build_attrs_declarator (std_attrs, inner);
}
+ inner = build_function_declarator (args, inner);
return c_parser_direct_declarator_inner (parser, id_present, inner);
}
}
@@ -4352,7 +4399,7 @@ c_parser_parameter_declaration (c_parser *parser, tree attrs,
c_declarator *id_declarator = declarator;
while (id_declarator && id_declarator->kind != cdk_id)
id_declarator = id_declarator->declarator;
- location_t caret_loc = (id_declarator->u.id
+ location_t caret_loc = (id_declarator->u.id.id
? id_declarator->id_loc
: start_loc);
location_t param_loc = make_location (caret_loc, start_loc, end_loc);
@@ -4973,6 +5020,80 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
return nreverse (attributes);
}
+/* Look past an optional balanced token sequence of raw look-ahead
+ tokens starting with the *Nth token. *N is updated to point to the
+ following token. Return true if such a sequence was found, false
+ if the tokens parsed were not balanced. */
+
+static bool
+c_parser_check_balanced_raw_token_sequence (c_parser *parser, unsigned int *n)
+{
+ while (true)
+ {
+ c_token *token = c_parser_peek_nth_token_raw (parser, *n);
+ switch (token->type)
+ {
+ case CPP_OPEN_BRACE:
+ {
+ ++*n;
+ if (c_parser_check_balanced_raw_token_sequence (parser, n))
+ {
+ token = c_parser_peek_nth_token_raw (parser, *n);
+ if (token->type == CPP_CLOSE_BRACE)
+ ++*n;
+ else
+ return false;
+ }
+ else
+ return false;
+ break;
+ }
+
+ case CPP_OPEN_PAREN:
+ {
+ ++*n;
+ if (c_parser_check_balanced_raw_token_sequence (parser, n))
+ {
+ token = c_parser_peek_nth_token_raw (parser, *n);
+ if (token->type == CPP_CLOSE_PAREN)
+ ++*n;
+ else
+ return false;
+ }
+ else
+ return false;
+ break;
+ }
+
+ case CPP_OPEN_SQUARE:
+ {
+ ++*n;
+ if (c_parser_check_balanced_raw_token_sequence (parser, n))
+ {
+ token = c_parser_peek_nth_token_raw (parser, *n);
+ if (token->type == CPP_CLOSE_SQUARE)
+ ++*n;
+ else
+ return false;
+ }
+ else
+ return false;
+ break;
+ }
+
+ case CPP_CLOSE_BRACE:
+ case CPP_CLOSE_PAREN:
+ case CPP_CLOSE_SQUARE:
+ case CPP_EOF:
+ return true;
+
+ default:
+ ++*n;
+ break;
+ }
+ }
+}
+
/* Return whether standard attributes start with the Nth token. */
static bool
@@ -4981,10 +5102,18 @@ c_parser_nth_token_starts_std_attributes (c_parser *parser, unsigned int n)
if (!(c_parser_peek_nth_token (parser, n)->type == CPP_OPEN_SQUARE
&& c_parser_peek_nth_token (parser, n + 1)->type == CPP_OPEN_SQUARE))
return false;
- /* In C, '[[' must start attributes. In Objective-C, identifying
- whether those tokens start attributes requires unbounded
- lookahead, which is not yet implemented. */
- return !c_dialect_objc ();
+ /* In C, '[[' must start attributes. In Objective-C, we need to
+ check whether '[[' is matched by ']]'. */
+ if (!c_dialect_objc ())
+ return true;
+ n += 2;
+ if (!c_parser_check_balanced_raw_token_sequence (parser, &n))
+ return false;
+ c_token *token = c_parser_peek_nth_token_raw (parser, n);
+ if (token->type != CPP_CLOSE_SQUARE)
+ return false;
+ token = c_parser_peek_nth_token_raw (parser, n + 1);
+ return token->type == CPP_CLOSE_SQUARE;
}
static tree
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index dffefa3fd1a..cdfb9080346 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -460,9 +460,15 @@ struct c_declarator {
/* Except for cdk_id, the contained declarator. For cdk_id, NULL. */
struct c_declarator *declarator;
union {
- /* For identifiers, an IDENTIFIER_NODE or NULL_TREE if an abstract
- declarator. */
- tree id;
+ /* For identifiers. */
+ struct {
+ /* An IDENTIFIER_NODE, or NULL_TREE if an abstract
+ declarator. */
+ tree id;
+ /* Any attributes (which apply to the declaration rather than to
+ the type described by the outer declarators). */
+ tree attrs;
+ } id;
/* For functions. */
struct c_arg_info *arg_info;
/* For arrays. */
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 5f74a3b28d9..f9ab1e38b42 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -3892,6 +3892,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr)
addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
tree target_type = TREE_TYPE (TREE_TYPE (op0));
+ tree orig_op0 = op0;
tree orig_op1 = op1;
/* If the operands point into different address spaces, we need to
@@ -3962,6 +3963,10 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr)
/* This generates an error if op1 is pointer to incomplete type. */
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
error_at (loc, "arithmetic on pointer to an incomplete type");
+ else if (verify_type_context (loc, TCTX_POINTER_ARITH,
+ TREE_TYPE (TREE_TYPE (orig_op0))))
+ verify_type_context (loc, TCTX_POINTER_ARITH,
+ TREE_TYPE (TREE_TYPE (orig_op1)));
op1 = c_size_in_bytes (target_type);
@@ -4614,6 +4619,9 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
pedwarn (location, OPT_Wpointer_arith,
"wrong type argument to decrement");
}
+ else
+ verify_type_context (location, TCTX_POINTER_ARITH,
+ TREE_TYPE (argtype));
inc = c_size_in_bytes (TREE_TYPE (argtype));
inc = convert_to_ptrofftype_loc (location, inc);
diff --git a/gcc/c/gimple-parser.c b/gcc/c/gimple-parser.c
index c16d0dfb88e..43e943744ae 100644
--- a/gcc/c/gimple-parser.c
+++ b/gcc/c/gimple-parser.c
@@ -2040,13 +2040,13 @@ c_parser_gimple_declaration (gimple_parser &parser)
unsigned version, ver_offset;
if (declarator->kind == cdk_id
&& is_gimple_reg_type (specs->type)
- && c_parser_parse_ssa_name_id (declarator->u.id,
+ && c_parser_parse_ssa_name_id (declarator->u.id.id,
&version, &ver_offset)
/* The following restricts it to unnamed anonymous SSA names
which fails parsing of named ones in dumps (we could
decide to not dump their name for -gimple). */
&& ver_offset == 0)
- c_parser_parse_ssa_name (parser, declarator->u.id, specs->type,
+ c_parser_parse_ssa_name (parser, declarator->u.id.id, specs->type,
version, ver_offset);
else
{
diff --git a/gcc/cfganal.c b/gcc/cfganal.c
index 1a5c720984e..1d8393d4fd9 100644
--- a/gcc/cfganal.c
+++ b/gcc/cfganal.c
@@ -1030,6 +1030,8 @@ pre_and_rev_post_order_compute_fn (struct function *fn,
}
/* Clear the temporarily allocated flag. */
+ if (!rev_post_order)
+ rev_post_order = pre_order;
for (int i = 0; i < pre_order_num; ++i)
BASIC_BLOCK_FOR_FN (fn, rev_post_order[i])->flags &= ~visited;
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 1f7a5c58d98..b75430f3f3a 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1923,6 +1923,9 @@ cgraph_node::dump (FILE *f)
if (profile_id)
fprintf (f, " Profile id: %i\n",
profile_id);
+ if (unit_id)
+ fprintf (f, " Unit id: %i\n",
+ unit_id);
cgraph_function_version_info *vi = function_version ();
if (vi != NULL)
{
@@ -1973,6 +1976,8 @@ cgraph_node::dump (FILE *f)
fprintf (f, " icf_merged");
if (merged_comdat)
fprintf (f, " merged_comdat");
+ if (merged_extern_inline)
+ fprintf (f, " merged_extern_inline");
if (split_part)
fprintf (f, " split_part");
if (indirect_call_target)
@@ -2227,6 +2232,7 @@ static bool
cgraph_node_cannot_be_local_p_1 (cgraph_node *node, void *)
{
return !(!node->force_output
+ && !node->ifunc_resolver
&& ((DECL_COMDAT (node->decl)
&& !node->forced_by_abi
&& !node->used_from_object_file_p ()
@@ -3060,6 +3066,13 @@ cgraph_node::verify_node (void)
error ("inline clone in same comdat group list");
error_found = true;
}
+ if (inlined_to && !count.compatible_p (inlined_to->count))
+ {
+ error ("inline clone count is not compatible");
+ count.debug ();
+ inlined_to->count.debug ();
+ error_found = true;
+ }
if (!definition && !in_other_partition && local)
{
error ("local symbols must be defined");
@@ -3088,6 +3101,13 @@ cgraph_node::verify_node (void)
identifier_to_locale (e->caller->name ()));
error_found = true;
}
+ if (!e->count.compatible_p (count))
+ {
+ error ("edge count is not compatible with function count");
+ e->count.debug ();
+ count.debug ();
+ error_found = true;
+ }
if (!e->indirect_unknown_callee
|| !e->indirect_info)
{
@@ -3136,6 +3156,13 @@ cgraph_node::verify_node (void)
{
if (e->verify_count ())
error_found = true;
+ if (!e->count.compatible_p (count))
+ {
+ error ("edge count is not compatible with function count");
+ e->count.debug ();
+ count.debug ();
+ error_found = true;
+ }
if (gimple_has_body_p (e->caller->decl)
&& !e->caller->inlined_to
&& !e->speculative
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 0d2442c997c..9c086fedaef 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -497,6 +497,8 @@ public:
and their visibility needs to be copied from their "masters" at
the end of parsing. */
unsigned cpp_implicit_alias : 1;
+ /* The alias is a symbol version. */
+ unsigned symver : 1;
/* Set once the definition was analyzed. The list of references and
other properties are built during analysis. */
unsigned analyzed : 1;
@@ -1433,6 +1435,8 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
int count_materialization_scale;
/* ID assigned by the profiling. */
unsigned int profile_id;
+ /* ID of the translation unit. */
+ int unit_id;
/* Time profiler: first run of function. */
int tp_first_run;
@@ -1469,6 +1473,8 @@ struct GTY((tag ("SYMTAB_FUNCTION"))) cgraph_node : public symtab_node
unsigned nonfreeing_fn : 1;
/* True if there was multiple COMDAT bodies merged by lto-symtab. */
unsigned merged_comdat : 1;
+ /* True if this def was merged with extern inlines. */
+ unsigned merged_extern_inline : 1;
/* True if function was created to be executed in parallel. */
unsigned parallelized_function : 1;
/* True if function is part split out by ipa-split. */
@@ -2090,7 +2096,7 @@ public:
edges_count (0), edges_max_uid (1), edges_max_summary_id (0),
cgraph_released_summary_ids (), edge_released_summary_ids (),
nodes (NULL), asmnodes (NULL), asm_last_node (NULL),
- order (0), global_info_ready (false), state (PARSING),
+ order (0), max_unit (0), global_info_ready (false), state (PARSING),
function_flags_ready (false), cpp_implicit_aliases_done (false),
section_hash (NULL), assembler_name_hash (NULL), init_priority_hash (NULL),
dump_file (NULL), ipa_clones_dump_file (NULL), cloned_nodes (),
@@ -2355,6 +2361,9 @@ public:
them, to support -fno-toplevel-reorder. */
int order;
+ /* Maximal unit ID used. */
+ int max_unit;
+
/* Set when whole unit has been analyzed so we can access global info. */
bool global_info_ready;
/* What state callgraph is in right now. */
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index ac5c57a47aa..81c5dfd194f 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -80,6 +80,11 @@ along with GCC; see the file COPYING3. If not see
#include "tree-inline.h"
#include "dumpfile.h"
#include "gimple-pretty-print.h"
+#include "alloc-pool.h"
+#include "symbol-summary.h"
+#include "tree-vrp.h"
+#include "ipa-prop.h"
+#include "ipa-fnsummary.h"
/* Create clone of edge in the node N represented by CALL_EXPR
the callgraph. */
@@ -136,8 +141,9 @@ cgraph_edge::clone (cgraph_node *n, gcall *call_stmt, unsigned stmt_uid,
/* Update IPA profile. Local profiles need no updating in original. */
if (update_original)
- count = count.combine_with_ipa_count (count.ipa ()
- - new_edge->count.ipa ());
+ count = count.combine_with_ipa_count_within (count.ipa ()
+ - new_edge->count.ipa (),
+ caller->count);
symtab->call_edge_duplication_hooks (this, new_edge);
return new_edge;
}
@@ -228,6 +234,9 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node)
new_thunk->unique_name = in_lto_p;
new_thunk->former_clone_of = thunk->decl;
new_thunk->clone.param_adjustments = node->clone.param_adjustments;
+ new_thunk->unit_id = thunk->unit_id;
+ new_thunk->merged_comdat = thunk->merged_comdat;
+ new_thunk->merged_extern_inline = thunk->merged_extern_inline;
cgraph_edge *e = new_thunk->create_edge (node, NULL, new_thunk->count);
symtab->call_edge_duplication_hooks (thunk->callees, e);
@@ -267,6 +276,8 @@ cgraph_node::expand_all_artificial_thunks ()
{
thunk->thunk.thunk_p = false;
thunk->analyze ();
+ ipa_analyze_node (thunk);
+ inline_analyze_function (thunk);
}
thunk->expand_all_artificial_thunks ();
}
@@ -341,7 +352,14 @@ cgraph_node::create_clone (tree new_decl, profile_count prof_count,
/* Update IPA profile. Local profiles need no updating in original. */
if (update_original)
- count = count.combine_with_ipa_count (count.ipa () - prof_count.ipa ());
+ {
+ if (inlined_to)
+ count = count.combine_with_ipa_count_within (count.ipa ()
+ - prof_count.ipa (),
+ inlined_to->count);
+ else
+ count = count.combine_with_ipa_count (count.ipa () - prof_count.ipa ());
+ }
new_node->decl = new_decl;
new_node->register_symbol ();
new_node->origin = origin;
@@ -368,6 +386,9 @@ cgraph_node::create_clone (tree new_decl, profile_count prof_count,
new_node->icf_merged = icf_merged;
new_node->merged_comdat = merged_comdat;
new_node->thunk = thunk;
+ new_node->unit_id = unit_id;
+ new_node->merged_comdat = merged_comdat;
+ new_node->merged_extern_inline = merged_extern_inline;
if (param_adjustments)
new_node->clone.param_adjustments = param_adjustments;
@@ -873,6 +894,9 @@ cgraph_node::create_version_clone (tree new_decl,
new_version->inlined_to = inlined_to;
new_version->rtl = rtl;
new_version->count = count;
+ new_version->unit_id = unit_id;
+ new_version->merged_comdat = merged_comdat;
+ new_version->merged_extern_inline = merged_extern_inline;
for (e = callees; e; e=e->next_callee)
if (!bbs_to_copy
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index aa26160bf3f..75ff10bc0cd 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -711,6 +711,89 @@ symbol_table::process_same_body_aliases (void)
cpp_implicit_aliases_done = true;
}
+/* Process a symver attribute. */
+
+static void
+process_symver_attribute (symtab_node *n)
+{
+ tree value = lookup_attribute ("symver", DECL_ATTRIBUTES (n->decl));
+
+ if (!value)
+ return;
+ if (lookup_attribute ("symver", TREE_CHAIN (value)))
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "multiple versions for one symbol");
+ return;
+ }
+ tree symver = get_identifier_with_length
+ (TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (value))),
+ TREE_STRING_LENGTH (TREE_VALUE (TREE_VALUE (value))));
+ symtab_node *def = symtab_node::get_for_asmname (symver);
+
+ if (def)
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "duplicate definition of a symbol version");
+ inform (DECL_SOURCE_LOCATION (def->decl),
+ "same version was previously defined here");
+ return;
+ }
+ if (!n->definition)
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "symbol needs to be defined to have a version");
+ return;
+ }
+ if (DECL_COMMON (n->decl))
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "common symbol cannot be versioned");
+ return;
+ }
+ if (DECL_COMDAT (n->decl))
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "comdat symbol cannot be versioned");
+ return;
+ }
+ if (n->weakref)
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "weakref cannot be versioned");
+ return;
+ }
+ if (!TREE_PUBLIC (n->decl))
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "versioned symbol must be public");
+ return;
+ }
+ if (DECL_VISIBILITY (n->decl) != VISIBILITY_DEFAULT)
+ {
+ error_at (DECL_SOURCE_LOCATION (n->decl),
+ "versioned symbol must have default visibility");
+ return;
+ }
+
+ /* Create new symbol table entry representing the version. */
+ tree new_decl = copy_node (n->decl);
+
+ DECL_INITIAL (new_decl) = NULL_TREE;
+ if (TREE_CODE (new_decl) == FUNCTION_DECL)
+ DECL_STRUCT_FUNCTION (new_decl) = NULL;
+ SET_DECL_ASSEMBLER_NAME (new_decl, symver);
+ TREE_PUBLIC (new_decl) = 1;
+ DECL_ATTRIBUTES (new_decl) = NULL;
+
+ symtab_node *symver_node = symtab_node::get_create (new_decl);
+ symver_node->alias = true;
+ symver_node->definition = true;
+ symver_node->symver = true;
+ symver_node->create_reference (n, IPA_REF_ALIAS, NULL);
+ symver_node->analyzed = true;
+}
+
/* Process attributes common for vars and functions. */
static void
@@ -730,6 +813,7 @@ process_common_attributes (symtab_node *node, tree decl)
if (lookup_attribute ("no_reorder", DECL_ATTRIBUTES (decl)))
node->no_reorder = 1;
+ process_symver_attribute (node);
}
/* Look for externally_visible and used attributes and mark cgraph nodes
@@ -2137,8 +2221,12 @@ cgraph_node::assemble_thunks_and_aliases (void)
/* Force assemble_alias to really output the alias this time instead
of buffering it in same alias pairs. */
TREE_ASM_WRITTEN (decl) = 1;
- do_assemble_alias (alias->decl,
- DECL_ASSEMBLER_NAME (decl));
+ if (alias->symver)
+ do_assemble_symver (alias->decl,
+ DECL_ASSEMBLER_NAME (decl));
+ else
+ do_assemble_alias (alias->decl,
+ DECL_ASSEMBLER_NAME (decl));
alias->assemble_thunks_and_aliases ();
TREE_ASM_WRITTEN (decl) = saved_written;
}
diff --git a/gcc/combine.c b/gcc/combine.c
index 2e21459f504..16e606d8a21 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -2117,12 +2117,16 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED,
/* If INSN contains an autoincrement or autodecrement, make sure that
register is not used between there and I3, and not already used in
- I3 either. Neither must it be used in PRED or SUCC, if they exist. */
+ I3 either. Neither must it be used in PRED or SUCC, if they exist.
+ Also insist that I3 not be a jump if using LRA; if it were one
+ and the incremented register were spilled, we would lose.
+ Reload handles this correctly. */
if (AUTO_INC_DEC)
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) == REG_INC
- && (reg_used_between_p (XEXP (link, 0), insn, i3)
+ && ((JUMP_P (i3) && targetm.lra_p ())
+ || reg_used_between_p (XEXP (link, 0), insn, i3)
|| (pred != NULL_RTX
&& reg_overlap_mentioned_p (XEXP (link, 0), PATTERN (pred)))
|| (pred2 != NULL_RTX
@@ -11808,7 +11812,9 @@ gen_lowpart_for_combine (machine_mode omode, rtx x)
/* If X is a comparison operator, rewrite it in a new mode. This
probably won't match, but may allow further simplifications. */
- else if (COMPARISON_P (x))
+ else if (COMPARISON_P (x)
+ && SCALAR_INT_MODE_P (imode)
+ && SCALAR_INT_MODE_P (omode))
return gen_rtx_fmt_ee (GET_CODE (x), omode, XEXP (x, 0), XEXP (x, 1));
/* If we couldn't simplify X any other way, just enclose it in a
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index 5b1fc7b7b28..c16b9362ea9 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -715,6 +715,9 @@ namespace aarch64_sve {
tree, unsigned int, tree *);
gimple *gimple_fold_builtin (unsigned int, gimple_stmt_iterator *, gcall *);
rtx expand_builtin (unsigned int, tree, rtx);
+#ifdef GCC_TARGET_H
+ bool verify_type_context (location_t, type_context_kind, const_tree, bool);
+#endif
}
extern void aarch64_split_combinev16qi (rtx operands[3]);
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
index 27736b99f1b..5dd7ccb74ff 100644
--- a/gcc/config/aarch64/aarch64-sve-builtins.cc
+++ b/gcc/config/aarch64/aarch64-sve-builtins.cc
@@ -3296,6 +3296,55 @@ builtin_type_p (const_tree type)
return svbool_type_p (type) || nvectors_if_data_type (type) > 0;
}
+/* Implement TARGET_VERIFY_TYPE_CONTEXT for SVE types. */
+bool
+verify_type_context (location_t loc, type_context_kind context,
+ const_tree type, bool silent_p)
+{
+ if (!builtin_type_p (type))
+ return true;
+
+ switch (context)
+ {
+ case TCTX_SIZEOF:
+ case TCTX_STATIC_STORAGE:
+ if (!silent_p)
+ error_at (loc, "SVE type %qT does not have a fixed size", type);
+ return false;
+
+ case TCTX_ALIGNOF:
+ if (!silent_p)
+ error_at (loc, "SVE type %qT does not have a defined alignment", type);
+ return false;
+
+ case TCTX_THREAD_STORAGE:
+ if (!silent_p)
+ error_at (loc, "variables of type %qT cannot have thread-local"
+ " storage duration", type);
+ return false;
+
+ case TCTX_POINTER_ARITH:
+ if (!silent_p)
+ error_at (loc, "arithmetic on pointer to SVE type %qT", type);
+ return false;
+
+ case TCTX_FIELD:
+ if (silent_p)
+ ;
+ else if (lang_GNU_CXX ())
+ error_at (loc, "member variables cannot have SVE type %qT", type);
+ else
+ error_at (loc, "fields cannot have SVE type %qT", type);
+ return false;
+
+ case TCTX_ARRAY_ELEMENT:
+ if (!silent_p)
+ error_at (loc, "array elements cannot have SVE type %qT", type);
+ return false;
+ }
+ gcc_unreachable ();
+}
+
}
using namespace aarch64_sve;
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 94e664af52f..d0cbe13273f 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -16200,6 +16200,15 @@ aarch64_mangle_type (const_tree type)
return NULL;
}
+/* Implement TARGET_VERIFY_TYPE_CONTEXT. */
+
+static bool
+aarch64_verify_type_context (location_t loc, type_context_kind context,
+ const_tree type, bool silent_p)
+{
+ return aarch64_sve::verify_type_context (loc, context, type, silent_p);
+}
+
/* Find the first rtx_insn before insn that will generate an assembly
instruction. */
@@ -21860,6 +21869,9 @@ aarch64_libgcc_floating_mode_supported_p
#undef TARGET_MANGLE_TYPE
#define TARGET_MANGLE_TYPE aarch64_mangle_type
+#undef TARGET_VERIFY_TYPE_CONTEXT
+#define TARGET_VERIFY_TYPE_CONTEXT aarch64_verify_type_context
+
#undef TARGET_MEMORY_MOVE_COST
#define TARGET_MEMORY_MOVE_COST aarch64_memory_move_cost
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index f711d4e3dc6..6bec4fb8acd 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -399,7 +399,7 @@
SI CSI SA USA SQ USQ
DI CDI DA UDA DQ UDQ
TA UTA
- SF SC
+ SF DF SC DC
PSI])
(define_expand "push<mode>1"
diff --git a/gcc/config/elfos.h b/gcc/config/elfos.h
index e00d437c27a..e91c0f34c72 100644
--- a/gcc/config/elfos.h
+++ b/gcc/config/elfos.h
@@ -248,6 +248,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
} \
while (0)
+#define ASM_OUTPUT_SYMVER_DIRECTIVE(FILE, NAME, NAME2) \
+ do \
+ { \
+ fputs ("\t.symver\t", (FILE)); \
+ assemble_name ((FILE), (NAME)); \
+ fputs (", ", (FILE)); \
+ assemble_name ((FILE), (NAME2)); \
+ fputc ('\n', (FILE)); \
+ } \
+ while (0)
+
/* The following macro defines the format used to output the second
operand of the .type assembler directive. Different svr4 assemblers
expect various different forms for this operand. The one given here
diff --git a/gcc/config/gcn/gcn.c b/gcc/config/gcn/gcn.c
index f85d84bbe95..d2a35c95d7a 100644
--- a/gcc/config/gcn/gcn.c
+++ b/gcc/config/gcn/gcn.c
@@ -1783,7 +1783,6 @@ gcn_expand_scalar_to_vector_address (machine_mode mode, rtx exec, rtx mem,
/* tmp[:] += zext (mem_base) */
if (exec)
{
- rtx undef_di = gcn_gen_undef (DImode);
emit_insn (gen_addv64si3_vcc_dup_exec (tmplo, mem_base_lo, tmplo,
vcc, undef_v64si, exec));
emit_insn (gen_addcv64si3_exec (tmphi, tmphi, const0_rtx,
@@ -3213,6 +3212,7 @@ tree
gcn_emutls_var_init (tree, tree decl, tree)
{
sorry_at (DECL_SOURCE_LOCATION (decl), "TLS is not implemented for GCN.");
+ return NULL_TREE;
}
/* }}} */
@@ -4340,8 +4340,6 @@ gcn_md_reorg (void)
{
basic_block bb;
rtx exec_reg = gen_rtx_REG (DImode, EXEC_REG);
- rtx exec_lo_reg = gen_rtx_REG (SImode, EXEC_LO_REG);
- rtx exec_hi_reg = gen_rtx_REG (SImode, EXEC_HI_REG);
regset_head live;
INIT_REG_SET (&live);
@@ -4937,6 +4935,8 @@ gcn_hsa_declare_function_name (FILE *file, const char *name, tree)
granulated_sgprs = (sgpr + extra_regs + 7) / 8 - 1;
else if (TARGET_GCN5)
granulated_sgprs = 2 * ((sgpr + extra_regs + 15) / 16 - 1);
+ else
+ gcc_unreachable ();
fputs ("\t.align\t256\n", file);
fputs ("\t.type\t", file);
diff --git a/gcc/config/gcn/mkoffload.c b/gcc/config/gcn/mkoffload.c
index 40b56375b75..b5a2870057c 100644
--- a/gcc/config/gcn/mkoffload.c
+++ b/gcc/config/gcn/mkoffload.c
@@ -36,17 +36,6 @@
const char tool_name[] = "gcn mkoffload";
-#define COMMENT_PREFIX "#"
-
-struct id_map
-{
- id_map *next;
- char *gcn_name;
-};
-
-static id_map *func_ids, **funcs_tail = &func_ids;
-static id_map *var_ids, **vars_tail = &var_ids;
-
/* Files to unlink. */
static const char *gcn_s1_name;
static const char *gcn_s2_name;
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index 62c68053563..fb43cafaad0 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -3129,8 +3129,8 @@
(define_insn "avx512f_maskcmp<mode>3"
[(set (match_operand:<avx512fmaskmode> 0 "register_operand" "=k")
(match_operator:<avx512fmaskmode> 3 "sse_comparison_operator"
- [(match_operand:VF 1 "register_operand" "v")
- (match_operand:VF 2 "nonimmediate_operand" "vm")]))]
+ [(match_operand:VF_AVX512VL 1 "register_operand" "v")
+ (match_operand:VF_AVX512VL 2 "nonimmediate_operand" "vm")]))]
"TARGET_AVX512F"
"vcmp%D3<ssemodesuffix>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "ssecmp")
diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h
index abd920e70f3..a88d9032347 100644
--- a/gcc/config/m68k/m68k-protos.h
+++ b/gcc/config/m68k/m68k-protos.h
@@ -42,7 +42,23 @@ extern const char *output_iorsi3 (rtx *);
extern const char *output_xorsi3 (rtx *);
extern const char *output_call (rtx);
extern const char *output_sibcall (rtx);
-extern void output_dbcc_and_branch (rtx *);
+extern void m68k_init_cc ();
+extern void output_dbcc_and_branch (rtx *, rtx_code);
+extern rtx_code m68k_output_compare_di (rtx, rtx, rtx, rtx, rtx_insn *, rtx_code);
+extern rtx_code m68k_output_compare_si (rtx, rtx, rtx_code);
+extern rtx_code m68k_output_compare_hi (rtx, rtx, rtx_code);
+extern rtx_code m68k_output_compare_qi (rtx, rtx, rtx_code);
+extern rtx_code m68k_output_compare_fp (rtx, rtx, rtx_code);
+extern rtx_code m68k_output_btst (rtx, rtx, rtx_code, int);
+extern rtx_code m68k_output_bftst (rtx, rtx, rtx, rtx_code);
+extern rtx_code m68k_find_flags_value (rtx, rtx, rtx_code);
+
+extern const char *m68k_output_scc (rtx_code);
+extern const char *m68k_output_scc_float (rtx_code);
+extern const char *m68k_output_branch_integer (rtx_code);
+extern const char *m68k_output_branch_integer_rev (rtx_code);
+extern const char *m68k_output_branch_float (rtx_code);
+extern const char *m68k_output_branch_float_rev (rtx_code);
extern int floating_exact_log2 (rtx);
extern bool strict_low_part_peephole_ok (machine_mode mode,
rtx_insn *first_insn, rtx target);
@@ -88,7 +104,6 @@ extern enum attr_op_mem m68k_sched_attr_op_mem (rtx_insn *);
extern enum reg_class m68k_secondary_reload_class (enum reg_class,
machine_mode, rtx);
extern enum reg_class m68k_preferred_reload_class (rtx, enum reg_class);
-extern int flags_in_68881 (void);
extern void m68k_expand_prologue (void);
extern bool m68k_use_return_insn (void);
extern void m68k_expand_epilogue (bool);
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 1030dfa5957..4b30c401e80 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -20,6 +20,7 @@ along with GCC; see the file COPYING3. If not see
#define IN_TARGET_CODE 1
#include "config.h"
+#define INCLUDE_STRING
#include "system.h"
#include "coretypes.h"
#include "backend.h"
@@ -194,6 +195,7 @@ static bool m68k_hard_regno_mode_ok (unsigned int, machine_mode);
static bool m68k_modes_tieable_p (machine_mode, machine_mode);
static machine_mode m68k_promote_function_mode (const_tree, machine_mode,
int *, const_tree, int);
+static void m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int);
/* Initialize the GCC target structure. */
@@ -355,6 +357,9 @@ static machine_mode m68k_promote_function_mode (const_tree, machine_mode,
#undef TARGET_HAVE_SPECULATION_SAFE_VALUE
#define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
+#undef TARGET_ASM_FINAL_POSTSCAN_INSN
+#define TARGET_ASM_FINAL_POSTSCAN_INSN m68k_asm_final_postscan_insn
+
static const struct attribute_spec m68k_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req,
@@ -1356,40 +1361,6 @@ m68k_expand_epilogue (bool sibcall_p)
emit_jump_insn (ret_rtx);
}
-/* Return true if X is a valid comparison operator for the dbcc
- instruction.
-
- Note it rejects floating point comparison operators.
- (In the future we could use Fdbcc).
-
- It also rejects some comparisons when CC_NO_OVERFLOW is set. */
-
-int
-valid_dbcc_comparison_p_2 (rtx x, machine_mode mode ATTRIBUTE_UNUSED)
-{
- switch (GET_CODE (x))
- {
- case EQ: case NE: case GTU: case LTU:
- case GEU: case LEU:
- return 1;
-
- /* Reject some when CC_NO_OVERFLOW is set. This may be over
- conservative */
- case GT: case LT: case GE: case LE:
- return ! (cc_prev_status.flags & CC_NO_OVERFLOW);
- default:
- return 0;
- }
-}
-
-/* Return nonzero if flags are currently in the 68881 flag register. */
-int
-flags_in_68881 (void)
-{
- /* We could add support for these in the future */
- return cc_status.flags & CC_IN_68881;
-}
-
/* Return true if PARALLEL contains register REGNO. */
static bool
m68k_reg_present_p (const_rtx parallel, unsigned int regno)
@@ -1580,18 +1551,186 @@ m68k_legitimize_address (rtx x, rtx oldx, machine_mode mode)
return x;
}
+
+/* For eliding comparisons, we remember how the flags were set.
+ FLAGS_COMPARE_OP0 and FLAGS_COMPARE_OP1 are remembered for a direct
+ comparison, they take priority. FLAGS_OPERAND1 and FLAGS_OPERAND2
+ are used in more cases, they are a fallback for comparisons against
+ zero after a move or arithmetic insn.
+ FLAGS_VALID is set to FLAGS_VALID_NO if we should not use any of
+ these values. */
+
+static rtx flags_compare_op0, flags_compare_op1;
+static rtx flags_operand1, flags_operand2;
+static attr_flags_valid flags_valid = FLAGS_VALID_NO;
+
+/* Return a code other than UNKNOWN if we can elide a CODE comparison of
+ OP0 with OP1. */
+
+rtx_code
+m68k_find_flags_value (rtx op0, rtx op1, rtx_code code)
+{
+ if (flags_compare_op0 != NULL_RTX)
+ {
+ if (rtx_equal_p (op0, flags_compare_op0)
+ && rtx_equal_p (op1, flags_compare_op1))
+ return code;
+ if (rtx_equal_p (op0, flags_compare_op1)
+ && rtx_equal_p (op1, flags_compare_op0))
+ return swap_condition (code);
+ return UNKNOWN;
+ }
+
+ machine_mode mode = GET_MODE (op0);
+ if (op1 != CONST0_RTX (mode))
+ return UNKNOWN;
+ /* Comparisons against 0 with these two should have been optimized out. */
+ gcc_assert (code != LTU && code != GEU);
+ if (flags_valid == FLAGS_VALID_NOOV && (code == GT || code == LE))
+ return UNKNOWN;
+ if (rtx_equal_p (flags_operand1, op0) || rtx_equal_p (flags_operand2, op0))
+ return (FLOAT_MODE_P (mode) ? code
+ : code == GE ? PLUS : code == LT ? MINUS : code);
+ /* See if we are testing whether the high part of a DImode value is
+ positive or negative and we have the full value as a remembered
+ operand. */
+ if (code != GE && code != LT)
+ return UNKNOWN;
+ if (mode == SImode
+ && flags_operand1 != NULL_RTX && GET_MODE (flags_operand1) == DImode
+ && REG_P (flags_operand1) && REG_P (op0)
+ && hard_regno_nregs (REGNO (flags_operand1), DImode) == 2
+ && REGNO (flags_operand1) == REGNO (op0))
+ return code == GE ? PLUS : MINUS;
+ if (mode == SImode
+ && flags_operand2 != NULL_RTX && GET_MODE (flags_operand2) == DImode
+ && REG_P (flags_operand2) && REG_P (op0)
+ && hard_regno_nregs (REGNO (flags_operand2), DImode) == 2
+ && REGNO (flags_operand2) == REGNO (op0))
+ return code == GE ? PLUS : MINUS;
+ return UNKNOWN;
+}
+
+/* Called through CC_STATUS_INIT, which is invoked by final whenever a
+ label is encountered. */
+
+void
+m68k_init_cc ()
+{
+ flags_compare_op0 = flags_compare_op1 = NULL_RTX;
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ flags_valid = FLAGS_VALID_NO;
+}
+
+/* Update flags for a move operation with OPERANDS. Called for move
+ operations where attr_flags_valid returns "set". */
+
+static void
+handle_flags_for_move (rtx *operands)
+{
+ flags_compare_op0 = flags_compare_op1 = NULL_RTX;
+ if (!ADDRESS_REG_P (operands[0]))
+ {
+ flags_valid = FLAGS_VALID_MOVE;
+ flags_operand1 = side_effects_p (operands[0]) ? NULL_RTX : operands[0];
+ if (side_effects_p (operands[1])
+ /* ??? For mem->mem moves, this can discard the source as a
+ valid compare operand. If you assume aligned moves, this
+ is unnecessary, but in theory, we could have an unaligned
+ move overwriting parts of its source. */
+ || modified_in_p (operands[1], current_output_insn))
+ flags_operand2 = NULL_RTX;
+ else
+ flags_operand2 = operands[1];
+ return;
+ }
+ if (flags_operand1 != NULL_RTX
+ && modified_in_p (flags_operand1, current_output_insn))
+ flags_operand1 = NULL_RTX;
+ if (flags_operand2 != NULL_RTX
+ && modified_in_p (flags_operand2, current_output_insn))
+ flags_operand2 = NULL_RTX;
+}
+
+/* Process INSN to remember flag operands if possible. */
+
+static void
+m68k_asm_final_postscan_insn (FILE *, rtx_insn *insn, rtx [], int)
+{
+ enum attr_flags_valid v = get_attr_flags_valid (insn);
+ if (v == FLAGS_VALID_SET)
+ return;
+ /* Comparisons use FLAGS_VALID_SET, so we can be sure we need to clear these
+ now. */
+ flags_compare_op0 = flags_compare_op1 = NULL_RTX;
+
+ if (v == FLAGS_VALID_NO)
+ {
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ return;
+ }
+ else if (v == FLAGS_VALID_UNCHANGED)
+ {
+ if (flags_operand1 != NULL_RTX && modified_in_p (flags_operand1, insn))
+ flags_operand1 = NULL_RTX;
+ if (flags_operand2 != NULL_RTX && modified_in_p (flags_operand2, insn))
+ flags_operand2 = NULL_RTX;
+ return;
+ }
+
+ flags_valid = v;
+ rtx set = single_set (insn);
+ rtx dest = SET_DEST (set);
+ rtx src = SET_SRC (set);
+ if (side_effects_p (dest))
+ dest = NULL_RTX;
+
+ switch (v)
+ {
+ case FLAGS_VALID_YES:
+ case FLAGS_VALID_NOOV:
+ flags_operand1 = dest;
+ flags_operand2 = NULL_RTX;
+ break;
+ case FLAGS_VALID_MOVE:
+ /* fmoves to memory or data registers do not set the condition
+ codes. Normal moves _do_ set the condition codes, but not in
+ a way that is appropriate for comparison with 0, because -0.0
+ would be treated as a negative nonzero number. Note that it
+ isn't appropriate to conditionalize this restriction on
+ HONOR_SIGNED_ZEROS because that macro merely indicates whether
+ we care about the difference between -0.0 and +0.0. */
+ if (dest != NULL_RTX
+ && !FP_REG_P (dest)
+ && (FP_REG_P (src)
+ || GET_CODE (src) == FIX
+ || FLOAT_MODE_P (GET_MODE (dest))))
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ else
+ {
+ flags_operand1 = dest;
+ if (GET_MODE (src) != VOIDmode && !side_effects_p (src)
+ && !modified_in_p (src, insn))
+ flags_operand2 = src;
+ else
+ flags_operand2 = NULL_RTX;
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ return;
+}
-
/* Output a dbCC; jCC sequence. Note we do not handle the
- floating point version of this sequence (Fdbcc). We also
- do not handle alternative conditions when CC_NO_OVERFLOW is
- set. It is assumed that valid_dbcc_comparison_p and flags_in_68881 will
- kick those out before we get here. */
+ floating point version of this sequence (Fdbcc).
+ OPERANDS are as in the two peepholes. CODE is the code
+ returned by m68k_output_branch_<mode>. */
void
-output_dbcc_and_branch (rtx *operands)
+output_dbcc_and_branch (rtx *operands, rtx_code code)
{
- switch (GET_CODE (operands[3]))
+ switch (code)
{
case EQ:
output_asm_insn ("dbeq %0,%l1\n\tjeq %l2", operands);
@@ -1633,6 +1772,14 @@ output_dbcc_and_branch (rtx *operands)
output_asm_insn ("dbls %0,%l1\n\tjls %l2", operands);
break;
+ case PLUS:
+ output_asm_insn ("dbpl %0,%l1\n\tjle %l2", operands);
+ break;
+
+ case MINUS:
+ output_asm_insn ("dbmi %0,%l1\n\tjle %l2", operands);
+ break;
+
default:
gcc_unreachable ();
}
@@ -1790,11 +1937,12 @@ output_scc_di (rtx op, rtx operand1, rtx operand2, rtx dest)
return "";
}
-const char *
-output_btst (rtx *operands, rtx countop, rtx dataop, rtx_insn *insn, int signpos)
+rtx_code
+m68k_output_btst (rtx countop, rtx dataop, rtx_code code, int signpos)
{
- operands[0] = countop;
- operands[1] = dataop;
+ rtx ops[2];
+ ops[0] = countop;
+ ops[1] = dataop;
if (GET_CODE (countop) == CONST_INT)
{
@@ -1805,40 +1953,41 @@ output_btst (rtx *operands, rtx countop, rtx dataop, rtx_insn *insn, int signpos
{
int offset = (count & ~signpos) / 8;
count = count & signpos;
- operands[1] = dataop = adjust_address (dataop, QImode, offset);
+ ops[1] = dataop = adjust_address (dataop, QImode, offset);
+ }
+
+ if (code == EQ || code == NE)
+ {
+ if (count == 31)
+ {
+ output_asm_insn ("tst%.l %1", ops);
+ return code == EQ ? PLUS : MINUS;
+ }
+ if (count == 15)
+ {
+ output_asm_insn ("tst%.w %1", ops);
+ return code == EQ ? PLUS : MINUS;
+ }
+ if (count == 7)
+ {
+ output_asm_insn ("tst%.b %1", ops);
+ return code == EQ ? PLUS : MINUS;
+ }
}
- if (count == signpos)
- cc_status.flags = CC_NOT_POSITIVE | CC_Z_IN_NOT_N;
- else
- cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N;
-
- /* These three statements used to use next_insns_test_no...
- but it appears that this should do the same job. */
- if (count == 31
- && next_insn_tests_no_inequality (insn))
- return "tst%.l %1";
- if (count == 15
- && next_insn_tests_no_inequality (insn))
- return "tst%.w %1";
- if (count == 7
- && next_insn_tests_no_inequality (insn))
- return "tst%.b %1";
/* Try to use `movew to ccr' followed by the appropriate branch insn.
On some m68k variants unfortunately that's slower than btst.
On 68000 and higher, that should also work for all HImode operands. */
if (TUNE_CPU32 || TARGET_COLDFIRE || optimize_size)
{
- if (count == 3 && DATA_REG_P (operands[1])
- && next_insn_tests_no_inequality (insn))
+ if (count == 3 && DATA_REG_P (ops[1]) && (code == EQ || code == NE))
{
- cc_status.flags = CC_NOT_NEGATIVE | CC_Z_IN_NOT_N | CC_NO_OVERFLOW;
- return "move%.w %1,%%ccr";
+ output_asm_insn ("move%.w %1,%%ccr", ops);
+ return code == EQ ? PLUS : MINUS;
}
- if (count == 2 && DATA_REG_P (operands[1])
- && next_insn_tests_no_inequality (insn))
+ if (count == 2 && DATA_REG_P (ops[1]) && (code == EQ || code == NE))
{
- cc_status.flags = CC_NOT_NEGATIVE | CC_INVERTED | CC_NO_OVERFLOW;
- return "move%.w %1,%%ccr";
+ output_asm_insn ("move%.w %1,%%ccr", ops);
+ return code == EQ ? NE : EQ;
}
/* count == 1 followed by bvc/bvs and
count == 0 followed by bcc/bcs are also possible, but need
@@ -1847,7 +1996,28 @@ output_btst (rtx *operands, rtx countop, rtx dataop, rtx_insn *insn, int signpos
cc_status.flags = CC_NOT_NEGATIVE;
}
- return "btst %0,%1";
+ output_asm_insn ("btst %0,%1", ops);
+ return code;
+}
+
+/* Output a bftst instruction for a zero_extract with ZXOP0, ZXOP1 and ZXOP2
+ operands. CODE is the code of the comparison, and we return the code to
+ be actually used in the jump. */
+
+rtx_code
+m68k_output_bftst (rtx zxop0, rtx zxop1, rtx zxop2, rtx_code code)
+{
+ if (zxop1 == const1_rtx && GET_CODE (zxop2) == CONST_INT)
+ {
+ int width = GET_CODE (zxop0) == REG ? 31 : 7;
+ /* Pass 1000 as SIGNPOS argument so that btst will
+ not think we are testing the sign bit for an `and'
+ and assume that nonzero implies a negative result. */
+ return m68k_output_btst (GEN_INT (width - INTVAL (zxop2)), zxop0, code, 1000);
+ }
+ rtx ops[3] = { zxop0, zxop1, zxop2 };
+ output_asm_insn ("bftst %0{%b2:%b1}", ops);
+ return code;
}
/* Return true if X is a legitimate base register. STRICT_P says
@@ -2839,7 +3009,8 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code,
case CONST_DOUBLE:
/* Make 0.0 cheaper than other floating constants to
encourage creating tstsf and tstdf insns. */
- if (outer_code == COMPARE
+ if ((GET_RTX_CLASS (outer_code) == RTX_COMPARE
+ || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE)
&& (x == CONST0_RTX (SFmode) || x == CONST0_RTX (DFmode)))
*total = 4;
else
@@ -2953,7 +3124,8 @@ m68k_rtx_costs (rtx x, machine_mode mode, int outer_code,
return true;
case ZERO_EXTRACT:
- if (outer_code == COMPARE)
+ if (GET_RTX_CLASS (outer_code) == RTX_COMPARE
+ || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE)
*total = 0;
return false;
@@ -3056,6 +3228,8 @@ output_move_simode_const (rtx *operands)
const char *
output_move_simode (rtx *operands)
{
+ handle_flags_for_move (operands);
+
if (GET_CODE (operands[1]) == CONST_INT)
return output_move_simode_const (operands);
else if ((GET_CODE (operands[1]) == SYMBOL_REF
@@ -3072,7 +3246,7 @@ output_move_simode (rtx *operands)
const char *
output_move_himode (rtx *operands)
{
- if (GET_CODE (operands[1]) == CONST_INT)
+ if (GET_CODE (operands[1]) == CONST_INT)
{
if (operands[1] == const0_rtx
&& (DATA_REG_P (operands[0])
@@ -3094,16 +3268,18 @@ output_move_himode (rtx *operands)
return "move%.w %1,%0";
}
else if (CONSTANT_P (operands[1]))
- return "move%.l %1,%0";
+ gcc_unreachable ();
return "move%.w %1,%0";
}
const char *
output_move_qimode (rtx *operands)
{
+ handle_flags_for_move (operands);
+
/* 68k family always modifies the stack pointer by at least 2, even for
byte pushes. The 5200 (ColdFire) does not do this. */
-
+
/* This case is generated by pushqi1 pattern now. */
gcc_assert (!(GET_CODE (operands[0]) == MEM
&& GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
@@ -3134,11 +3310,15 @@ output_move_qimode (rtx *operands)
if (operands[1] == const0_rtx && ADDRESS_REG_P (operands[0]))
return "sub%.l %0,%0";
if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
- return "move%.l %1,%0";
+ gcc_unreachable ();
/* 68k family (including the 5200 ColdFire) does not support byte moves to
from address registers. */
if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
- return "move%.w %1,%0";
+ {
+ if (ADDRESS_REG_P (operands[1]))
+ CC_STATUS_INIT;
+ return "move%.w %1,%0";
+ }
return "move%.b %1,%0";
}
@@ -4136,125 +4316,448 @@ output_addsi3 (rtx *operands)
}
return "add%.l %2,%0";
}
-
-/* Store in cc_status the expressions that the condition codes will
- describe after execution of an instruction whose pattern is EXP.
- Do not alter them if the instruction would not alter the cc's. */
-
-/* On the 68000, all the insns to store in an address register fail to
- set the cc's. However, in some cases these instructions can make it
- possibly invalid to use the saved cc's. In those cases we clear out
- some or all of the saved cc's so they won't be used. */
-void
-notice_update_cc (rtx exp, rtx insn)
+/* Emit a comparison between OP0 and OP1. Return true iff the comparison
+ was reversed. SC1 is an SImode scratch reg, and SC2 a DImode scratch reg,
+ as needed. CODE is the code of the comparison, we return it unchanged or
+ swapped, as necessary. */
+rtx_code
+m68k_output_compare_di (rtx op0, rtx op1, rtx sc1, rtx sc2, rtx_insn *insn,
+ rtx_code code)
{
- if (GET_CODE (exp) == SET)
+ rtx ops[4];
+ ops[0] = op0;
+ ops[1] = op1;
+ ops[2] = sc1;
+ ops[3] = sc2;
+ if (op1 == const0_rtx)
{
- if (GET_CODE (SET_SRC (exp)) == CALL)
- CC_STATUS_INIT;
- else if (ADDRESS_REG_P (SET_DEST (exp)))
+ if (!REG_P (op0) || ADDRESS_REG_P (op0))
{
- if (cc_status.value1 && modified_in_p (cc_status.value1, insn))
- cc_status.value1 = 0;
- if (cc_status.value2 && modified_in_p (cc_status.value2, insn))
- cc_status.value2 = 0;
+ rtx xoperands[2];
+
+ xoperands[0] = sc2;
+ xoperands[1] = op0;
+ output_move_double (xoperands);
+ output_asm_insn ("neg%.l %R0\n\tnegx%.l %0", xoperands);
+ return swap_condition (code);
}
- /* fmoves to memory or data registers do not set the condition
- codes. Normal moves _do_ set the condition codes, but not in
- a way that is appropriate for comparison with 0, because -0.0
- would be treated as a negative nonzero number. Note that it
- isn't appropriate to conditionalize this restriction on
- HONOR_SIGNED_ZEROS because that macro merely indicates whether
- we care about the difference between -0.0 and +0.0. */
- else if (!FP_REG_P (SET_DEST (exp))
- && SET_DEST (exp) != cc0_rtx
- && (FP_REG_P (SET_SRC (exp))
- || GET_CODE (SET_SRC (exp)) == FIX
- || FLOAT_MODE_P (GET_MODE (SET_DEST (exp)))))
- CC_STATUS_INIT;
- /* A pair of move insns doesn't produce a useful overall cc. */
- else if (!FP_REG_P (SET_DEST (exp))
- && !FP_REG_P (SET_SRC (exp))
- && GET_MODE_SIZE (GET_MODE (SET_SRC (exp))) > 4
- && (GET_CODE (SET_SRC (exp)) == REG
- || GET_CODE (SET_SRC (exp)) == MEM
- || GET_CODE (SET_SRC (exp)) == CONST_DOUBLE))
- CC_STATUS_INIT;
- else if (SET_DEST (exp) != pc_rtx)
+ if (find_reg_note (insn, REG_DEAD, op0))
+ {
+ output_asm_insn ("neg%.l %R0\n\tnegx%.l %0", ops);
+ return swap_condition (code);
+ }
+ else
{
- cc_status.flags = 0;
- cc_status.value1 = SET_DEST (exp);
- cc_status.value2 = SET_SRC (exp);
+ /* 'sub' clears %1, and also clears the X cc bit.
+ 'tst' sets the Z cc bit according to the low part of the DImode
+ operand.
+ 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high
+ part. */
+ output_asm_insn ("sub%.l %2,%2\n\ttst%.l %R0\n\tsubx%.l %2,%0", ops);
+ return code;
}
}
- else if (GET_CODE (exp) == PARALLEL
- && GET_CODE (XVECEXP (exp, 0, 0)) == SET)
+
+ if (rtx_equal_p (sc2, op0))
{
- rtx dest = SET_DEST (XVECEXP (exp, 0, 0));
- rtx src = SET_SRC (XVECEXP (exp, 0, 0));
+ output_asm_insn ("sub%.l %R1,%R3\n\tsubx%.l %1,%3", ops);
+ return code;
+ }
+ else
+ {
+ output_asm_insn ("sub%.l %R0,%R3\n\tsubx%.l %0,%3", ops);
+ return swap_condition (code);
+ }
+}
- if (ADDRESS_REG_P (dest))
- CC_STATUS_INIT;
- else if (dest != pc_rtx)
+static void
+remember_compare_flags (rtx op0, rtx op1)
+{
+ if (side_effects_p (op0) || side_effects_p (op1))
+ CC_STATUS_INIT;
+ else
+ {
+ flags_compare_op0 = op0;
+ flags_compare_op1 = op1;
+ flags_operand1 = flags_operand2 = NULL_RTX;
+ flags_valid = FLAGS_VALID_SET;
+ }
+}
+
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_si (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
+
+ remember_compare_flags (op0, op1);
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+ if (op1 == const0_rtx && (TARGET_68020 || TARGET_COLDFIRE || !ADDRESS_REG_P (op0)))
+ output_asm_insn ("tst%.l %0", ops);
+ else if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
+ output_asm_insn ("cmpm%.l %1,%0", ops);
+ else if (REG_P (op1)
+ || (!REG_P (op0) && GET_CODE (op0) != MEM))
+ {
+ output_asm_insn ("cmp%.l %d0,%d1", ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ }
+ else if (!TARGET_COLDFIRE
+ && ADDRESS_REG_P (op0)
+ && GET_CODE (op1) == CONST_INT
+ && INTVAL (op1) < 0x8000
+ && INTVAL (op1) >= -0x8000)
+ output_asm_insn ("cmp%.w %1,%0", ops);
+ else
+ output_asm_insn ("cmp%.l %d1,%d0", ops);
+ return code;
+}
+
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_hi (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
+
+ remember_compare_flags (op0, op1);
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+ if (op1 == const0_rtx)
+ output_asm_insn ("tst%.w %d0", ops);
+ else if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
+ output_asm_insn ("cmpm%.w %1,%0", ops);
+ else if ((REG_P (op1) && !ADDRESS_REG_P (op1))
+ || (!REG_P (op0) && GET_CODE (op0) != MEM))
+ {
+ output_asm_insn ("cmp%.w %d0,%d1", ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ }
+ else
+ output_asm_insn ("cmp%.w %d1,%d0", ops);
+ return code;
+}
+
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_qi (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
+
+ remember_compare_flags (op0, op1);
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+ if (op1 == const0_rtx)
+ output_asm_insn ("tst%.b %d0", ops);
+ else if (GET_CODE (op0) == MEM && GET_CODE (op1) == MEM)
+ output_asm_insn ("cmpm%.b %1,%0", ops);
+ else if (REG_P (op1) || (!REG_P (op0) && GET_CODE (op0) != MEM))
+ {
+ output_asm_insn ("cmp%.b %d0,%d1", ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ }
+ else
+ output_asm_insn ("cmp%.b %d1,%d0", ops);
+ return code;
+}
+
+/* Emit a comparison between OP0 and OP1. CODE is the code of the
+ comparison. It is returned, potentially modified if necessary. */
+rtx_code
+m68k_output_compare_fp (rtx op0, rtx op1, rtx_code code)
+{
+ rtx_code tmp = m68k_find_flags_value (op0, op1, code);
+ if (tmp != UNKNOWN)
+ return tmp;
+
+ rtx ops[2];
+ ops[0] = op0;
+ ops[1] = op1;
+
+ remember_compare_flags (op0, op1);
+
+ machine_mode mode = GET_MODE (op0);
+ std::string prec = mode == SFmode ? "s" : mode == DFmode ? "d" : "x";
+
+ if (op1 == CONST0_RTX (GET_MODE (op0)))
+ {
+ if (FP_REG_P (op0))
{
- cc_status.flags = 0;
- cc_status.value1 = dest;
- cc_status.value2 = src;
+ if (TARGET_COLDFIRE_FPU)
+ output_asm_insn ("ftst%.d %0", ops);
+ else
+ output_asm_insn ("ftst%.x %0", ops);
}
+ else
+ output_asm_insn (("ftst%." + prec + " %0").c_str (), ops);
+ return code;
}
- else
- CC_STATUS_INIT;
- if (cc_status.value2 != 0
- && ADDRESS_REG_P (cc_status.value2)
- && GET_MODE (cc_status.value2) == QImode)
- CC_STATUS_INIT;
- if (cc_status.value2 != 0)
- switch (GET_CODE (cc_status.value2))
- {
- case ASHIFT: case ASHIFTRT: case LSHIFTRT:
- case ROTATE: case ROTATERT:
- /* These instructions always clear the overflow bit, and set
- the carry to the bit shifted out. */
- cc_status.flags |= CC_OVERFLOW_UNUSABLE | CC_NO_CARRY;
- break;
- case PLUS: case MINUS: case MULT:
- case DIV: case UDIV: case MOD: case UMOD: case NEG:
- if (GET_MODE (cc_status.value2) != VOIDmode)
- cc_status.flags |= CC_NO_OVERFLOW;
- break;
- case ZERO_EXTEND:
- /* (SET r1 (ZERO_EXTEND r2)) on this machine
- ends with a move insn moving r2 in r2's mode.
- Thus, the cc's are set for r2.
- This can set N bit spuriously. */
- cc_status.flags |= CC_NOT_NEGATIVE;
+ switch (which_alternative)
+ {
+ case 0:
+ if (TARGET_COLDFIRE_FPU)
+ output_asm_insn ("fcmp%.d %1,%0", ops);
+ else
+ output_asm_insn ("fcmp%.x %1,%0", ops);
+ break;
+ case 1:
+ output_asm_insn (("fcmp%." + prec + " %f1,%0").c_str (), ops);
+ break;
+ case 2:
+ output_asm_insn (("fcmp%." + prec + " %0,%f1").c_str (), ops);
+ std::swap (flags_compare_op0, flags_compare_op1);
+ return swap_condition (code);
+ case 3:
+ /* This is the ftst case, handled earlier. */
+ gcc_unreachable ();
+ }
+ return code;
+}
- default:
- break;
- }
- if (cc_status.value1 && GET_CODE (cc_status.value1) == REG
- && cc_status.value2
- && reg_overlap_mentioned_p (cc_status.value1, cc_status.value2))
- cc_status.value2 = 0;
- /* Check for PRE_DEC in dest modifying a register used in src. */
- if (cc_status.value1 && GET_CODE (cc_status.value1) == MEM
- && GET_CODE (XEXP (cc_status.value1, 0)) == PRE_DEC
- && cc_status.value2
- && reg_overlap_mentioned_p (XEXP (XEXP (cc_status.value1, 0), 0),
- cc_status.value2))
- cc_status.value2 = 0;
- if (((cc_status.value1 && FP_REG_P (cc_status.value1))
- || (cc_status.value2 && FP_REG_P (cc_status.value2))))
- cc_status.flags = CC_IN_68881;
- if (cc_status.value2 && GET_CODE (cc_status.value2) == COMPARE
- && GET_MODE_CLASS (GET_MODE (XEXP (cc_status.value2, 0))) == MODE_FLOAT)
- {
- cc_status.flags = CC_IN_68881;
- if (!FP_REG_P (XEXP (cc_status.value2, 0))
- && FP_REG_P (XEXP (cc_status.value2, 1)))
- cc_status.flags |= CC_REVERSED;
+/* Return an output template for a branch with CODE. */
+const char *
+m68k_output_branch_integer (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "jeq %l3";
+ case NE:
+ return "jne %l3";
+ case GT:
+ return "jgt %l3";
+ case GTU:
+ return "jhi %l3";
+ case LT:
+ return "jlt %l3";
+ case LTU:
+ return "jcs %l3";
+ case GE:
+ return "jge %l3";
+ case GEU:
+ return "jcc %l3";
+ case LE:
+ return "jle %l3";
+ case LEU:
+ return "jls %l3";
+ case PLUS:
+ return "jpl %l3";
+ case MINUS:
+ return "jmi %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a reversed branch with CODE. */
+const char *
+m68k_output_branch_integer_rev (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "jne %l3";
+ case NE:
+ return "jeq %l3";
+ case GT:
+ return "jle %l3";
+ case GTU:
+ return "jls %l3";
+ case LT:
+ return "jge %l3";
+ case LTU:
+ return "jcc %l3";
+ case GE:
+ return "jlt %l3";
+ case GEU:
+ return "jcs %l3";
+ case LE:
+ return "jgt %l3";
+ case LEU:
+ return "jhi %l3";
+ case PLUS:
+ return "jmi %l3";
+ case MINUS:
+ return "jpl %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a scc instruction with CODE. */
+const char *
+m68k_output_scc (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "seq %0";
+ case NE:
+ return "sne %0";
+ case GT:
+ return "sgt %0";
+ case GTU:
+ return "shi %0";
+ case LT:
+ return "slt %0";
+ case LTU:
+ return "scs %0";
+ case GE:
+ return "sge %0";
+ case GEU:
+ return "scc %0";
+ case LE:
+ return "sle %0";
+ case LEU:
+ return "sls %0";
+ case PLUS:
+ return "spl %0";
+ case MINUS:
+ return "smi %0";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a floating point branch
+ instruction with CODE. */
+const char *
+m68k_output_branch_float (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "fjeq %l3";
+ case NE:
+ return "fjne %l3";
+ case GT:
+ return "fjgt %l3";
+ case LT:
+ return "fjlt %l3";
+ case GE:
+ return "fjge %l3";
+ case LE:
+ return "fjle %l3";
+ case ORDERED:
+ return "fjor %l3";
+ case UNORDERED:
+ return "fjun %l3";
+ case UNEQ:
+ return "fjueq %l3";
+ case UNGE:
+ return "fjuge %l3";
+ case UNGT:
+ return "fjugt %l3";
+ case UNLE:
+ return "fjule %l3";
+ case UNLT:
+ return "fjult %l3";
+ case LTGT:
+ return "fjogl %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a reversed floating point branch
+ instruction with CODE. */
+const char *
+m68k_output_branch_float_rev (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "fjne %l3";
+ case NE:
+ return "fjeq %l3";
+ case GT:
+ return "fjngt %l3";
+ case LT:
+ return "fjnlt %l3";
+ case GE:
+ return "fjnge %l3";
+ case LE:
+ return "fjnle %l3";
+ case ORDERED:
+ return "fjun %l3";
+ case UNORDERED:
+ return "fjor %l3";
+ case UNEQ:
+ return "fjogl %l3";
+ case UNGE:
+ return "fjolt %l3";
+ case UNGT:
+ return "fjole %l3";
+ case UNLE:
+ return "fjogt %l3";
+ case UNLT:
+ return "fjoge %l3";
+ case LTGT:
+ return "fjueq %l3";
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Return an output template for a floating point scc
+ instruction with CODE. */
+const char *
+m68k_output_scc_float (rtx_code code)
+{
+ switch (code)
+ {
+ case EQ:
+ return "fseq %0";
+ case NE:
+ return "fsne %0";
+ case GT:
+ return "fsgt %0";
+ case GTU:
+ return "fshi %0";
+ case LT:
+ return "fslt %0";
+ case GE:
+ return "fsge %0";
+ case LE:
+ return "fsle %0";
+ case ORDERED:
+ return "fsor %0";
+ case UNORDERED:
+ return "fsun %0";
+ case UNEQ:
+ return "fsueq %0";
+ case UNGE:
+ return "fsuge %0";
+ case UNGT:
+ return "fsugt %0";
+ case UNLE:
+ return "fsule %0";
+ case UNLT:
+ return "fsult %0";
+ case LTGT:
+ return "fsogl %0";
+ default:
+ gcc_unreachable ();
}
}
@@ -4932,6 +5435,7 @@ const char *
output_andsi3 (rtx *operands)
{
int logval;
+ CC_STATUS_INIT;
if (GET_CODE (operands[2]) == CONST_INT
&& (INTVAL (operands[2]) | 0xffff) == -1
&& (DATA_REG_P (operands[0])
@@ -4941,8 +5445,6 @@ output_andsi3 (rtx *operands)
if (GET_CODE (operands[0]) != REG)
operands[0] = adjust_address (operands[0], HImode, 2);
operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
if (operands[2] == const0_rtx)
return "clr%.w %0";
return "and%.w %2,%0";
@@ -4959,10 +5461,13 @@ output_andsi3 (rtx *operands)
operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
operands[1] = GEN_INT (logval % 8);
}
- /* This does not set condition codes in a standard way. */
- CC_STATUS_INIT;
return "bclr %1,%0";
}
+ /* Only a standard logical operation on the whole word sets the
+ condition codes in a way we can use. */
+ if (!side_effects_p (operands[0]))
+ flags_operand1 = operands[0];
+ flags_valid = FLAGS_VALID_YES;
return "and%.l %2,%0";
}
@@ -4970,6 +5475,7 @@ const char *
output_iorsi3 (rtx *operands)
{
register int logval;
+ CC_STATUS_INIT;
if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >> 16 == 0
&& (DATA_REG_P (operands[0])
@@ -4978,8 +5484,6 @@ output_iorsi3 (rtx *operands)
{
if (GET_CODE (operands[0]) != REG)
operands[0] = adjust_address (operands[0], HImode, 2);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
if (INTVAL (operands[2]) == 0xffff)
return "mov%.w %2,%0";
return "or%.w %2,%0";
@@ -4996,9 +5500,13 @@ output_iorsi3 (rtx *operands)
operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
operands[1] = GEN_INT (logval % 8);
}
- CC_STATUS_INIT;
return "bset %1,%0";
}
+ /* Only a standard logical operation on the whole word sets the
+ condition codes in a way we can use. */
+ if (!side_effects_p (operands[0]))
+ flags_operand1 = operands[0];
+ flags_valid = FLAGS_VALID_YES;
return "or%.l %2,%0";
}
@@ -5006,6 +5514,7 @@ const char *
output_xorsi3 (rtx *operands)
{
register int logval;
+ CC_STATUS_INIT;
if (GET_CODE (operands[2]) == CONST_INT
&& INTVAL (operands[2]) >> 16 == 0
&& (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))
@@ -5013,8 +5522,6 @@ output_xorsi3 (rtx *operands)
{
if (! DATA_REG_P (operands[0]))
operands[0] = adjust_address (operands[0], HImode, 2);
- /* Do not delete a following tstl %0 insn; that would be incorrect. */
- CC_STATUS_INIT;
if (INTVAL (operands[2]) == 0xffff)
return "not%.w %0";
return "eor%.w %2,%0";
@@ -5031,9 +5538,13 @@ output_xorsi3 (rtx *operands)
operands[0] = adjust_address (operands[0], SImode, 3 - (logval / 8));
operands[1] = GEN_INT (logval % 8);
}
- CC_STATUS_INIT;
return "bchg %1,%0";
}
+ /* Only a standard logical operation on the whole word sets the
+ condition codes in a way we can use. */
+ if (!side_effects_p (operands[0]))
+ flags_operand1 = operands[0];
+ flags_valid = FLAGS_VALID_YES;
return "eor%.l %2,%0";
}
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index fc65e524b13..39955b05f1d 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -671,36 +671,6 @@ __transfer_from_trampoline () \
#define FUNCTION_MODE QImode
-/* Tell final.c how to eliminate redundant test instructions. */
-
-/* Here we define machine-dependent flags and fields in cc_status
- (see `conditions.h'). */
-
-/* Set if the cc value is actually in the 68881, so a floating point
- conditional branch must be output. */
-#define CC_IN_68881 04000
-
-/* On the 68000, all the insns to store in an address register fail to
- set the cc's. However, in some cases these instructions can make it
- possibly invalid to use the saved cc's. In those cases we clear out
- some or all of the saved cc's so they won't be used. */
-#define NOTICE_UPDATE_CC(EXP,INSN) notice_update_cc (EXP, INSN)
-
-/* The shift instructions always clear the overflow bit. */
-#define CC_OVERFLOW_UNUSABLE 01000
-
-/* The shift instructions use the carry bit in a way not compatible with
- conditional branches. conditions.h uses CC_NO_OVERFLOW for this purpose.
- Rename it to something more understandable. */
-#define CC_NO_CARRY CC_NO_OVERFLOW
-
-#define OUTPUT_JUMP(NORMAL, FLOAT, NO_OV) \
-do { if (cc_prev_status.flags & CC_IN_68881) \
- return FLOAT; \
- if (cc_prev_status.flags & CC_NO_OVERFLOW) \
- return NO_OV; \
- return NORMAL; } while (0)
-
/* Control the assembler format that we output. */
#define ASM_APP_ON "#APP\n"
@@ -900,6 +870,8 @@ do { if (cc_prev_status.flags & CC_IN_68881) \
#define PRINT_OPERAND_ADDRESS(FILE, ADDR) print_operand_address (FILE, ADDR)
+#define CC_STATUS_INIT m68k_init_cc ()
+
#include "config/m68k/m68k-opts.h"
enum fpu_type
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 31e8767e7e3..454f822e392 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -250,6 +250,18 @@
;; Alternative is OK for ColdFire.
(define_attr "ok_for_coldfire" "yes,no" (const_string "yes"))
+;; Instruction sets flags predictably to allow a following comparison to be
+;; elided.
+;; "no" means we should clear all flag state. "yes" means the destination
+;; register is valid. "noov" is similar but does not allow tests that rely
+;; on the overflow flag. "unchanged" means the instruction does not set the
+;; flags (but we should still verify none of the remembered operands are
+;; clobbered). "move" is a special case for which we remember both the
+;; destination and the source. "set" is another special case where the
+;; instruction pattern already performs the update and no more work is
+;; required in postscan_insn.
+(define_attr "flags_valid" "no,yes,set,noov,move,unchanged" (const_string "no"))
+
;; Define 'enabled' attribute.
(define_attr "enabled" ""
(cond [(and (match_test "TARGET_COLDFIRE")
@@ -303,150 +315,129 @@
DONE;
})
-;; We don't want to allow a constant operand for test insns because
-;; (set (cc0) (const_int foo)) has no mode information. Such insns will
-;; be folded while optimizing anyway.
-
-(define_insn "tstdi"
- [(set (cc0)
- (compare (match_operand:DI 0 "nonimmediate_operand" "am,d")
- (const_int 0)))
- (clobber (match_scratch:SI 1 "=X,d"))
- (clobber (match_scratch:DI 2 "=d,X"))]
+;; Compare instructions, combined with jumps or scc operations.
+
+(define_insn "beq0_di"
+ [(set (pc)
+ (if_then_else (eq (match_operand:DI 0 "general_operand" "d*a,o,<>")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ",,"))
+ (pc)))
+ (clobber (match_scratch:SI 2 "=d,&d,d"))]
""
{
- if (which_alternative == 0)
- {
- rtx xoperands[2];
-
- xoperands[0] = operands[2];
- xoperands[1] = operands[0];
- output_move_double (xoperands);
- cc_status.flags |= CC_REVERSED; /*|*/
- return "neg%.l %R2\;negx%.l %2";
- }
- if (find_reg_note (insn, REG_DEAD, operands[0]))
+ rtx_code code = m68k_find_flags_value (operands[0], const0_rtx, EQ);
+ if (code == EQ)
+ return "jeq %l1";
+ if (which_alternative == 2)
+ return "move%.l %0,%2\;or%.l %0,%2\;jeq %l1";
+ if (GET_CODE (operands[0]) == REG)
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ else
+ operands[3] = adjust_address (operands[0], SImode, 4);
+ if (! ADDRESS_REG_P (operands[0]))
{
- cc_status.flags |= CC_REVERSED; /*|*/
- return "neg%.l %R0\;negx%.l %0";
+ if (reg_overlap_mentioned_p (operands[2], operands[0]))
+ {
+ if (reg_overlap_mentioned_p (operands[2], operands[3]))
+ return "or%.l %0,%2\;jeq %l1";
+ else
+ return "or%.l %3,%2\;jeq %l1";
+ }
+ return "move%.l %0,%2\;or%.l %3,%2\;jeq %l1";
}
+ operands[4] = gen_label_rtx();
+ if (TARGET_68020 || TARGET_COLDFIRE)
+ output_asm_insn ("tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1", operands);
else
- /*
- 'sub' clears %1, and also clears the X cc bit
- 'tst' sets the Z cc bit according to the low part of the DImode operand
- 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high part.
- */
- return "sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0";
-})
-
-;; If you think that the 68020 does not support tstl a0,
-;; reread page B-167 of the 68020 manual more carefully.
-(define_insn "*tstsi_internal_68020_cf"
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
- (const_int 0)))]
- "TARGET_68020 || TARGET_COLDFIRE"
- "tst%.l %0"
- [(set_attr "type" "tst_l")])
-
-;; On an address reg, cmpw may replace cmpl.
-(define_insn "*tstsi_internal"
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "dm,r")
- (const_int 0)))]
- "!(TARGET_68020 || TARGET_COLDFIRE)"
- "@
- tst%.l %0
- cmp%.w #0,%0"
- [(set_attr "type" "tst_l,cmp")])
-
-;; This can't use an address register, because comparisons
-;; with address registers as second operand always test the whole word.
-(define_insn "*tsthi_internal"
- [(set (cc0)
- (compare (match_operand:HI 0 "nonimmediate_operand" "dm")
- (const_int 0)))]
- ""
- "tst%.w %0"
- [(set_attr "type" "tst")])
-
-(define_insn "*tstqi_internal"
- [(set (cc0)
- (compare (match_operand:QI 0 "nonimmediate_operand" "dm")
- (const_int 0)))]
- ""
- "tst%.b %0"
- [(set_attr "type" "tst")])
-
-(define_insn "tst<mode>_68881"
- [(set (cc0)
- (compare (match_operand:FP 0 "general_operand" "f<FP:dreg>m")
- (match_operand:FP 1 "const0_operand" "H")))]
- "TARGET_68881"
-{
- cc_status.flags = CC_IN_68881;
- if (FP_REG_P (operands[0]))
- return "ftst%.x %0";
- return "ftst%.<FP:prec> %0";
-}
- [(set_attr "type" "ftst")])
-
-(define_insn "tst<mode>_cf"
- [(set (cc0)
- (compare (match_operand:FP 0 "general_operand" "f<FP:dreg><Q>U")
- (match_operand:FP 1 "const0_operand" "H")))]
- "TARGET_COLDFIRE_FPU"
-{
- cc_status.flags = CC_IN_68881;
- if (FP_REG_P (operands[0]))
- return "ftst%.d %0";
- return "ftst%.<FP:prec> %0";
-}
- [(set_attr "type" "ftst")])
-
-
-;; compare instructions.
+ output_asm_insn ("cmp%.w #0,%0\;jne %l4\;cmp%.w #0,%3\;jeq %l1", operands);
+ (*targetm.asm_out.internal_label) (asm_out_file, "L",
+ CODE_LABEL_NUMBER (operands[4]));
+ return "";
+})
-(define_insn "*cmpdi_internal"
- [(set (cc0)
- (compare (match_operand:DI 1 "nonimmediate_operand" "0,d")
- (match_operand:DI 2 "general_operand" "d,0")))
- (clobber (match_scratch:DI 0 "=d,d"))]
+(define_insn "bne0_di"
+ [(set (pc)
+ (if_then_else (ne (match_operand:DI 0 "general_operand" "d,o,*a")
+ (const_int 0))
+ (label_ref (match_operand 1 "" ",,"))
+ (pc)))
+ (clobber (match_scratch:SI 2 "=d,&d,X"))]
""
{
- if (rtx_equal_p (operands[0], operands[1]))
- return "sub%.l %R2,%R0\;subx%.l %2,%0";
+ rtx_code code = m68k_find_flags_value (operands[0], const0_rtx, NE);
+ if (code == NE)
+ return "jne %l1";
+ if (GET_CODE (operands[0]) == REG)
+ operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else
+ operands[3] = adjust_address (operands[0], SImode, 4);
+ if (!ADDRESS_REG_P (operands[0]))
{
- cc_status.flags |= CC_REVERSED; /*|*/
- return "sub%.l %R1,%R0\;subx%.l %1,%0";
+ if (reg_overlap_mentioned_p (operands[2], operands[0]))
+ {
+ if (reg_overlap_mentioned_p (operands[2], operands[3]))
+ return "or%.l %0,%2\;jne %l1";
+ else
+ return "or%.l %3,%2\;jne %l1";
+ }
+ return "move%.l %0,%2\;or%.l %3,%2\;jne %l1";
}
+ if (TARGET_68020 || TARGET_COLDFIRE)
+ return "tst%.l %0\;jne %l1\;tst%.l %3\;jne %l1";
+ else
+ return "cmp%.w #0,%0\;jne %l1\;cmp%.w #0,%3\;jne %l1";
})
-(define_insn "cmpdi"
- [(set (cc0)
- (compare (match_operand:DI 0 "nonimmediate_operand")
- (match_operand:DI 1 "general_operand")))
- (clobber (match_scratch:DI 2))]
+(define_insn "cbranchdi4_insn"
+ [(set (pc)
+ (if_then_else (match_operator 1 "ordered_comparison_operator"
+ [(match_operand:DI 2 "nonimmediate_operand" "0,d,am,d")
+ (match_operand:DI 3 "general_operand" "d,0,C0,C0")])
+ (label_ref (match_operand 4 ""))
+ (pc)))
+ (clobber (match_scratch:DI 0 "=d,d,d,X"))
+ (clobber (match_scratch:SI 5 "=X,X,X,d"))]
""
- "")
-
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_di (operands[2], operands[3], operands[5], operands[0], insn, code);
+ operands[3] = operands[4];
+ return m68k_output_branch_integer (code);
+})
(define_expand "cbranchdi4"
- [(set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(match_operand:DI 1 "nonimmediate_operand")
- (match_operand:DI 2 "general_operand")])
- (label_ref (match_operand 3 ""))
- (pc)))]
+ [(parallel
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:DI 1 "nonimmediate_operand")
+ (match_operand:DI 2 "general_operand")])
+ (label_ref (match_operand 3 ""))
+ (pc)))
+ (clobber (match_scratch:DI 4 ""))
+ (clobber (match_scratch:SI 5 ""))])]
""
{
- if (operands[2] == const0_rtx)
- emit_insn (gen_tstdi (operands[1]));
- else
- emit_insn (gen_cmpdi (operands[1], operands[2]));
- operands[1] = cc0_rtx;
- operands[2] = const0_rtx;
+ rtx_code code = GET_CODE (operands[0]);
+ if ((code == GE || code == LT) && operands[2] == const0_rtx)
+ {
+ rtx xop1 = operand_subword_force (operands[1], 0, DImode);
+ rtx xop2 = operand_subword_force (operands[2], 0, DImode);
+ /* gen_cbranchsi4 won't use anything from operands[0] other than the
+ code. */
+ emit_jump_insn (gen_cbranchsi4 (operands[0], xop1, xop2, operands[3]));
+ DONE;
+ }
+ if (code == EQ && operands[2] == const0_rtx)
+ {
+ emit_jump_insn (gen_beq0_di (operands[1], operands[3]));
+ DONE;
+ }
+ if (code == NE && operands[2] == const0_rtx)
+ {
+ emit_jump_insn (gen_bne0_di (operands[1], operands[3]));
+ DONE;
+ }
})
(define_expand "cstoredi4"
@@ -456,40 +447,38 @@
(match_operand:DI 3 "general_operand")]))]
""
{
- if (operands[3] == const0_rtx)
- emit_insn (gen_tstdi (operands[2]));
- else
- emit_insn (gen_cmpdi (operands[2], operands[3]));
- operands[2] = cc0_rtx;
- operands[3] = const0_rtx;
+ rtx_code code = GET_CODE (operands[1]);
+ if ((code == GE || code == LT) && operands[3] == const0_rtx)
+ {
+ rtx xop2 = operand_subword_force (operands[2], 0, DImode);
+ rtx xop3 = operand_subword_force (operands[3], 0, DImode);
+ /* gen_cstoresi4 won't use anything from operands[1] other than the
+ code. */
+ emit_jump_insn (gen_cstoresi4 (operands[0], operands[1], xop2, xop3));
+ DONE;
+ }
})
+(define_mode_iterator CMPMODE [QI HI SI])
-(define_expand "cbranchsi4"
- [(set (cc0)
- (compare (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (set (pc)
+(define_expand "cbranch<mode>4"
+ [(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "")
+ (match_operand:CMPMODE 2 "m68k_comparison_operand" "")])
(label_ref (match_operand 3 ""))
(pc)))]
""
"")
-(define_expand "cstoresi4"
- [(set (cc0)
- (compare (match_operand:SI 2 "nonimmediate_operand" "")
- (match_operand:SI 3 "general_operand" "")))
- (set (match_operand:QI 0 "register_operand")
+(define_expand "cstore<mode>4"
+ [(set (match_operand:QI 0 "register_operand")
(match_operator:QI 1 "ordered_comparison_operator"
- [(cc0) (const_int 0)]))]
+ [(match_operand:CMPMODE 2 "nonimmediate_operand" "")
+ (match_operand:CMPMODE 3 "m68k_comparison_operand" "")]))]
""
"")
-
-;; A composite of the cmp, cmpa, cmpi & cmpm m68000 op codes.
-;;
;; In theory we ought to be able to use some 'S' constraints and
;; operand predicates that allow PC-rel addressing modes in the
;; comparison patterns and expanders below. But we would have to be
@@ -497,315 +486,357 @@
;; both operands and determining whether or not we emit the operands in
;; order or reversed is not trivial to do just based on the constraints
;; and operand predicates. So to be safe, just don't allow the PC-rel
-;; versions in the various comparison expanders, patterns, for comparisons.
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "rKT,rKs,mr,ma,>")
- (match_operand:SI 1 "general_operand" "mr,ma,KTr,Ksr,>")))]
+
+(define_mode_attr scc0_constraints [(QI "=d,d,d") (HI "=d,d,d,d,d") (SI "=d,d,d,d,d,d")])
+(define_mode_attr cmp1_constraints [(QI "dn,dm,>") (HI "rnm,d,n,m,>") (SI "r,r,r,mr,ma,>")])
+(define_mode_attr cmp2_constraints [(QI "dm,nd,>") (HI "d,rnm,m,n,>") (SI "mrC0,mr,ma,KTrC0,Ksr,>")])
+
+;; Note that operand 0 of an SCC insn is supported in the hardware as
+;; memory, but we cannot allow it to be in memory in case the address
+;; needs to be reloaded.
+
+(define_mode_attr scc0_cf_constraints [(QI "=d") (HI "=d") (SI "=d,d,d")])
+(define_mode_attr cmp1_cf_constraints [(QI "dm") (HI "dm") (SI "mr,r,rm")])
+(define_mode_attr cmp2_cf_constraints [(QI "C0") (HI "C0") (SI "r,mrKs,C0")])
+(define_mode_attr cmp2_cf_predicate [(QI "const0_operand") (HI "const0_operand") (SI "general_operand")])
+
+(define_insn "cbranch<mode>4_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_constraints>")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
"!TARGET_COLDFIRE"
{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- return "cmpm%.l %1,%0";
- if (REG_P (operands[1])
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
- {
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.l %d0,%d1";
- }
- if (ADDRESS_REG_P (operands[0])
- && GET_CODE (operands[1]) == CONST_INT
- && INTVAL (operands[1]) < 0x8000
- && INTVAL (operands[1]) >= -0x8000)
- return "cmp%.w %1,%0";
- return "cmp%.l %d1,%d0";
-})
-
-(define_insn "*cmpsi_cf"
- [(set (cc0)
- (compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r")
- (match_operand:SI 1 "general_operand" "r,mrKs")))]
- "TARGET_COLDFIRE"
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "flags_valid" "set")])
+
+(define_insn "cbranch<mode>4_insn_rev"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_constraints>")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "!TARGET_COLDFIRE"
{
- if (REG_P (operands[1])
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
- {
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.l %d0,%d1";
- }
- return "cmp%.l %d1,%d0";
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer_rev (code);
}
- [(set_attr "type" "cmp_l")])
+ [(set_attr "flags_valid" "set")])
-(define_expand "cbranchhi4"
- [(set (cc0)
- (compare (match_operand:HI 1 "nonimmediate_operand" "")
- (match_operand:HI 2 "m68k_subword_comparison_operand" "")))
- (set (pc)
+(define_insn "cbranch<mode>4_insn_cf"
+ [(set (pc)
(if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 2 "<cmp2_cf_predicate>" "<cmp2_cf_constraints>")])
(label_ref (match_operand 3 ""))
(pc)))]
- ""
- "")
+ "TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_expand "cstorehi4"
- [(set (cc0)
- (compare (match_operand:HI 2 "nonimmediate_operand" "")
- (match_operand:HI 3 "m68k_subword_comparison_operand" "")))
- (set (match_operand:QI 0 "register_operand")
- (match_operator:QI 1 "ordered_comparison_operator"
- [(cc0) (const_int 0)]))]
- ""
- "")
+(define_insn "cbranch<mode>4_insn_cf_rev"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 2 "<cmp2_cf_predicate>" "<cmp2_cf_constraints>")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ return m68k_output_branch_integer_rev (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>")
- (match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))]
+(define_insn "cstore<mode>4_insn"
+ [(set (match_operand:QI 0 "register_operand" "<scc0_constraints>")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 2 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 3 "general_operand" "<cmp2_constraints>")]))]
"!TARGET_COLDFIRE"
{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- return "cmpm%.w %1,%0";
- if ((REG_P (operands[1]) && !ADDRESS_REG_P (operands[1]))
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
- {
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.w %d0,%d1";
- }
- return "cmp%.w %d1,%d0";
-})
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_<mode> (operands[2], operands[3], code);
+ return m68k_output_scc (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_expand "cbranchqi4"
- [(set (cc0)
- (compare (match_operand:QI 1 "nonimmediate_operand" "")
- (match_operand:QI 2 "m68k_subword_comparison_operand" "")))
- (set (pc)
- (if_then_else (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
+(define_insn "cstore<mode>4_insn_cf"
+ [(set (match_operand:QI 0 "register_operand" "<scc0_cf_constraints>")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 2 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 3 "<cmp2_cf_predicate>" "<cmp2_cf_constraints>")]))]
+ "TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_<mode> (operands[2], operands[3], code);
+ return m68k_output_scc (code);
+}
+ [(set_attr "flags_valid" "set")])
+
+;; ColdFire/5200 only allows "<Q>" type addresses when the bit position is
+;; specified as a constant, so we must disable all patterns that may extract
+;; from a MEM at a constant bit position if we can't use this as a constraint.
+
+(define_insn "cbranchsi4_btst_mem_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:QI 1 "memory_src_operand" "oS,o")
+ (const_int 1)
+ (minus:SI (const_int 7)
+ (match_operand:SI 2 "general_operand" "di,d")))
+ (const_int 0)])
(label_ref (match_operand 3 ""))
(pc)))]
""
- "")
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_btst (operands[2], operands[1], code, 7);
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "ok_for_coldfire" "no,yes")])
-(define_expand "cstoreqi4"
- [(set (cc0)
- (compare (match_operand:QI 2 "nonimmediate_operand" "")
- (match_operand:QI 3 "m68k_subword_comparison_operand" "")))
- (set (match_operand:QI 0 "register_operand")
- (match_operator:QI 1 "ordered_comparison_operator"
- [(cc0) (const_int 0)]))]
- ""
- "")
+(define_insn "cbranchsi4_btst_reg_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:SI 1 "register_operand" "d")
+ (const_int 1)
+ (minus:SI (const_int 31)
+ (match_operand:SI 2 "general_operand" "di")))
+ (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "!(CONST_INT_P (operands[1]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_btst (operands[2], operands[1], code, 31);
+ return m68k_output_branch_integer (code);
+})
-(define_insn ""
- [(set (cc0)
- (compare (match_operand:QI 0 "nonimmediate_operand" "dn,dm,>")
- (match_operand:QI 1 "general_operand" "dm,nd,>")))]
- "!TARGET_COLDFIRE"
+;; Nonoffsettable mem refs are ok in this one pattern
+;; since we don't try to adjust them.
+(define_insn "cbranchsi4_btst_mem_insn_1"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
+ (const_int 1)
+ (match_operand:SI 2 "const_int_operand" "n"))
+ (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "!TARGET_COLDFIRE && (unsigned) INTVAL (operands[2]) < 8"
{
- if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
- return "cmpm%.b %1,%0";
- if (REG_P (operands[1])
- || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
+ rtx_code code = GET_CODE (operands[0]);
+ operands[2] = GEN_INT (7 - INTVAL (operands[2]));
+ code = m68k_output_btst (operands[2], operands[1], code, 7);
+ return m68k_output_branch_integer (code);
+})
+
+(define_insn "cbranchsi4_btst_reg_insn_1"
+ [(set (pc)
+ (if_then_else (match_operator 0 "equality_comparison_operator"
+ [(zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do,dQ")
+ (const_int 1)
+ (match_operand:SI 2 "const_int_operand" "n,n"))
+ (const_int 0)])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "!(REG_P (operands[1]) && !IN_RANGE (INTVAL (operands[2]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ if (GET_CODE (operands[1]) == MEM)
{
- cc_status.flags |= CC_REVERSED; /*|*/
- return "cmp%.b %d0,%d1";
+ operands[1] = adjust_address (operands[1], QImode,
+ INTVAL (operands[2]) / 8);
+ operands[2] = GEN_INT (7 - INTVAL (operands[2]) % 8);
+ code = m68k_output_btst (operands[2], operands[1], code, 7);
}
- return "cmp%.b %d1,%d0";
+ else
+ {
+ operands[2] = GEN_INT (31 - INTVAL (operands[2]));
+ code = m68k_output_btst (operands[2], operands[1], code, 31);
+ }
+ return m68k_output_branch_integer (code);
+}
+ [(set_attr "ok_for_coldfire" "no,yes")])
+
+(define_mode_iterator BTST [QI SI])
+(define_mode_attr btst_predicate [(QI "memory_operand") (SI "register_operand")])
+(define_mode_attr btst_constraint [(QI "o") (SI "d")])
+(define_mode_attr btst_range [(QI "7") (SI "31")])
+
+;; Special patterns for optimizing bit-field instructions.
+(define_insn "cbranch_bftst<mode>_insn"
+ [(set (pc)
+ (if_then_else (match_operator 0 "ordered_comparison_operator"
+ [(zero_extract:SI (match_operand:BTST 1 "<btst_predicate>" "<btst_constraint>")
+ (match_operand:SI 2 "const_int_operand" "n")
+ (match_operand:SI 3 "general_operand" "dn"))
+ (const_int 0)])
+ (label_ref (match_operand 4 ""))
+ (pc)))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (!REG_P (operands[1]) || !CONST_INT_P (operands[3])
+ || IN_RANGE (INTVAL (operands[3]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_bftst (operands[1], operands[2], operands[3], code);
+ operands[3] = operands[4];
+ return m68k_output_branch_integer (code);
})
+(define_insn "cstore_bftst<mode>_insn"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (match_operator:QI 1 "ordered_comparison_operator"
+ [(zero_extract:SI (match_operand:BTST 2 "<btst_predicate>" "<btst_constraint>")
+ (match_operand:SI 3 "const_int_operand" "n")
+ (match_operand:SI 4 "general_operand" "dn"))
+ (const_int 0)]))]
+ "TARGET_68020 && TARGET_BITFIELD
+ && (!REG_P (operands[2]) || !CONST_INT_P (operands[4])
+ || IN_RANGE (INTVAL (operands[4]), 0, 31))"
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_bftst (operands[2], operands[3], operands[4], code);
+ return m68k_output_scc (code);
+})
+
+;; Floating point comparison patterns
(define_expand "cbranch<mode>4"
- [(set (cc0)
- (compare (match_operand:FP 1 "register_operand" "")
- (match_operand:FP 2 "fp_src_operand" "")))
- (set (pc)
+ [(set (pc)
(if_then_else (match_operator 0 "comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:FP 1 "register_operand" "")
+ (match_operand:FP 2 "fp_src_operand" "")])
(label_ref (match_operand 3 ""))
(pc)))]
"TARGET_HARD_FLOAT"
"")
+;; ??? This presumably tries to allow tests against zero for coldfire, but
+;; it would have to test operands[3] and use CONST0_RTX (mode).
(define_expand "cstore<mode>4"
- [(set (cc0)
- (compare (match_operand:FP 2 "register_operand" "")
- (match_operand:FP 3 "fp_src_operand" "")))
- (set (match_operand:QI 0 "register_operand")
+ [(set (match_operand:QI 0 "register_operand")
(match_operator:QI 1 "m68k_cstore_comparison_operator"
- [(cc0) (const_int 0)]))]
+ [(match_operand:FP 2 "register_operand" "")
+ (match_operand:FP 3 "fp_src_operand" "")]))]
"TARGET_HARD_FLOAT && !(TUNE_68060 || TARGET_COLDFIRE_FPU)"
"if (TARGET_COLDFIRE && operands[2] != const0_rtx)
FAIL;")
-(define_insn "*cmp<mode>_68881"
- [(set (cc0)
- (compare (match_operand:FP 0 "fp_src_operand" "f,f,<FP:dreg>mF")
- (match_operand:FP 1 "fp_src_operand" "f,<FP:dreg>mF,f")))]
+(define_insn "cbranch<mode>4_insn_68881"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg>mF,f<FP:dreg>m")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg>mF,f,H")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
"TARGET_68881
- && (register_operand (operands[0], <MODE>mode)
- || register_operand (operands[1], <MODE>mode))"
- "@
- fcmp%.x %1,%0
- fcmp%.<FP:prec> %f1,%0
- fcmp%.<FP:prec> %0,%f1"
- [(set_attr "type" "fcmp")])
-
-(define_insn "*cmp<mode>_cf"
- [(set (cc0)
- (compare (match_operand:FP 0 "fp_src_operand" "f,f,<FP:dreg><Q>U")
- (match_operand:FP 1 "fp_src_operand" "f,<FP:dreg><Q>U,f")))]
- "TARGET_COLDFIRE_FPU
- && (register_operand (operands[0], <MODE>mode)
- || register_operand (operands[1], <MODE>mode))"
- "@
- fcmp%.d %1,%0
- fcmp%.<FP:prec> %f1,%0
- fcmp%.<FP:prec> %0,%f1"
- [(set_attr "type" "fcmp")])
-
-;; Recognizers for btst instructions.
-
-;; ColdFire/5200 only allows "<Q>" type addresses when the bit position is
-;; specified as a constant, so we must disable all patterns that may extract
-;; from a MEM at a constant bit position if we can't use this as a constraint.
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_src_operand" "oS")
- (const_int 1)
- (minus:SI (const_int 7)
- (match_operand:SI 1 "general_operand" "di")))
- (const_int 0)))]
- "!TARGET_COLDFIRE"
-{
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
-
-;; This is the same as the above pattern except for the constraints. The 'i'
-;; has been deleted.
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
- (const_int 1)
- (minus:SI (const_int 7)
- (match_operand:SI 1 "general_operand" "d")))
- (const_int 0)))]
- "TARGET_COLDFIRE"
-{
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (const_int 1)
- (minus:SI (const_int 31)
- (match_operand:SI 1 "general_operand" "di")))
- (const_int 0)))]
- "!(CONST_INT_P (operands[1]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
-
-;; The following two patterns are like the previous two
-;; except that they use the fact that bit-number operands
-;; are automatically masked to 3 or 5 bits.
-
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
- (const_int 1)
- (minus:SI (const_int 7)
- (and:SI
- (match_operand:SI 1 "register_operand" "d")
- (const_int 7))))
- (const_int 0)))]
- ""
-{
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (const_int 1)
- (minus:SI (const_int 31)
- (and:SI
- (match_operand:SI 1 "register_operand" "d")
- (const_int 31))))
- (const_int 0)))]
- ""
+(define_insn "cbranch<mode>4_insn_cf"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg><Q>U,f<FP:dreg><Q>U")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg><Q>U,f,H")])
+ (label_ref (match_operand 3 ""))
+ (pc)))]
+ "TARGET_COLDFIRE_FPU
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-;; Nonoffsettable mem refs are ok in this one pattern
-;; since we don't try to adjust them.
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "m")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n"))
- (const_int 0)))]
- "(unsigned) INTVAL (operands[1]) < 8 && !TARGET_COLDFIRE"
+(define_insn "cbranch<mode>4_insn_rev_68881"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg>mF,f<FP:dreg>m")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg>mF,f,H")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "TARGET_68881
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- operands[1] = GEN_INT (7 - INTVAL (operands[1]));
- return output_btst (operands, operands[1], operands[0], insn, 7);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float_rev (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "do")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n"))
- (const_int 0)))]
- "!TARGET_COLDFIRE
- && !(REG_P (operands[0]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
+(define_insn "cbranch<mode>4_insn_rev_cf"
+ [(set (pc)
+ (if_then_else (match_operator 0 "comparison_operator"
+ [(match_operand:FP 1 "fp_src_operand" "f,f,<FP:dreg><Q>U,f<FP:dreg><Q>U")
+ (match_operand:FP 2 "fp_src_operand" "f,<FP:dreg><Q>U,f,H")])
+ (pc)
+ (label_ref (match_operand 3 ""))))]
+ "TARGET_COLDFIRE_FPU
+ && (register_operand (operands[1], <MODE>mode)
+ || register_operand (operands[2], <MODE>mode)
+ || const0_operand (operands[2], <MODE>mode))"
{
- if (GET_CODE (operands[0]) == MEM)
- {
- operands[0] = adjust_address (operands[0], QImode,
- INTVAL (operands[1]) / 8);
- operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
- return output_btst (operands, operands[1], operands[0], insn, 7);
- }
- operands[1] = GEN_INT (31 - INTVAL (operands[1]));
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_fp (operands[1], operands[2], code);
+ return m68k_output_branch_float_rev (code);
+}
+ [(set_attr "flags_valid" "set")])
-;; This is the same as the above pattern except for the constraints.
-;; The 'o' has been replaced with 'Q'.
+(define_insn "cstore<mode>4_insn_68881"
+ [(set (match_operand:QI 0 "register_operand" "=d,d,d,d")
+ (match_operator:QI 1 "m68k_cstore_comparison_operator"
+ [(match_operand:FP 2 "fp_src_operand" "f,f,<FP:dreg>mF,f<FP:dreg>m")
+ (match_operand:FP 3 "fp_src_operand" "f,<FP:dreg>mF,f,H")]))]
+ "TARGET_HARD_FLOAT && !(TUNE_68060 || TARGET_COLDFIRE_FPU)
+ && (register_operand (operands[2], <MODE>mode)
+ || register_operand (operands[3], <MODE>mode)
+ || const0_operand (operands[3], <MODE>mode))"
+{
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_fp (operands[2], operands[3], code);
+ return m68k_output_scc_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-(define_insn ""
- [(set
- (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "dQ")
- (const_int 1)
- (match_operand:SI 1 "const_int_operand" "n"))
- (const_int 0)))]
- "TARGET_COLDFIRE
- && !(REG_P (operands[0]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
+;; Test against zero only for coldfire floating point cstore.
+(define_insn "cstore<mode>4_insn_cf"
+ [(set (match_operand:QI 0 "register_operand" "=d")
+ (match_operator:QI 1 "m68k_cstore_comparison_operator"
+ [(match_operand:FP 2 "fp_src_operand" "f<FP:dreg><Q>U")
+ (match_operand:FP 3 "const0_operand" "H")]))]
+ "TARGET_HARD_FLOAT && TARGET_COLDFIRE_FPU"
{
- if (GET_CODE (operands[0]) == MEM)
- {
- operands[0] = adjust_address (operands[0], QImode,
- INTVAL (operands[1]) / 8);
- operands[1] = GEN_INT (7 - INTVAL (operands[1]) % 8);
- return output_btst (operands, operands[1], operands[0], insn, 7);
- }
- operands[1] = GEN_INT (31 - INTVAL (operands[1]));
- return output_btst (operands, operands[1], operands[0], insn, 31);
-})
+ rtx_code code = GET_CODE (operands[1]);
+ code = m68k_output_compare_fp (operands[2], operands[3], code);
+ return m68k_output_scc_float (code);
+}
+ [(set_attr "flags_valid" "set")])
-
;; move instructions
;; A special case in which it is not desirable
@@ -964,7 +995,8 @@
"!TARGET_COLDFIRE && reload_completed"
{
return output_move_simode (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
;; Before reload is completed the register constraints
;; force integer constants in range for a moveq to be reloaded
@@ -976,7 +1008,8 @@
"!TARGET_COLDFIRE"
{
return output_move_simode (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
;; ColdFire move instructions can have at most one operand of mode >= 6.
(define_insn "*movsi_cf"
@@ -1052,13 +1085,21 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=g")
(match_operand:HI 1 "general_src_operand" "gS"))]
"!TARGET_COLDFIRE"
- "* return output_move_himode (operands);")
+ "* return output_move_himode (operands);"
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "address_reg_operand")
+ (const_string "unchanged")
+ (const_string "move")))])
(define_insn ""
[(set (match_operand:HI 0 "nonimmediate_operand" "=r<Q>,g,U")
(match_operand:HI 1 "general_operand" "g,r<Q>,U"))]
"TARGET_COLDFIRE"
- "* return output_move_himode (operands);")
+ "* return output_move_himode (operands);"
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "address_reg_operand")
+ (const_string "unchanged")
+ (const_string "move")))])
(define_expand "movstricthi"
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" ""))
@@ -1070,13 +1111,15 @@
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(match_operand:HI 1 "general_src_operand" "rmSn"))]
"!TARGET_COLDFIRE"
- "* return output_move_stricthi (operands);")
+ "* return output_move_stricthi (operands);"
+ [(set_attr "flags_valid" "move")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+d,m"))
(match_operand:HI 1 "general_src_operand" "rmn,r"))]
"TARGET_COLDFIRE"
- "* return output_move_stricthi (operands);")
+ "* return output_move_stricthi (operands);"
+ [(set_attr "flags_valid" "move")])
(define_expand "movqi"
[(set (match_operand:QI 0 "nonimmediate_operand" "")
@@ -1088,13 +1131,15 @@
[(set (match_operand:QI 0 "nonimmediate_operand" "=d,*a,m")
(match_operand:QI 1 "general_src_operand" "dmSi*a,di*a,dmSi"))]
"!TARGET_COLDFIRE"
- "* return output_move_qimode (operands);")
+ "* return output_move_qimode (operands);"
+ [(set_attr "flags_valid" "set")])
(define_insn ""
[(set (match_operand:QI 0 "nonimmediate_operand" "=d<Q>,dm,U,d*a")
(match_operand:QI 1 "general_src_operand" "dmi,d<Q>,U,di*a"))]
"TARGET_COLDFIRE"
- "* return output_move_qimode (operands);")
+ "* return output_move_qimode (operands);"
+ [(set_attr "flags_valid" "set")])
(define_expand "movstrictqi"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" ""))
@@ -1106,7 +1151,8 @@
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(match_operand:QI 1 "general_src_operand" "dmSn"))]
"!TARGET_COLDFIRE"
- "* return output_move_strictqi (operands);")
+ "* return output_move_strictqi (operands);"
+ [(set_attr "flags_valid" "move")])
(define_insn "*movstrictqi_cf"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+d, Ac, d,m"))
@@ -1200,7 +1246,8 @@
return "clr%.l %0";
}
return "move%.l %1,%0";
-})
+}
+ [(set_attr "flags_valid" "move")])
(define_insn "movsf_cf_soft"
[(set (match_operand:SF 0 "nonimmediate_operand" "=r<Q>,g,U")
@@ -1340,7 +1387,8 @@
return "fmove%.d %f1,%0";
}
return output_move_double (operands);
-})
+}
+ [(set_attr "flags_valid" "move")])
(define_insn_and_split "movdf_cf_soft"
[(set (match_operand:DF 0 "nonimmediate_operand" "=r,g")
@@ -1461,7 +1509,8 @@
return "fmove%.x %f1,%0";
}
return output_move_double (operands);
-})
+}
+ [(set_attr "flags_valid" "move")])
(define_insn ""
[(set (match_operand:XF 0 "nonimmediate_operand" "=rm,rf,&rof<>")
@@ -1582,16 +1631,16 @@
"!TARGET_COLDFIRE"
{
if (GET_CODE (operands[0]) == REG)
- {
- /* Must clear condition codes, since the move.l bases them on
- the entire 32 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.l %1,%0";
- }
+ return "move%.l %1,%0";
+
if (GET_CODE (operands[1]) == MEM)
operands[1] = adjust_address (operands[1], QImode, 3);
return "move%.b %1,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "no")
+ (const_string "yes")))])
(define_insn "trunchiqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm,d")
@@ -1602,23 +1651,19 @@
if (GET_CODE (operands[0]) == REG
&& (GET_CODE (operands[1]) == MEM
|| GET_CODE (operands[1]) == CONST_INT))
- {
- /* Must clear condition codes, since the move.w bases them on
- the entire 16 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.w %1,%0";
- }
+ return "move%.w %1,%0";
+
if (GET_CODE (operands[0]) == REG)
- {
- /* Must clear condition codes, since the move.l bases them on
- the entire 32 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.l %1,%0";
- }
+ return "move%.l %1,%0";
+
if (GET_CODE (operands[1]) == MEM)
operands[1] = adjust_address (operands[1], QImode, 1);
return "move%.b %1,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "no")
+ (const_string "yes")))])
(define_insn "truncsihi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm,d")
@@ -1627,16 +1672,16 @@
"!TARGET_COLDFIRE"
{
if (GET_CODE (operands[0]) == REG)
- {
- /* Must clear condition codes, since the move.l bases them on
- the entire 32 bits, not just the desired 8 bits. */
- CC_STATUS_INIT;
- return "move%.l %1,%0";
- }
+ return "move%.l %1,%0";
+
if (GET_CODE (operands[1]) == MEM)
operands[1] = adjust_address (operands[1], QImode, 2);
return "move%.w %1,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "no")
+ (const_string "yes")))])
;; zero extension instructions
@@ -1804,7 +1849,6 @@
(sign_extend:DI (match_operand:QI 1 "general_src_operand" "rmS")))]
""
{
- CC_STATUS_INIT;
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
if (ISA_HAS_MVS_MVZ)
return "mvs%.b %1,%2\;smi %0\;extb%.l %0";
@@ -1830,7 +1874,6 @@
(match_operand:HI 1 "general_src_operand" "rmS")))]
""
{
- CC_STATUS_INIT;
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
if (ISA_HAS_MVS_MVZ)
return "mvs%.w %1,%2\;smi %0\;extb%.l %0";
@@ -1847,8 +1890,6 @@
(clobber (match_scratch:SI 2 "=X,d,d,d"))]
""
{
- CC_STATUS_INIT;
-
if (which_alternative == 0)
/* Handle alternative 0. */
{
@@ -1883,7 +1924,6 @@
(match_operand:SI 2 "general_operand" "rmn"))))]
""
{
- CC_STATUS_INIT;
operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
if (GET_CODE (operands[1]) == CONST_INT
&& (unsigned) INTVAL (operands[1]) > 8)
@@ -1975,10 +2015,7 @@
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "f%&move%.x %1,%0";
@@ -2004,10 +2041,7 @@
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "fdmove%.d %1,%0";
@@ -2137,7 +2171,6 @@
(clobber (match_scratch:SI 3 "=d"))]
"TARGET_68881 && TUNE_68040"
{
- CC_STATUS_INIT;
return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.l %1,%0\;fmovem%.l %2,%!";
})
@@ -2148,7 +2181,6 @@
(clobber (match_scratch:SI 3 "=d"))]
"TARGET_68881 && TUNE_68040"
{
- CC_STATUS_INIT;
return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.w %1,%0\;fmovem%.l %2,%!";
})
@@ -2159,7 +2191,6 @@
(clobber (match_scratch:SI 3 "=d"))]
"TARGET_68881 && TUNE_68040"
{
- CC_STATUS_INIT;
return "fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.b %1,%0\;fmovem%.l %2,%!";
})
@@ -2301,7 +2332,6 @@
(clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (ADDRESS_REG_P (operands[0]))
return "add%.w %1,%0";
else if (ADDRESS_REG_P (operands[3]))
@@ -2317,7 +2347,6 @@
(match_operand:DI 2 "general_operand" "0,0")))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (GET_CODE (operands[0]) == REG)
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else
@@ -2332,7 +2361,6 @@
(match_operand:DI 2 "register_operand" "0")))]
"TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
return "add%.l %1,%R0\;negx%.l %0\;neg%.l %0";
})
@@ -2346,7 +2374,6 @@
(match_operand:DI 2 "general_operand" "0,0")))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[1]) == REG)
operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
else
@@ -2412,7 +2439,6 @@
else
{
gcc_assert (GET_CODE (operands[0]) == MEM);
- CC_STATUS_INIT;
if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
{
operands[1] = gen_rtx_MEM (SImode,
@@ -2431,7 +2457,11 @@
return "add%.l %R2,%1\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%0";
}
}
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "noov")
+ (const_string "no")))])
(define_insn "addsi_lshrsi_31"
[(set (match_operand:SI 0 "nonimmediate_operand" "=dm,dm,d<Q>")
@@ -2476,7 +2506,8 @@
"! TARGET_COLDFIRE"
- "* return output_addsi3 (operands);")
+ "* return output_addsi3 (operands);"
+ [(set_attr "flags_valid" "noov,unchanged,unchanged,noov,unchanged")])
(define_insn_and_split "*addsi3_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=mr,mr,a, m,r, ?a, ?a,?a,?a")
@@ -2561,7 +2592,7 @@
return "subq%.w %2,%0";
}
/* On the CPU32 it is faster to use two addqw instructions to
- add a small integer (8 < N <= 16) to a register.
+ add a small integer (8 < N <= 16) to a register.
Likewise for subqw. */
if (TUNE_CPU32 && REG_P (operands[0]))
{
@@ -2582,7 +2613,11 @@
return MOTOROLA ? "lea (%c2,%0),%0" : "lea %0@(%c2),%0";
}
return "add%.w %2,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "address_reg_operand")
+ (const_string "unchanged")
+ (const_string "noov")))])
;; These insns must use MATCH_DUP instead of the more expected
;; use of a matching constraint because the "output" here is also
@@ -2596,6 +2631,7 @@
(match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
"!TARGET_COLDFIRE"
{
+ gcc_assert (!ADDRESS_REG_P (operands[0]));
if (GET_CODE (operands[1]) == CONST_INT)
{
/* If the constant would be a negative number when interpreted as
@@ -2633,11 +2669,10 @@
return "subq%.w #8,%0\;subq%.w %1,%0";
}
}
- if (ADDRESS_REG_P (operands[0]) && !TUNE_68040)
- return MOTOROLA ? "lea (%c1,%0),%0" : "lea %0@(%c1),%0";
}
return "add%.w %1,%0";
-})
+}
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
@@ -2645,6 +2680,7 @@
(match_dup 0)))]
"!TARGET_COLDFIRE"
{
+ gcc_assert (!ADDRESS_REG_P (operands[0]));
if (GET_CODE (operands[1]) == CONST_INT)
{
/* If the constant would be a negative number when interpreted as
@@ -2682,11 +2718,10 @@
return "subq%.w #8,%0\;subq%.w %1,%0";
}
}
- if (ADDRESS_REG_P (operands[0]) && !TUNE_68040)
- return MOTOROLA ? "lea (%c1,%0),%0" : "lea %0@(%c1),%0";
}
return "add%.w %1,%0";
-})
+}
+ [(set_attr "flags_valid" "noov")])
(define_insn "addqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
@@ -2709,7 +2744,8 @@
}
}
return "add%.b %2,%0";
-})
+}
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
@@ -2827,7 +2863,6 @@
(clobber (match_scratch:SI 3 "=&d,X,a,?d"))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (ADDRESS_REG_P (operands[0]))
return "sub%.w %2,%0";
else if (ADDRESS_REG_P (operands[3]))
@@ -2843,7 +2878,6 @@
(const_int 32))))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[1]) == REG)
operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
else
@@ -2911,7 +2945,6 @@
else
{
gcc_assert (GET_CODE (operands[0]) == MEM);
- CC_STATUS_INIT;
if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
{
operands[1]
@@ -2930,20 +2963,26 @@
return "sub%.l %R2,%1\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%0";
}
}
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 0 "register_operand")
+ (const_string "noov")
+ (const_string "no")))])
(define_insn "subsi3"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=mda,m,d,a")
- (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0")
- (match_operand:SI 2 "general_src_operand" "I,dT,mSrT,mSrs")))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=md,ma,m,d,a")
+ (minus:SI (match_operand:SI 1 "general_operand" "0,0,0,0,0")
+ (match_operand:SI 2 "general_src_operand" "I,I,dT,mSrT,mSrs")))]
""
"@
subq%.l %2, %0
+ subq%.l %2, %0
sub%.l %2,%0
sub%.l %2,%0
sub%.l %2,%0"
- [(set_attr "type" "aluq_l,alu_l,alu_l,alu_l")
- (set_attr "opy" "2")])
+ [(set_attr "type" "aluq_l,aluq_l,alu_l,alu_l,alu_l")
+ (set_attr "opy" "2")
+ (set_attr "flags_valid" "noov,unchanged,noov,noov,unchanged")])
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=a")
@@ -2958,28 +2997,32 @@
(minus:HI (match_operand:HI 1 "general_operand" "0,0")
(match_operand:HI 2 "general_src_operand" "dn,rmSn")))]
"!TARGET_COLDFIRE"
- "sub%.w %2,%0")
+ "sub%.w %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(minus:HI (match_dup 0)
(match_operand:HI 1 "general_src_operand" "dn,rmSn")))]
"!TARGET_COLDFIRE"
- "sub%.w %1,%0")
+ "sub%.w %1,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn "subqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(minus:QI (match_operand:QI 1 "general_operand" "0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "sub%.b %2,%0")
+ "sub%.b %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(minus:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "sub%.b %1,%0")
+ "sub%.b %1,%0"
+ [(set_attr "flags_valid" "noov")])
(define_expand "sub<mode>3"
[(set (match_operand:FP 0 "nonimmediate_operand" "")
@@ -3240,10 +3283,7 @@
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "mulu%.l %3,%0:%1";
-})
+ "mulu%.l %3,%0:%1")
(define_insn "const_umulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -3254,10 +3294,7 @@
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "mulu%.l %3,%0:%1";
-})
+ "mulu%.l %3,%0:%1")
(define_expand "smulsi3_highpart"
[(parallel
@@ -3289,10 +3326,7 @@
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "muls%.l %3,%0:%1";
-})
+ "muls%.l %3,%0:%1")
(define_insn "const_smulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -3303,10 +3337,7 @@
(const_int 32))))
(clobber (match_operand:SI 1 "register_operand" "=d"))]
"TARGET_68020 && !TUNE_68060 && !TARGET_COLDFIRE"
-{
- CC_STATUS_INIT;
- return "muls%.l %3,%0:%1";
-})
+ "muls%.l %3,%0:%1")
(define_expand "mul<mode>3"
[(set (match_operand:FP 0 "nonimmediate_operand" "")
@@ -3483,19 +3514,19 @@
(define_expand "divmodsi4"
[(parallel
- [(set (match_operand:SI 0 "nonimmediate_operand" "")
+ [(set (match_operand:SI 0 "register_operand" "")
(div:SI (match_operand:SI 1 "general_operand" "")
(match_operand:SI 2 "general_src_operand" "")))
- (set (match_operand:SI 3 "nonimmediate_operand" "")
+ (set (match_operand:SI 3 "register_operand" "")
(mod:SI (match_dup 1) (match_dup 2)))])]
"TARGET_68020 || TARGET_CF_HWDIV"
"")
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(div:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "d<Q>U")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=&d")
+ (set (match_operand:SI 3 "register_operand" "=&d")
(mod:SI (match_dup 1) (match_dup 2)))]
"TARGET_CF_HWDIV"
{
@@ -3510,10 +3541,10 @@
(set_attr "opy" "2")])
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(div:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:SI 3 "register_operand" "=d")
(mod:SI (match_dup 1) (match_dup 2)))]
"TARGET_68020"
{
@@ -3525,19 +3556,19 @@
(define_expand "udivmodsi4"
[(parallel
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:SI 3 "register_operand" "=d")
(umod:SI (match_dup 1) (match_dup 2)))])]
"TARGET_68020 || TARGET_CF_HWDIV"
"")
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "d<Q>U")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=&d")
+ (set (match_operand:SI 3 "register_operand" "=&d")
(umod:SI (match_dup 1) (match_dup 2)))]
"TARGET_CF_HWDIV"
{
@@ -3552,10 +3583,10 @@
(set_attr "opy" "2")])
(define_insn ""
- [(set (match_operand:SI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:SI 0 "register_operand" "=d")
(udiv:SI (match_operand:SI 1 "general_operand" "0")
(match_operand:SI 2 "general_src_operand" "dmSTK")))
- (set (match_operand:SI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:SI 3 "register_operand" "=d")
(umod:SI (match_dup 1) (match_dup 2)))]
"TARGET_68020 && !TARGET_COLDFIRE"
{
@@ -3566,10 +3597,10 @@
})
(define_insn "divmodhi4"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:HI 0 "register_operand" "=d")
(div:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_src_operand" "dmSKT")))
- (set (match_operand:HI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:HI 3 "register_operand" "=d")
(mod:HI (match_dup 1) (match_dup 2)))]
"!TARGET_COLDFIRE || TARGET_CF_HWDIV"
{
@@ -3578,19 +3609,16 @@
"extl %0\;divs %2,%0",
operands);
if (!find_reg_note(insn, REG_UNUSED, operands[3]))
- {
- CC_STATUS_INIT;
- return "move%.l %0,%3\;swap %3";
- }
+ return "move%.l %0,%3\;swap %3";
else
return "";
})
(define_insn "udivmodhi4"
- [(set (match_operand:HI 0 "nonimmediate_operand" "=d")
+ [(set (match_operand:HI 0 "register_operand" "=d")
(udiv:HI (match_operand:HI 1 "general_operand" "0")
(match_operand:HI 2 "general_src_operand" "dmSKT")))
- (set (match_operand:HI 3 "nonimmediate_operand" "=d")
+ (set (match_operand:HI 3 "register_operand" "=d")
(umod:HI (match_dup 1) (match_dup 2)))]
"!TARGET_COLDFIRE || TARGET_CF_HWDIV"
{
@@ -3606,10 +3634,7 @@
operands);
if (!find_reg_note(insn, REG_UNUSED, operands[3]))
- {
- CC_STATUS_INIT;
- return "move%.l %0,%3\;swap %3";
- }
+ return "move%.l %0,%3\;swap %3";
else
return "";
})
@@ -3644,7 +3669,8 @@
"!TARGET_COLDFIRE"
{
return output_andsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "andsi3_5200"
[(set (match_operand:SI 0 "not_sp_operand" "=m,d")
@@ -3669,35 +3695,40 @@
(and:HI (match_operand:HI 1 "general_operand" "%0,0")
(match_operand:HI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.w %2,%0")
+ "and%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(and:HI (match_dup 0)
(match_operand:HI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.w %1,%0")
+ "and%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+m,d"))
(and:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "and%.w %1,%0")
+ "and%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "andqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(and:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.b %2,%0")
+ "and%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(and:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "and%.b %1,%0")
+ "and%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
@@ -3716,7 +3747,6 @@
{
int byte_mode;
- CC_STATUS_INIT;
if (GET_CODE (operands[0]) == REG)
operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
else
@@ -3747,7 +3777,8 @@
"! TARGET_COLDFIRE"
{
return output_iorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "iorsi3_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=m,d")
@@ -3756,7 +3787,8 @@
"TARGET_COLDFIRE"
{
return output_iorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "iorhi3"
[(set (match_operand:HI 0 "nonimmediate_operand" "=m,d")
@@ -3777,28 +3809,32 @@
(ior:HI (match_operand:HI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "or%.w %1,%0")
+ "or%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "iorqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=m,d")
(ior:QI (match_operand:QI 1 "general_operand" "%0,0")
(match_operand:QI 2 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "or%.b %2,%0")
+ "or%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(ior:QI (match_dup 0)
(match_operand:QI 1 "general_src_operand" "dn,dmSn")))]
"!TARGET_COLDFIRE"
- "or%.b %1,%0")
+ "or%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+m,d"))
(ior:QI (match_operand:QI 1 "general_src_operand" "dn,dmSn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "or%.b %1,%0")
+ "or%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
;; On all 68k models, this makes faster code in a special case.
;; See also ashlsi_16, ashrsi_16 and lshrsi_16.
@@ -3810,7 +3846,6 @@
(const_int 16))))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[2]) != REG)
operands[2] = adjust_address (operands[2], HImode, 2);
if (GET_CODE (operands[2]) != REG
@@ -3827,7 +3862,6 @@
{
int byte_mode;
- CC_STATUS_INIT;
byte_mode = (GET_MODE (operands[1]) == QImode);
if (GET_CODE (operands[0]) == MEM)
operands[0] = adjust_address (operands[0], byte_mode ? QImode : HImode,
@@ -3855,7 +3889,8 @@
"!TARGET_COLDFIRE"
{
return output_xorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "xorsi3_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=dm,d")
@@ -3864,49 +3899,56 @@
"TARGET_COLDFIRE"
{
return output_xorsi3 (operands);
-})
+}
+ [(set_attr "flags_valid" "set")])
(define_insn "xorhi3"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(xor:HI (match_operand:HI 1 "general_operand" "%0")
(match_operand:HI 2 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.w %2,%0")
+ "eor%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(xor:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.w %1,%0")
+ "eor%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(xor:HI (match_operand:HI 1 "general_operand" "dn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "eor%.w %1,%0")
+ "eor%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "xorqi3"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(xor:QI (match_operand:QI 1 "general_operand" "%0")
(match_operand:QI 2 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.b %2,%0")
+ "eor%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(xor:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dn")))]
"!TARGET_COLDFIRE"
- "eor%.b %1,%0")
+ "eor%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(xor:QI (match_operand:QI 1 "general_operand" "dn")
(match_dup 0)))]
"!TARGET_COLDFIRE"
- "eor%.b %1,%0")
+ "eor%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
;; negation instructions
@@ -3965,38 +4007,44 @@
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
"neg%.l %0"
- [(set_attr "type" "neg_l")])
+ [(set_attr "type" "neg_l")
+ (set_attr "flags_valid" "noov")])
(define_insn "negsi2_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d")
(neg:SI (match_operand:SI 1 "general_operand" "0")))]
"TARGET_COLDFIRE"
"neg%.l %0"
- [(set_attr "type" "neg_l")])
+ [(set_attr "type" "neg_l")
+ (set_attr "flags_valid" "noov")])
(define_insn "neghi2"
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(neg:HI (match_operand:HI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "neg%.w %0")
+ "neg%.w %0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(neg:HI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "neg%.w %0")
+ "neg%.w %0"
+ [(set_attr "flags_valid" "noov")])
(define_insn "negqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(neg:QI (match_operand:QI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "neg%.b %0")
+ "neg%.b %0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(neg:QI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "neg%.b %0")
+ "neg%.b %0"
+ [(set_attr "flags_valid" "noov")])
;; If using software floating point, just flip the sign bit.
@@ -4290,20 +4338,14 @@
[(set (match_operand:SI 0 "register_operand" "=d")
(clz:SI (match_operand:SI 1 "general_operand" "do")))]
"TARGET_68020 && TARGET_BITFIELD"
-{
- CC_STATUS_INIT;
- return "bfffo %1{#0:#0},%0";
-})
+ "bfffo %1{#0:#0},%0")
;; ColdFire ff1 instruction implements clz.
(define_insn "*clzsi2_cf"
[(set (match_operand:SI 0 "register_operand" "=d")
(clz:SI (match_operand:SI 1 "register_operand" "0")))]
"ISA_HAS_FF1"
-{
- CC_STATUS_INIT;
- return "ff1 %0";
-}
+ "ff1 %0"
[(set_attr "type" "ext")])
;; one complement instructions
@@ -4324,7 +4366,8 @@
[(set (match_operand:SI 0 "nonimmediate_operand" "=dm")
(not:SI (match_operand:SI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "not%.l %0")
+ "not%.l %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "one_cmplsi2_5200"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d")
@@ -4337,25 +4380,29 @@
[(set (match_operand:HI 0 "nonimmediate_operand" "=dm")
(not:HI (match_operand:HI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "not%.w %0")
+ "not%.w %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "nonimmediate_operand" "+dm"))
(not:HI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "not%.w %0")
+ "not%.w %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "one_cmplqi2"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(not:QI (match_operand:QI 1 "general_operand" "0")))]
"!TARGET_COLDFIRE"
- "not%.b %0")
+ "not%.b %0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+dm"))
(not:QI (match_dup 0)))]
"!TARGET_COLDFIRE"
- "not%.b %0")
+ "not%.b %0"
+ [(set_attr "flags_valid" "yes")])
;; arithmetic shift instructions
;; We don't need the shift memory by 1 bit instruction
@@ -4379,7 +4426,6 @@
(clobber (match_scratch:SI 2 "=a,X"))]
""
{
- CC_STATUS_INIT;
if (GET_CODE (operands[0]) == MEM)
{
if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
@@ -4577,13 +4623,10 @@
(ashift:SI (match_operand:SI 1 "register_operand" "0")
(const_int 16)))]
"!TUNE_68060"
-{
- CC_STATUS_INIT;
- return "swap %0\;clr%.w %0";
-})
+ "swap %0\;clr%.w %0")
;; ashift patterns : use lsl instead of asl, because lsl always clears the
-;; overflow bit, so we must not set CC_NO_OVERFLOW.
+;; overflow bit, allowing more comparisons.
;; On the 68000, this makes faster code in a special case.
@@ -4595,8 +4638,6 @@
&& INTVAL (operands[2]) > 16
&& INTVAL (operands[2]) <= 24"
{
- CC_STATUS_INIT;
-
operands[2] = GEN_INT (INTVAL (operands[2]) - 16);
return "lsl%.w %2,%0\;swap %0\;clr%.w %0";
})
@@ -4608,40 +4649,45 @@
""
{
if (operands[2] == const1_rtx)
- {
- cc_status.flags = CC_NO_OVERFLOW;
- return "add%.l %0,%0";
- }
+ return "add%.l %0,%0";
return "lsl%.l %2,%0";
-})
+}
+ [(set (attr "flags_valid")
+ (if_then_else (match_operand 2 "const1_operand")
+ (const_string "noov")
+ (const_string "yes")))])
(define_insn "ashlhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(ashift:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.w %2,%0")
+ "lsl%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(ashift:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.w %1,%0")
+ "lsl%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "ashlqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(ashift:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.b %2,%0")
+ "lsl%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(ashift:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsl%.b %1,%0")
+ "lsl%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
;; On most 68k models, this makes faster code in a special case.
@@ -4695,7 +4741,6 @@
"!TARGET_COLDFIRE"
{
operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- CC_STATUS_INIT;
return "asr%.l #1,%0\;roxr%.l #1,%1";
})
@@ -4761,7 +4806,6 @@
(const_int 32)))]
""
{
- CC_STATUS_INIT;
if (TARGET_68020)
return "move%.l %1,%R0\;smi %0\;extb%.l %0";
else
@@ -4775,7 +4819,6 @@
(clobber (match_scratch:SI 2 "=d,d"))]
""
{
- CC_STATUS_INIT;
operands[3] = adjust_address (operands[0], SImode,
which_alternative == 0 ? 4 : 0);
operands[0] = adjust_address (operands[0], SImode, 0);
@@ -4808,7 +4851,6 @@
|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63))"
{
operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- CC_STATUS_INIT;
if (INTVAL (operands[2]) == 48)
return "swap %0\;ext%.l %0\;move%.l %0,%1\;smi %0\;ext%.w %0";
if (INTVAL (operands[2]) == 31)
@@ -4858,35 +4900,40 @@
""
"asr%.l %2,%0"
[(set_attr "type" "shift")
- (set_attr "opy" "2")])
+ (set_attr "opy" "2")
+ (set_attr "flags_valid" "noov")])
(define_insn "ashrhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.w %2,%0")
+ "asr%.w %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(ashiftrt:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.w %1,%0")
+ "asr%.w %1,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn "ashrqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.b %2,%0")
+ "asr%.b %2,%0"
+ [(set_attr "flags_valid" "noov")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(ashiftrt:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "asr%.b %1,%0")
+ "asr%.b %1,%0"
+ [(set_attr "flags_valid" "noov")])
;; logical shift instructions
@@ -4933,7 +4980,6 @@
(const_int 1)))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
return "lsr%.l #1,%0\;roxr%.l #1,%R0";
})
@@ -5131,7 +5177,6 @@
(const_int 16)))]
"!TUNE_68060"
{
- CC_STATUS_INIT;
return "clr%.w %0\;swap %0";
})
@@ -5157,35 +5202,40 @@
""
"lsr%.l %2,%0"
[(set_attr "type" "shift")
- (set_attr "opy" "2")])
+ (set_attr "opy" "2")
+ (set_attr "flags_valid" "yes")])
(define_insn "lshrhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
(match_operand:HI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.w %2,%0")
+ "lsr%.w %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
(lshiftrt:HI (match_dup 0)
(match_operand:HI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.w %1,%0")
+ "lsr%.w %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "lshrqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.b %2,%0")
+ "lsr%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(lshiftrt:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "lsr%.b %1,%0")
+ "lsr%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
;; rotate instructions
@@ -5195,7 +5245,8 @@
(const_int 16)))]
""
"swap %0"
- [(set_attr "type" "shift")])
+ [(set_attr "type" "shift")
+ (set_attr "flags_valid" "yes")])
(define_insn "rotlsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -5212,7 +5263,8 @@
}
else
return "rol%.l %2,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotlhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
@@ -5227,7 +5279,8 @@
}
else
return "rol%.w %2,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "*rotlhi3_lowpart"
[(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
@@ -5242,7 +5295,8 @@
}
else
return "rol%.w %1,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotlqi3"
[(set (match_operand:QI 0 "register_operand" "=d")
@@ -5257,7 +5311,8 @@
}
else
return "rol%.b %2,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "*rotlqi3_lowpart"
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
@@ -5272,14 +5327,16 @@
}
else
return "rol%.b %1,%0";
-})
+}
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotrsi3"
[(set (match_operand:SI 0 "register_operand" "=d")
(rotatert:SI (match_operand:SI 1 "register_operand" "0")
(match_operand:SI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "ror%.l %2,%0")
+ "ror%.l %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn "rotrhi3"
[(set (match_operand:HI 0 "register_operand" "=d")
@@ -5300,14 +5357,16 @@
(rotatert:QI (match_operand:QI 1 "register_operand" "0")
(match_operand:QI 2 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "ror%.b %2,%0")
+ "ror%.b %2,%0"
+ [(set_attr "flags_valid" "yes")])
(define_insn ""
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
(rotatert:QI (match_dup 0)
(match_operand:QI 1 "general_operand" "dI")))]
"!TARGET_COLDFIRE"
- "ror%.b %1,%0")
+ "ror%.b %1,%0"
+ [(set_attr "flags_valid" "yes")])
(define_expand "bswapsi2"
[(set (match_operand:SI 0 "register_operand")
@@ -5332,10 +5391,7 @@
(match_operand:SI 1 "general_operand" "d")) 3)
(match_dup 0)))]
""
-{
- CC_STATUS_INIT;
- return "bset %1,%0";
-}
+ "bset %1,%0"
[(set_attr "type" "bitrw")])
;; set bit, bit number is (sign/zero)_extended from HImode/QImode
@@ -5346,10 +5402,7 @@
[(match_operand 1 "general_operand" "d")])) 3)
(match_dup 0)))]
""
-{
- CC_STATUS_INIT;
- return "bset %1,%0";
-}
+ "bset %1,%0"
[(set_attr "type" "bitrw")])
(define_insn "*bsetdreg"
@@ -5359,10 +5412,7 @@
(const_int 31)))
(match_operand:SI 2 "register_operand" "0")))]
""
-{
- CC_STATUS_INIT;
- return "bset %1,%0";
-}
+ "bset %1,%0"
[(set_attr "type" "bitrw")])
(define_insn "*bchgdreg"
@@ -5372,10 +5422,7 @@
(const_int 31)))
(match_operand:SI 2 "register_operand" "0")))]
""
-{
- CC_STATUS_INIT;
- return "bchg %1,%0";
-}
+ "bchg %1,%0"
[(set_attr "type" "bitrw")])
(define_insn "*bclrdreg"
@@ -5385,10 +5432,7 @@
(const_int 31)))
(match_operand:SI 2 "register_operand" "0")))]
""
-{
- CC_STATUS_INIT;
- return "bclr %1,%0";
-}
+ "bclr %1,%0"
[(set_attr "type" "bitrw")])
;; clear bit, bit number is int
@@ -5399,10 +5443,7 @@
(match_operand:SI 1 "general_operand" "d")))
(const_int 0))]
""
-{
- CC_STATUS_INIT;
- return "bclr %1,%0";
-}
+ "bclr %1,%0"
[(set_attr "type" "bitrw")])
;; clear bit, bit number is (sign/zero)_extended from HImode/QImode
@@ -5414,10 +5455,7 @@
[(match_operand 1 "general_operand" "d")])))
(const_int 0))]
""
-{
- CC_STATUS_INIT;
- return "bclr %1,%0";
-}
+ "bclr %1,%0"
[(set_attr "type" "bitrw")])
;; Special cases of bit-field insns which we should
@@ -5500,7 +5538,6 @@
&& (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
{
- cc_status.flags |= CC_NOT_NEGATIVE;
if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
return "bfextu %1{%b3:%b2},%0";
@@ -5586,15 +5623,6 @@
(match_operand:SI 3 "nonmemory_operand" "dn")))]
"TARGET_68020 && TARGET_BITFIELD"
{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL (operands[2]) != 32)
- cc_status.flags |= CC_NOT_NEGATIVE;
- }
- else
- {
- CC_STATUS_INIT;
- }
return "bfextu %1{%b3:%b2},%0";
})
@@ -5609,7 +5637,6 @@
|| (GET_CODE (operands[1]) == CONST_INT
&& (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))"
{
- CC_STATUS_INIT;
return "bfchg %0{%b2:%b1}";
})
@@ -5620,7 +5647,6 @@
(const_int 0))]
"TARGET_68020 && TARGET_BITFIELD"
{
- CC_STATUS_INIT;
return "bfclr %0{%b2:%b1}";
})
@@ -5631,7 +5657,6 @@
(const_int -1))]
"TARGET_68020 && TARGET_BITFIELD"
{
- CC_STATUS_INIT;
return "bfset %0{%b2:%b1}";
})
@@ -5680,15 +5705,6 @@
(match_operand:SI 3 "const_int_operand" "n")))]
"TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[3]), 0, 31)"
{
- if (GET_CODE (operands[2]) == CONST_INT)
- {
- if (INTVAL (operands[2]) != 32)
- cc_status.flags |= CC_NOT_NEGATIVE;
- }
- else
- {
- CC_STATUS_INIT;
- }
return "bfextu %1{%b3:%b2},%0";
})
@@ -5699,7 +5715,6 @@
(const_int 0))]
"TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
{
- CC_STATUS_INIT;
return "bfclr %0{%b2:%b1}";
})
@@ -5710,7 +5725,6 @@
(const_int -1))]
"TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
{
- CC_STATUS_INIT;
return "bfset %0{%b2:%b1}";
})
@@ -5733,58 +5747,6 @@
return "bfins %3,%0{%b2:%b1}";
})
-;; Special patterns for optimizing bit-field instructions.
-
-(define_insn "*tst_bftst_mem"
- [(set (cc0)
- (compare (zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "general_operand" "dn"))
- (const_int 0)))]
- "TARGET_68020 && TARGET_BITFIELD"
-{
- if (operands[1] == const1_rtx
- && GET_CODE (operands[2]) == CONST_INT)
- {
- int width = GET_CODE (operands[0]) == REG ? 31 : 7;
- return output_btst (operands,
- GEN_INT (width - INTVAL (operands[2])),
- operands[0], insn, 1000);
- /* Pass 1000 as SIGNPOS argument so that btst will
- not think we are testing the sign bit for an `and'
- and assume that nonzero implies a negative result. */
- }
- if (INTVAL (operands[1]) != 32)
- cc_status.flags = CC_NOT_NEGATIVE;
- return "bftst %0{%b2:%b1}";
-})
-
-
-;;; now handle the register cases
-(define_insn "*tst_bftst_reg"
- [(set (cc0)
- (compare (zero_extract:SI (match_operand:SI 0 "register_operand" "d")
- (match_operand:SI 1 "const_int_operand" "n")
- (match_operand:SI 2 "general_operand" "dn"))
- (const_int 0)))]
- "TARGET_68020 && TARGET_BITFIELD
- && !(CONST_INT_P (operands[2]) && !IN_RANGE (INTVAL (operands[2]), 0, 31))"
-{
- if (operands[1] == const1_rtx
- && GET_CODE (operands[2]) == CONST_INT)
- {
- int width = GET_CODE (operands[0]) == REG ? 31 : 7;
- return output_btst (operands, GEN_INT (width - INTVAL (operands[2])),
- operands[0], insn, 1000);
- /* Pass 1000 as SIGNPOS argument so that btst will
- not think we are testing the sign bit for an `and'
- and assume that nonzero implies a negative result. */
- }
- if (INTVAL (operands[1]) != 32)
- cc_status.flags = CC_NOT_NEGATIVE;
- return "bftst %0{%b2:%b1}";
-})
-
(define_insn "scc0_di"
[(set (match_operand:QI 0 "nonimmediate_operand" "=dm")
(match_operator 1 "ordered_comparison_operator"
@@ -5822,879 +5784,6 @@
{
return output_scc_di (operands[1], operands[2], operands[3], operands[0]);
})
-
-;; Note that operand 0 of an SCC insn is supported in the hardware as
-;; memory, but we cannot allow it to be in memory in case the address
-;; needs to be reloaded.
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (eq:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("seq %0", "fseq %0", "seq %0");
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ne:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sne %0", "fsne %0", "sne %0");
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (gt:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sgt %0", "fsgt %0", 0);
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (gtu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "shi %0";
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (lt:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("slt %0", "fslt %0", "smi %0");
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ltu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "scs %0";
-})
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ge:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sge %0", "fsge %0", "spl %0");
-})
-
-(define_insn "*scc"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (geu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "scc %0";
-}
- [(set_attr "type" "scc")])
-
-(define_insn ""
- [(set (match_operand:QI 0 "register_operand" "=d")
- (le:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- OUTPUT_JUMP ("sle %0", "fsle %0", 0);
-})
-
-(define_insn "*sls"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (leu:QI (cc0) (const_int 0)))]
- ""
-{
- cc_status = cc_prev_status;
- return "sls %0";
-}
- [(set_attr "type" "scc")])
-
-(define_insn "*sordered_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ordered:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsor %0";
-})
-
-(define_insn "*sunordered_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unordered:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsun %0";
-})
-
-(define_insn "*suneq_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (uneq:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsueq %0";
-})
-
-(define_insn "*sunge_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unge:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsuge %0";
-})
-
-(define_insn "*sungt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ungt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsugt %0";
-})
-
-(define_insn "*sunle_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unle:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsule %0";
-})
-
-(define_insn "*sunlt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (unlt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsult %0";
-})
-
-(define_insn "*sltgt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (ltgt:QI (cc0) (const_int 0)))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsogl %0";
-})
-
-(define_insn "*fsogt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (unle:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsogt %0";
-})
-
-(define_insn "*fsoge_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (unlt:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsoge %0";
-})
-
-(define_insn "*fsolt_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (unge:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsolt %0";
-})
-
-(define_insn "*fsole_1"
- [(set (match_operand:QI 0 "register_operand" "=d")
- (not:QI (ungt:QI (cc0) (const_int 0))))]
- "TARGET_68881 && !TUNE_68060"
-{
- cc_status = cc_prev_status;
- return "fsole %0";
-})
-
-;; Basic conditional jump instructions.
-
-(define_insn "beq0_di"
- [(set (pc)
- (if_then_else (eq (match_operand:DI 0 "general_operand" "d*a,o,<>")
- (const_int 0))
- (label_ref (match_operand 1 "" ",,"))
- (pc)))
- (clobber (match_scratch:SI 2 "=d,&d,d"))]
- ""
-{
- CC_STATUS_INIT;
- if (which_alternative == 2)
- return "move%.l %0,%2\;or%.l %0,%2\;jeq %l1";
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return "jeq %l1";
- }
- if (GET_CODE (operands[0]) == REG)
- operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- else
- operands[3] = adjust_address (operands[0], SImode, 4);
- if (! ADDRESS_REG_P (operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[3]))
- return "or%.l %0,%2\;jeq %l1";
- else
- return "or%.l %3,%2\;jeq %l1";
- }
- return "move%.l %0,%2\;or%.l %3,%2\;jeq %l1";
- }
- operands[4] = gen_label_rtx();
- if (TARGET_68020 || TARGET_COLDFIRE)
- output_asm_insn ("tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1", operands);
- else
- output_asm_insn ("cmp%.w #0,%0\;jne %l4\;cmp%.w #0,%3\;jeq %l1", operands);
- (*targetm.asm_out.internal_label) (asm_out_file, "L",
- CODE_LABEL_NUMBER (operands[4]));
- return "";
-})
-
-(define_insn "bne0_di"
- [(set (pc)
- (if_then_else (ne (match_operand:DI 0 "general_operand" "d,o,*a")
- (const_int 0))
- (label_ref (match_operand 1 "" ",,"))
- (pc)))
- (clobber (match_scratch:SI 2 "=d,&d,X"))]
- ""
-{
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return "jne %l1";
- }
- CC_STATUS_INIT;
- if (GET_CODE (operands[0]) == REG)
- operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
- else
- operands[3] = adjust_address (operands[0], SImode, 4);
- if (!ADDRESS_REG_P (operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[0]))
- {
- if (reg_overlap_mentioned_p (operands[2], operands[3]))
- return "or%.l %0,%2\;jne %l1";
- else
- return "or%.l %3,%2\;jne %l1";
- }
- return "move%.l %0,%2\;or%.l %3,%2\;jne %l1";
- }
- if (TARGET_68020 || TARGET_COLDFIRE)
- return "tst%.l %0\;jne %l1\;tst%.l %3\;jne %l1";
- else
- return "cmp%.w #0,%0\;jne %l1\;cmp%.w #0,%3\;jne %l1";
-})
-
-(define_insn "bge0_di"
- [(set (pc)
- (if_then_else (ge (match_operand:DI 0 "general_operand" "ro")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
-{
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return cc_status.flags & CC_REVERSED ? "jle %l1" : "jpl %l1";
- }
- CC_STATUS_INIT;
- if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (operands[0]))
- output_asm_insn("tst%.l %0", operands);
- else
- {
- /* On an address reg, cmpw may replace cmpl. */
- output_asm_insn("cmp%.w #0,%0", operands);
- }
- return "jpl %l1";
-})
-
-(define_insn "blt0_di"
- [(set (pc)
- (if_then_else (lt (match_operand:DI 0 "general_operand" "ro")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))]
- ""
-{
- if ((cc_prev_status.value1
- && rtx_equal_p (cc_prev_status.value1, operands[0]))
- || (cc_prev_status.value2
- && rtx_equal_p (cc_prev_status.value2, operands[0])))
- {
- cc_status = cc_prev_status;
- return cc_status.flags & CC_REVERSED ? "jgt %l1" : "jmi %l1";
- }
- CC_STATUS_INIT;
- if (TARGET_68020 || TARGET_COLDFIRE || ! ADDRESS_REG_P (operands[0]))
- output_asm_insn("tst%.l %0", operands);
- else
- {
- /* On an address reg, cmpw may replace cmpl. */
- output_asm_insn("cmp%.w #0,%0", operands);
- }
- return "jmi %l1";
-})
-
-(define_insn "beq"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bne"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bgt"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jgt %l0", "fjgt %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bgtu"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jhi %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "blt"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jlt %l0", "fjlt %l0", "jmi %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bltu"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcs %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bge"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jge %l0", "fjge %l0", "jpl %l0");
-})
-
-(define_insn "bgeu"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcc %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "ble"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jle %l0", "fjle %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bleu"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jls %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "bordered"
- [(set (pc)
- (if_then_else (ordered (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjor %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunordered"
- [(set (pc)
- (if_then_else (unordered (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjun %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "buneq"
- [(set (pc)
- (if_then_else (uneq (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjueq %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunge"
- [(set (pc)
- (if_then_else (unge (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjuge %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bungt"
- [(set (pc)
- (if_then_else (ungt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjugt %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunle"
- [(set (pc)
- (if_then_else (unle (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjule %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bunlt"
- [(set (pc)
- (if_then_else (unlt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjult %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "bltgt"
- [(set (pc)
- (if_then_else (ltgt (cc0) (const_int 0))
- (label_ref (match_operand 0 "" ""))
- (pc)))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjogl %l0";
-}
- [(set_attr "type" "fbcc")])
-
-;; Negated conditional jump instructions.
-
-(define_insn "*beq_rev"
- [(set (pc)
- (if_then_else (eq (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- OUTPUT_JUMP ("jne %l0", "fjne %l0", "jne %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bne_rev"
- [(set (pc)
- (if_then_else (ne (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- OUTPUT_JUMP ("jeq %l0", "fjeq %l0", "jeq %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bgt_rev"
- [(set (pc)
- (if_then_else (gt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jle %l0", "fjngt %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bgtu_rev"
- [(set (pc)
- (if_then_else (gtu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jls %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*blt_rev"
- [(set (pc)
- (if_then_else (lt (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jge %l0", "fjnlt %l0", "jpl %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bltu_rev"
- [(set (pc)
- (if_then_else (ltu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcc %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bge_rev"
- [(set (pc)
- (if_then_else (ge (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jlt %l0", "fjnge %l0", "jmi %l0");
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bgeu_rev"
- [(set (pc)
- (if_then_else (geu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jcs %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*ble_rev"
- [(set (pc)
- (if_then_else (le (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- OUTPUT_JUMP ("jgt %l0", "fjnle %l0", 0);
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bleu_rev"
- [(set (pc)
- (if_then_else (leu (cc0)
- (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- ""
-{
- if ((cc_status.flags & CC_OVERFLOW_UNUSABLE) != 0)
- {
- cc_status.flags &= ~CC_OVERFLOW_UNUSABLE;
- return 0;
- }
-
- return "jhi %l0";
-}
- [(set_attr "type" "bcc")])
-
-(define_insn "*bordered_rev"
- [(set (pc)
- (if_then_else (ordered (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjun %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bunordered_rev"
- [(set (pc)
- (if_then_else (unordered (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjor %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*buneq_rev"
- [(set (pc)
- (if_then_else (uneq (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjogl %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bunge_rev"
- [(set (pc)
- (if_then_else (unge (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjolt %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bungt_rev"
- [(set (pc)
- (if_then_else (ungt (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjole %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bunle_rev"
- [(set (pc)
- (if_then_else (unle (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjogt %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bunlt_rev"
- [(set (pc)
- (if_then_else (unlt (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjoge %l0";
-}
- [(set_attr "type" "fbcc")])
-
-(define_insn "*bltgt_rev"
- [(set (pc)
- (if_then_else (ltgt (cc0) (const_int 0))
- (pc)
- (label_ref (match_operand 0 "" ""))))]
- "TARGET_HARD_FLOAT"
-{
- gcc_assert (cc_prev_status.flags & CC_IN_68881);
- return "fjueq %l0";
-}
- [(set_attr "type" "fbcc")])
;; Unconditional and other jump instructions
(define_insn "jump"
@@ -6779,7 +5868,6 @@
(const_int -1)))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1";
if (GET_CODE (operands[0]) == MEM)
@@ -6799,7 +5887,6 @@
(const_int -1)))]
"!TARGET_COLDFIRE"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1\;clr%.w %0\;subq%.l #1,%0\;jcc %l1";
if (GET_CODE (operands[0]) == MEM)
@@ -6822,7 +5909,6 @@
(const_int -1)))]
"!TARGET_COLDFIRE && find_reg_note (insn, REG_NONNEG, 0)"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1";
if (GET_CODE (operands[0]) == MEM)
@@ -6857,7 +5943,6 @@
(const_int -1)))]
"!TARGET_COLDFIRE && find_reg_note (insn, REG_NONNEG, 0)"
{
- CC_STATUS_INIT;
if (DATA_REG_P (operands[0]))
return "dbra %0,%l1\;clr%.w %0\;subq%.l #1,%0\;jcc %l1";
if (GET_CODE (operands[0]) == MEM)
@@ -7004,13 +6089,15 @@
(define_insn "blockage"
[(unspec_volatile [(const_int 0)] UNSPECV_BLOCKAGE)]
""
- "")
+ ""
+ [(set_attr "flags_valid" "unchanged")])
(define_insn "nop"
[(const_int 0)]
""
"nop"
- [(set_attr "type" "nop")])
+ [(set_attr "type" "nop")
+ (set_attr "flags_valid" "unchanged")])
(define_expand "prologue"
[(const_int 0)]
@@ -7379,97 +6466,56 @@
;;
;; Which moves the jCC condition outside the inner loop for free.
;;
+(define_mode_iterator DBCC [HI SI])
(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (if_then_else
- (ne (match_operand:HI 0 "register_operand" "")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:HI (match_dup 0)
- (const_int -1)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
-{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
- return "";
-})
-
-(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
- (label_ref (match_operand 2 "" ""))
- (pc)))
- (parallel
- [(set (pc)
- (if_then_else
- (ne (match_operand:SI 0 "register_operand" "")
- (const_int 0))
- (label_ref (match_operand 1 "" ""))
- (pc)))
- (set (match_dup 0)
- (plus:SI (match_dup 0)
- (const_int -1)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
-{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
- return "";
-})
-
-(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
+ [(set (pc) (if_then_else (match_operator 3 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 4 "general_operand" "")
+ (match_operand:CMPMODE 5 "general_operand" "")])
(label_ref (match_operand 2 "" ""))
(pc)))
(parallel
[(set (pc)
(if_then_else
- (ge (plus:HI (match_operand:HI 0 "register_operand" "")
- (const_int -1))
+ (ne (match_operand:DBCC 0 "register_operand" "")
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
- (plus:HI (match_dup 0)
- (const_int -1)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ (plus:DBCC (match_dup 0)
+ (const_int -1)))])]
+ "!TARGET_COLDFIRE && DATA_REG_P (operands[0])"
{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
+ rtx_code code = GET_CODE (operands[3]);
+ code = m68k_output_compare_<CMPMODE:mode> (operands[4], operands[5], code);
+ output_dbcc_and_branch (operands, code);
return "";
})
(define_peephole
- [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
- [(cc0) (const_int 0)])
+ [(set (pc) (if_then_else (match_operator 3 "ordered_comparison_operator"
+ [(match_operand:CMPMODE 4 "general_operand" "")
+ (match_operand:CMPMODE 5 "general_operand" "")])
(label_ref (match_operand 2 "" ""))
(pc)))
(parallel
[(set (pc)
(if_then_else
- (ge (plus:SI (match_operand:SI 0 "register_operand" "")
- (const_int -1))
+ (ge (plus:DBCC (match_operand:DBCC 0 "register_operand" "")
+ (const_int -1))
(const_int 0))
(label_ref (match_operand 1 "" ""))
(pc)))
(set (match_dup 0)
- (plus:SI (match_dup 0)
- (const_int -1)))])]
- "!TARGET_COLDFIRE && DATA_REG_P (operands[0]) && ! flags_in_68881 ()"
+ (plus:DBCC (match_dup 0)
+ (const_int -1)))])]
+ "!TARGET_COLDFIRE && DATA_REG_P (operands[0])"
{
- CC_STATUS_INIT;
- output_dbcc_and_branch (operands);
+ rtx_code code = GET_CODE (operands[3]);
+ code = m68k_output_compare_<CMPMODE:mode> (operands[4], operands[5], code);
+ output_dbcc_and_branch (operands, code);
return "";
})
-
(define_insn "extendsfxf2"
[(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f")
@@ -7480,10 +6526,7 @@
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "f%$move%.x %1,%0";
@@ -7512,10 +6555,7 @@
{
if (REGNO (operands[0]) == REGNO (operands[1]))
{
- /* Extending float to double in an fp-reg is a no-op.
- NOTICE_UPDATE_CC has already assumed that the
- cc will be set. So cancel what it did. */
- cc_status = cc_prev_status;
+ /* Extending float to double in an fp-reg is a no-op. */
return "";
}
return "fmove%.x %1,%0";
@@ -7583,64 +6623,52 @@
return "fcos%.<FP:prec> %1,%0";
})
-;; Unconditional traps are assumed to have (const_int 1) for the condition.
+;; Unconditional traps are assumed to have const_true_rtx for the condition.
(define_insn "trap"
- [(trap_if (const_int 1) (const_int 7))]
+ [(trap_if (const_int -1) (const_int 7))]
""
"trap #7"
[(set_attr "type" "trap")])
-(define_expand "ctrapdi4"
+;; ??? Our trap instruction uses constant 7 for operand 3, which is
+;; also the trap vector used by TRAPcc instruction. By restricting
+;; these patterns to const1_operand, they will not be generated.
+;; Left disabled for now, as enabling it seems to cause issues.
+(define_insn "ctrap<mode>4"
[(trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_constraints>")])
+ (match_operand:SI 3 "const1_operand" ""))]
+ "TARGET_68020 && !TARGET_COLDFIRE"
{
- if (operands[2] == const0_rtx)
- emit_insn (gen_tstdi (operands[1]));
- else
- emit_insn (gen_cmpdi (operands[1], operands[2]));
- operands[1] = cc0_rtx;
- operands[2] = const0_rtx;
-})
-
-(define_expand "ctrapsi4"
- [(set (cc0)
- (compare (match_operand:SI 1 "nonimmediate_operand" "")
- (match_operand:SI 2 "general_operand" "")))
- (trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
- "")
-
-(define_expand "ctraphi4"
- [(set (cc0)
- (compare (match_operand:HI 1 "nonimmediate_src_operand" "")
- (match_operand:HI 2 "general_src_operand" "")))
- (trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
- "")
-
-(define_expand "ctrapqi4"
- [(set (cc0)
- (compare (match_operand:QI 1 "nonimmediate_src_operand" "")
- (match_operand:QI 2 "general_src_operand" "")))
- (trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 3 "const1_operand" ""))]
- "TARGET_68020"
- "")
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ switch (code)
+ {
+ case EQ: return "trapeq";
+ case NE: return "trapne";
+ case GT: return "trapgt";
+ case GTU: return "traphi";
+ case LT: return "traplt";
+ case LTU: return "trapcs";
+ case GE: return "trapge";
+ case GEU: return "trapcc";
+ case LE: return "traple";
+ case LEU: return "trapls";
+ default: gcc_unreachable ();
+ }
+})
-(define_insn "*conditional_trap"
+(define_insn "ctrap<mode>4_cf"
[(trap_if (match_operator 0 "ordered_comparison_operator"
- [(cc0) (const_int 0)])
- (match_operand:SI 1 "const1_operand" "I"))]
- "TARGET_68020 && ! flags_in_68881 ()"
-{
- switch (GET_CODE (operands[0]))
+ [(match_operand:CMPMODE 1 "nonimmediate_operand" "<cmp1_cf_constraints>")
+ (match_operand:CMPMODE 2 "general_operand" "<cmp2_cf_constraints>")])
+ (match_operand:SI 3 "const1_operand" ""))]
+ "TARGET_68020 && TARGET_COLDFIRE"
+{
+ rtx_code code = GET_CODE (operands[0]);
+ code = m68k_output_compare_<mode> (operands[1], operands[2], code);
+ switch (code)
{
case EQ: return "trapeq";
case NE: return "trapne";
@@ -7735,10 +6763,8 @@
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "addq_subq_operand" ""))
- (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
- (match_dup 0)))
(set (pc) (if_then_else (match_operator 5 "equality_comparison_operator"
- [(cc0) (const_int 0)])
+ [(match_operand:SI 2 "register_operand" "") (match_dup 0)])
(match_operand 3 "pc_or_label_operand")
(match_operand 4 "pc_or_label_operand")))]
"peep2_reg_dead_p (2, operands[0])
@@ -7747,8 +6773,7 @@
&& DATA_REG_P (operands[2])
&& !rtx_equal_p (operands[0], operands[2])"
[(set (match_dup 2) (plus:SI (match_dup 2) (match_dup 6)))
- (set (cc0) (compare (match_dup 2) (const_int 0)))
- (set (pc) (if_then_else (match_op_dup 5 [(cc0) (const_int 0)])
+ (set (pc) (if_then_else (match_op_dup 5 [(match_dup 2) (const_int 0)])
(match_dup 3)
(match_dup 4)))]
"operands[6] = GEN_INT (-INTVAL (operands[1]));")
@@ -7756,9 +6781,8 @@
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "pow2_m1_operand" ""))
- (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
- (match_operand:SI 3 "register_operand" "")))
- (set (pc) (if_then_else (gtu (cc0) (const_int 0))
+ (set (pc) (if_then_else (gtu (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" ""))
(match_operand 4 "pc_or_label_operand")
(match_operand 5 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
@@ -7769,8 +6793,7 @@
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[2])"
[(set (match_dup 7) (lshiftrt:SI (match_dup 7) (match_dup 6)))
- (set (cc0) (compare (match_dup 7) (const_int 0)))
- (set (pc) (if_then_else (ne (cc0) (const_int 0))
+ (set (pc) (if_then_else (ne (match_dup 7) (const_int 0))
(match_dup 4) (match_dup 5)))]
"
{
@@ -7779,9 +6802,8 @@
}")
(define_peephole2
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "pow2_m1_operand" "")))
- (set (pc) (if_then_else (gtu (cc0) (const_int 0))
+ [(set (pc) (if_then_else (gtu (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "pow2_m1_operand" ""))
(match_operand 2 "pc_or_label_operand")
(match_operand 3 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
@@ -7790,17 +6812,15 @@
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[0])"
[(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 4)))
- (set (cc0) (compare (match_dup 0) (const_int 0)))
- (set (pc) (if_then_else (ne (cc0) (const_int 0))
+ (set (pc) (if_then_else (ne (match_dup 0) (const_int 0))
(match_dup 2) (match_dup 3)))]
"{ operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); }")
(define_peephole2
[(set (match_operand:SI 0 "register_operand" "")
(match_operand:SI 1 "pow2_m1_operand" ""))
- (set (cc0) (compare (match_operand:SI 2 "register_operand" "")
- (match_operand:SI 3 "register_operand" "")))
- (set (pc) (if_then_else (leu (cc0) (const_int 0))
+ (set (pc) (if_then_else (leu (match_operand:SI 2 "register_operand" "")
+ (match_operand:SI 3 "register_operand" ""))
(match_operand 4 "pc_or_label_operand")
(match_operand 5 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
@@ -7811,8 +6831,7 @@
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[2])"
[(set (match_dup 7) (lshiftrt:SI (match_dup 7) (match_dup 6)))
- (set (cc0) (compare (match_dup 7) (const_int 0)))
- (set (pc) (if_then_else (eq (cc0) (const_int 0))
+ (set (pc) (if_then_else (eq (match_dup 7) (const_int 0))
(match_dup 4) (match_dup 5)))]
"
{
@@ -7820,9 +6839,8 @@
operands[7] = operands[2];
}")
(define_peephole2
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (match_operand:SI 1 "pow2_m1_operand" "")))
- (set (pc) (if_then_else (leu (cc0) (const_int 0))
+ [(set (pc) (if_then_else (leu (match_operand:SI 0 "register_operand" "")
+ (match_operand:SI 1 "pow2_m1_operand" ""))
(match_operand 2 "pc_or_label_operand")
(match_operand 3 "pc_or_label_operand")))]
"INTVAL (operands[1]) <= 255
@@ -7831,8 +6849,7 @@
&& (optimize_size || TUNE_68040_60)
&& DATA_REG_P (operands[0])"
[(set (match_dup 0) (lshiftrt:SI (match_dup 0) (match_dup 4)))
- (set (cc0) (compare (match_dup 0) (const_int 0)))
- (set (pc) (if_then_else (eq (cc0) (const_int 0))
+ (set (pc) (if_then_else (eq (match_dup 0) (const_int 0))
(match_dup 2) (match_dup 3)))]
"{ operands[4] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1)); }")
@@ -7841,10 +6858,9 @@
;; internally against 65535).
;; The rotate in the output pattern will turn into a swap.
(define_peephole2
- [(set (cc0) (compare (match_operand:SI 0 "register_operand" "")
- (const_int 65535)))
- (set (pc) (if_then_else (match_operator 1 "swap_peephole_relational_operator"
- [(cc0) (const_int 0)])
+ [(set (pc) (if_then_else (match_operator 1 "swap_peephole_relational_operator"
+ [(match_operand:SI 0 "register_operand" "")
+ (const_int 65535)])
(match_operand 2 "pc_or_label_operand")
(match_operand 3 "pc_or_label_operand")))]
"peep2_reg_dead_p (1, operands[0])
@@ -7852,7 +6868,6 @@
&& (optimize_size || TUNE_68000_10)
&& DATA_REG_P (operands[0])"
[(set (match_dup 0) (rotate:SI (match_dup 0) (const_int 16)))
- (set (cc0) (compare (subreg:HI (match_dup 0) 2) (const_int 0)))
- (set (pc) (if_then_else (match_op_dup 1 [(cc0) (const_int 0)])
+ (set (pc) (if_then_else (match_op_dup 1 [(subreg:HI (match_dup 0) 2) (const_int 0)])
(match_dup 2) (match_dup 3)))]
"")
diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md
index ad297883f85..9e4c8ba864f 100644
--- a/gcc/config/m68k/predicates.md
+++ b/gcc/config/m68k/predicates.md
@@ -115,15 +115,6 @@
&& (INTVAL (op) >= (-0x7fffffff - 1) && INTVAL (op) <= 0x7fffffff));
})
-;; Return true if X is a valid comparison operator for the dbcc
-;; instruction. Note it rejects floating point comparison
-;; operators. (In the future we could use Fdbcc). It also rejects
-;; some comparisons when CC_NO_OVERFLOW is set.
-
-(define_predicate "valid_dbcc_comparison_p"
- (and (match_code "eq,ne,gtu,ltu,geu,leu,gt,lt,ge,le")
- (match_test "valid_dbcc_comparison_p_2 (op, mode)")))
-
(define_predicate "m68k_cstore_comparison_operator"
(if_then_else (match_test "TARGET_68881")
(match_operand 0 "comparison_operator")
@@ -210,10 +201,10 @@
(and (match_code "const_int")
(match_test "op == const1_rtx")))
-;; A valid operand for a HImode or QImode conditional operation.
-;; ColdFire has tst patterns, but not cmp patterns.
-(define_predicate "m68k_subword_comparison_operand"
- (if_then_else (match_test "TARGET_COLDFIRE")
+;; A valid operand for a conditional operation.
+;; ColdFire has tst patterns for HImode and QImode, but not cmp patterns.
+(define_predicate "m68k_comparison_operand"
+ (if_then_else (match_test "TARGET_COLDFIRE && mode != SImode")
(and (match_code "const_int")
(match_test "op == const0_rtx"))
(match_operand 0 "general_src_operand")))
@@ -234,15 +225,17 @@
;; Special case of general_src_operand, which rejects a few fp
;; constants (which we prefer in registers) before reload.
+;; Used only in comparisons, and we do want to allow zero.
(define_predicate "fp_src_operand"
(match_operand 0 "general_src_operand")
{
- return !CONSTANT_P (op)
- || (TARGET_68881
- && (!standard_68881_constant_p (op)
- || reload_in_progress
- || reload_completed));
+ return (!CONSTANT_P (op)
+ || op == CONST0_RTX (mode)
+ || (TARGET_68881
+ && (!standard_68881_constant_p (op)
+ || reload_in_progress
+ || reload_completed)));
})
;; Used to detect constants that are valid for addq/subq instructions
@@ -282,3 +275,6 @@
(define_predicate "swap_peephole_relational_operator"
(match_code "gtu,leu,gt,le"))
+
+(define_predicate "address_reg_operand"
+ (match_test ("ADDRESS_REG_P (op)")))
diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
index 4cea0f4e2f2..ca6222658a9 100644
--- a/gcc/config/nios2/nios2.c
+++ b/gcc/config/nios2/nios2.c
@@ -2373,6 +2373,22 @@ nios2_in_small_data_p (const_tree exp)
if (nios2_small_section_name_p (section))
return true;
}
+ else if (flexible_array_type_p (TREE_TYPE (exp))
+ && (!TREE_PUBLIC (exp) || DECL_EXTERNAL (exp)))
+ {
+ /* We really should not consider any objects of any flexibly-sized
+ type to be small data, but pre-GCC 10 did not test
+ for this and just fell through to the next case. Thus older
+ code compiled with -mgpopt=global could contain GP-relative
+ accesses to objects defined in this compilation unit with
+ external linkage. We retain the possible small-data treatment
+ of such definitions for backward ABI compatibility, but
+ no longer generate GP-relative accesses for external
+ references (so that the ABI could be changed in the future
+ with less potential impact), or objects with internal
+ linkage. */
+ return false;
+ }
else
{
HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
diff --git a/gcc/config/nios2/nios2.h b/gcc/config/nios2/nios2.h
index 9dec57d67ae..88671652707 100644
--- a/gcc/config/nios2/nios2.h
+++ b/gcc/config/nios2/nios2.h
@@ -467,10 +467,10 @@ while (0)
the linker seems to want the alignment of data objects
to depend on their types. We do exactly that here. */
-#undef ASM_OUTPUT_ALIGNED_LOCAL
-#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
+#undef ASM_OUTPUT_ALIGNED_DECL_LOCAL
+#define ASM_OUTPUT_ALIGNED_DECL_LOCAL(FILE, DECL, NAME, SIZE, ALIGN) \
do { \
- if ((SIZE) <= nios2_section_threshold) \
+ if (targetm.in_small_data_p (DECL)) \
switch_to_section (sbss_section); \
else \
switch_to_section (bss_section); \
diff --git a/gcc/config/rs6000/rs6000-call.c b/gcc/config/rs6000/rs6000-call.c
index 85ff85299d1..d332afb9c73 100644
--- a/gcc/config/rs6000/rs6000-call.c
+++ b/gcc/config/rs6000/rs6000-call.c
@@ -2935,6 +2935,10 @@ def_builtin (const char *name, tree type, enum rs6000_builtins code)
unsigned classify = rs6000_builtin_info[(int)code].attr;
const char *attr_string = "";
+ /* Don't define the builtin if it doesn't have a type. See PR92661. */
+ if (type == NULL_TREE)
+ return;
+
gcc_assert (name != NULL);
gcc_assert (IN_RANGE ((int)code, 0, (int)RS6000_BUILTIN_COUNT));
@@ -7702,6 +7706,11 @@ builtin_function_type (machine_mode mode_ret, machine_mode mode_arg0,
if (!ret_type && h.uns_p[0])
ret_type = builtin_mode_to_type[h.mode[0]][0];
+ /* If the required decimal float type has been disabled,
+ then return NULL_TREE. */
+ if (!ret_type && DECIMAL_FLOAT_MODE_P (h.mode[0]))
+ return NULL_TREE;
+
if (!ret_type)
fatal_error (input_location,
"internal error: builtin function %qs had an unexpected "
@@ -7719,6 +7728,11 @@ builtin_function_type (machine_mode mode_ret, machine_mode mode_arg0,
if (!arg_type[i] && uns_p)
arg_type[i] = builtin_mode_to_type[m][0];
+ /* If the required decimal float type has been disabled,
+ then return NULL_TREE. */
+ if (!arg_type[i] && DECIMAL_FLOAT_MODE_P (m))
+ return NULL_TREE;
+
if (!arg_type[i])
fatal_error (input_location,
"internal error: builtin function %qs, argument %d "
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 2995348f3ce..3c22f64c139 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -4915,30 +4915,11 @@ rs6000_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
static machine_mode
rs6000_preferred_simd_mode (scalar_mode mode)
{
- if (TARGET_VSX)
- switch (mode)
- {
- case E_DFmode:
- return V2DFmode;
- default:;
- }
- if (TARGET_ALTIVEC || TARGET_VSX)
- switch (mode)
- {
- case E_SFmode:
- return V4SFmode;
- case E_TImode:
- return V1TImode;
- case E_DImode:
- return V2DImode;
- case E_SImode:
- return V4SImode;
- case E_HImode:
- return V8HImode;
- case E_QImode:
- return V16QImode;
- default:;
- }
+ opt_machine_mode vmode = mode_for_vector (mode, 16 / GET_MODE_SIZE (mode));
+
+ if (vmode.exists () && !VECTOR_UNIT_NONE_P (vmode.require ()))
+ return vmode.require ();
+
return word_mode;
}
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index dff5680df0e..f3c8eb06fc1 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -2510,13 +2510,13 @@
(define_insn "bswap<mode>2_load"
[(set (match_operand:HSI 0 "gpc_reg_operand" "=r")
- (bswap:HSI (match_operand:HSI 1 "indexed_or_indirect_operand" "Z")))]
+ (bswap:HSI (match_operand:HSI 1 "memory_operand" "Z")))]
""
"l<wd>brx %0,%y1"
[(set_attr "type" "load")])
(define_insn "bswap<mode>2_store"
- [(set (match_operand:HSI 0 "indexed_or_indirect_operand" "=Z")
+ [(set (match_operand:HSI 0 "memory_operand" "=Z")
(bswap:HSI (match_operand:HSI 1 "gpc_reg_operand" "r")))]
""
"st<wd>brx %1,%y0"
@@ -2632,13 +2632,13 @@
;; Power7/cell has ldbrx/stdbrx, so use it directly
(define_insn "bswapdi2_load"
[(set (match_operand:DI 0 "gpc_reg_operand" "=r")
- (bswap:DI (match_operand:DI 1 "indexed_or_indirect_operand" "Z")))]
+ (bswap:DI (match_operand:DI 1 "memory_operand" "Z")))]
"TARGET_POWERPC64 && TARGET_LDBRX"
"ldbrx %0,%y1"
[(set_attr "type" "load")])
(define_insn "bswapdi2_store"
- [(set (match_operand:DI 0 "indexed_or_indirect_operand" "=Z")
+ [(set (match_operand:DI 0 "memory_operand" "=Z")
(bswap:DI (match_operand:DI 1 "gpc_reg_operand" "r")))]
"TARGET_POWERPC64 && TARGET_LDBRX"
"stdbrx %1,%y0"
@@ -6889,24 +6889,34 @@
UNSPEC_MOVSI_GOT))]
"")
-;; MR LA LWZ LFIWZX LXSIWZX
-;; STW STFIWX STXSIWX LI LIS
-;; # XXLOR XXSPLTIB 0 XXSPLTIB -1 VSPLTISW
-;; XXLXOR 0 XXLORC -1 P9 const MTVSRWZ MFVSRWZ
-;; MF%1 MT%0 NOP
+;; MR LA
+;; LWZ LFIWZX LXSIWZX
+;; STW STFIWX STXSIWX
+;; LI LIS #
+;; XXLOR XXSPLTIB 0 XXSPLTIB -1 VSPLTISW
+;; XXLXOR 0 XXLORC -1 P9 const
+;; MTVSRWZ MFVSRWZ
+;; MF%1 MT%0 NOP
+
(define_insn "*movsi_internal1"
[(set (match_operand:SI 0 "nonimmediate_operand"
- "=r, r, r, d, v,
- m, Z, Z, r, r,
- r, wa, wa, wa, v,
- wa, v, v, wa, r,
- r, *h, *h")
+ "=r, r,
+ r, d, v,
+ m, Z, Z,
+ r, r, r,
+ wa, wa, wa, v,
+ wa, v, v,
+ wa, r,
+ r, *h, *h")
(match_operand:SI 1 "input_operand"
- "r, U, m, Z, Z,
- r, d, v, I, L,
- n, wa, O, wM, wB,
- O, wM, wS, r, wa,
- *h, r, 0"))]
+ "r, U,
+ m, Z, Z,
+ r, d, v,
+ I, L, n,
+ wa, O, wM, wB,
+ O, wM, wS,
+ r, wa,
+ *h, r, 0"))]
"gpc_reg_operand (operands[0], SImode)
|| gpc_reg_operand (operands[1], SImode)"
"@
@@ -6934,23 +6944,32 @@
mt%0 %1
nop"
[(set_attr "type"
- "*, *, load, fpload, fpload,
- store, fpstore, fpstore, *, *,
- *, veclogical, vecsimple, vecsimple, vecsimple,
- veclogical, veclogical, vecsimple, mffgpr, mftgpr,
- *, *, *")
+ "*, *,
+ load, fpload, fpload,
+ store, fpstore, fpstore,
+ *, *, *,
+ veclogical, vecsimple, vecsimple, vecsimple,
+ veclogical, veclogical, vecsimple,
+ mffgpr, mftgpr,
+ *, *, *")
(set_attr "length"
- "*, *, *, *, *,
- *, *, *, *, *,
- 8, *, *, *, *,
- *, *, 8, *, *,
- *, *, *")
+ "*, *,
+ *, *, *,
+ *, *, *,
+ *, *, 8,
+ *, *, *, *,
+ *, *, 8,
+ *, *,
+ *, *, *")
(set_attr "isa"
- "*, *, *, p8v, p8v,
- *, p8v, p8v, *, *,
- *, p8v, p9v, p9v, p8v,
- p9v, p8v, p9v, p8v, p8v,
- *, *, *")])
+ "*, *,
+ *, p8v, p8v,
+ *, p8v, p8v,
+ *, *, *,
+ p8v, p9v, p9v, p8v,
+ p9v, p8v, p9v,
+ p8v, p8v,
+ *, *, *")])
;; Like movsi, but adjust a SF value to be used in a SI context, i.e.
;; (set (reg:SI ...) (subreg:SI (reg:SF ...) 0))
@@ -8808,24 +8827,33 @@
DONE;
})
-;; GPR store GPR load GPR move GPR li GPR lis GPR #
-;; FPR store FPR load FPR move AVX store AVX store AVX load
-;; AVX load VSX move P9 0 P9 -1 AVX 0/-1 VSX 0
-;; VSX -1 P9 const AVX const From SPR To SPR SPR<->SPR
-;; VSX->GPR GPR->VSX
+;; GPR store GPR load GPR move
+;; GPR li GPR lis GPR #
+;; FPR store FPR load FPR move
+;; AVX store AVX store AVX load AVX load VSX move
+;; P9 0 P9 -1 AVX 0/-1 VSX 0 VSX -1
+;; P9 const AVX const
+;; From SPR To SPR SPR<->SPR
+;; VSX->GPR GPR->VSX
(define_insn "*movdi_internal64"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=YZ, r, r, r, r, r,
- m, ^d, ^d, wY, Z, $v,
- $v, ^wa, wa, wa, v, wa,
- wa, v, v, r, *h, *h,
- ?r, ?wa")
+ "=YZ, r, r,
+ r, r, r,
+ m, ^d, ^d,
+ wY, Z, $v, $v, ^wa,
+ wa, wa, v, wa, wa,
+ v, v,
+ r, *h, *h,
+ ?r, ?wa")
(match_operand:DI 1 "input_operand"
- "r, YZ, r, I, L, nF,
- ^d, m, ^d, ^v, $v, wY,
- Z, ^wa, Oj, wM, OjwM, Oj,
- wM, wS, wB, *h, r, 0,
- wa, r"))]
+ "r, YZ, r,
+ I, L, nF,
+ ^d, m, ^d,
+ ^v, $v, wY, Z, ^wa,
+ Oj, wM, OjwM, Oj, wM,
+ wS, wB,
+ *h, r, 0,
+ wa, r"))]
"TARGET_POWERPC64
&& (gpc_reg_operand (operands[0], DImode)
|| gpc_reg_operand (operands[1], DImode))"
@@ -8857,24 +8885,33 @@
mfvsrd %0,%x1
mtvsrd %x0,%1"
[(set_attr "type"
- "store, load, *, *, *, *,
- fpstore, fpload, fpsimple, fpstore, fpstore, fpload,
- fpload, veclogical, vecsimple, vecsimple, vecsimple, veclogical,
- veclogical, vecsimple, vecsimple, mfjmpr, mtjmpr, *,
- mftgpr, mffgpr")
+ "store, load, *,
+ *, *, *,
+ fpstore, fpload, fpsimple,
+ fpstore, fpstore, fpload, fpload, veclogical,
+ vecsimple, vecsimple, vecsimple, veclogical, veclogical,
+ vecsimple, vecsimple,
+ mfjmpr, mtjmpr, *,
+ mftgpr, mffgpr")
(set_attr "size" "64")
(set_attr "length"
- "*, *, *, *, *, 20,
- *, *, *, *, *, *,
- *, *, *, *, *, *,
- *, 8, *, *, *, *,
- *, *")
+ "*, *, *,
+ *, *, 20,
+ *, *, *,
+ *, *, *, *, *,
+ *, *, *, *, *,
+ 8, *,
+ *, *, *,
+ *, *")
(set_attr "isa"
- "*, *, *, *, *, *,
- *, *, *, p9v, p7v, p9v,
- p7v, *, p9v, p9v, p7v, *,
- *, p7v, p7v, *, *, *,
- p8v, p8v")])
+ "*, *, *,
+ *, *, *,
+ *, *, *,
+ p9v, p7v, p9v, p7v, *,
+ p9v, p9v, p7v, *, *,
+ p7v, p7v,
+ *, *, *,
+ p8v, p8v")])
; Some DImode loads are best done as a load of -1 followed by a mask
; instruction.
diff --git a/gcc/config/s390/linux.h b/gcc/config/s390/linux.h
index 5f6b7041f0f..b7d440543f7 100644
--- a/gcc/config/s390/linux.h
+++ b/gcc/config/s390/linux.h
@@ -75,7 +75,9 @@ along with GCC; see the file COPYING3. If not see
#define GLIBC_DYNAMIC_LINKER32 "/lib/ld.so.1"
#define GLIBC_DYNAMIC_LINKER64 "/lib/ld64.so.1"
+#undef MUSL_DYNAMIC_LINKER32
#define MUSL_DYNAMIC_LINKER32 "/lib/ld-musl-s390.so.1"
+#undef MUSL_DYNAMIC_LINKER64
#define MUSL_DYNAMIC_LINKER64 "/lib/ld-musl-s390x.so.1"
#undef LINK_SPEC
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 33e2cfeede8..3a6bf059a2d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,197 @@
+2019-11-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/60228
+ * parser.c (cp_parser_omp_declare_reduction_exprs): If
+ processing_template_decl, wrap the combiner or initializer
+ into EXPR_STMT.
+ * decl.c (start_preparsed_function): Don't start a lambda scope
+ for DECL_OMP_DECLARE_REDUCTION_P functions.
+ (finish_function): Don't finish a lambda scope for
+ DECL_OMP_DECLARE_REDUCTION_P functions, nor cp_fold_function
+ them nor cp_genericize them.
+ * mangle.c (decl_mangling_context): Look through
+ DECL_OMP_DECLARE_REDUCTION_P functions.
+ * semantics.c (expand_or_defer_fn_1): For DECL_OMP_DECLARE_REDUCTION_P
+ functions, use tentative linkage, don't keep their bodies with
+ -fkeep-inline-functions and return false at the end.
+
+2019-11-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/92695
+ * decl2.c (mark_used): Don't call note_vague_linkage_fn for pure
+ virtual functions, even if they are declared inline.
+
+2019-11-16 Jason Merrill <jason@redhat.com>
+
+ Implement P1814R0, CTAD for alias templates.
+ * pt.c (rewrite_tparm_list): Factor out of build_deduction_guide.
+ (maybe_aggr_guide): Check for copy-init here.
+ (alias_ctad_tweaks, deduction_guides_for): New.
+ (ctor_deduction_guides_for): Factor out of do_class_deduction.
+ (ctad_template_p): New.
+ * parser.c (cp_parser_simple_type_specifier): Use it.
+ * constraint.cc (append_constraint): New.
+
+2019-11-16 Jason Merrill <jason@redhat.com>
+
+ * cxx-pretty-print.c (pp_cxx_unqualified_id): Handle alias
+ template-id.
+ * pt.c (complex_alias_template_p): True if constraints.
+ (get_underlying_template, tsubst): Check alias constraints.
+ (push_template_decl_real): Set alias constraints here.
+ * parser.c (cp_parser_alias_declaration): Not here.
+ * constraint.cc (get_constraints): Take const_tree.
+
+2019-11-12 Jason Merrill <jason@redhat.com>
+
+ PR c++/92206 - ICE with typedef to dependent alias.
+ * pt.c (dependent_alias_template_spec_p)
+ (alias_template_specialization_p): Add transparent_typedefs
+ parameter.
+ (iterative_hash_template_arg, any_template_parm_r)
+ (primary_template_specialization_p, tsubst, dependent_type_p_r):
+ Adjust.
+ * decl.c (check_elaborated_type_specifier): Adjust.
+ * error.c (dump_template_bindings, dump_aggr_type): Adjust.
+
+2019-11-27 Andrew Sutton <asutton@lock3software.com>
+
+ PR c++/92236
+ Defer evaluation of concept checks so that static assertions can
+ emit more detailed diagnostics.
+ * constexpr.c (cxx_eval_call_expression): Handle concept checks.
+ (cxx_eval_constant_expression): Diagnose misuse of function concepts
+ as template-id expressions. Follow the usual return path for results.
+ (cxx_eval_outermost_constant_expr): Avoid calling
+ cp_get_callee_fndecl_nofold for function concepts.
+ * constraint.cc (build_function_check): Fully type the concept check
+ so that we don't ICE in conversions.
+ * cp-gimplify.c (cp_genericize_r) [CALL_EXPR]: Handle concept checks.
+ [TEMPLATE_ID_EXPR] Likewise.
+ * cvt.c (convert_to_void): Always evaluate concept checks so we don't
+ accidentally ignore them. Substitution during satisfaction can make
+ a program ill-formed (example in g++.dg/cpp2a/concepts6.C).
+ * pt.c (tsubst_copy_and_build): [CALL_EXPR]: Don't evaluate concepts.
+ [TEMPLATE_ID_EXPR]: Likewise.
+ * semantics.c (finish_call_expr): Don't evaluate concepts.
+ (finish_id_expression_1): Likewise.
+ (finish_static_assert): Preserve the original condition so we can
+ diagnose concept errors when a check returns false.
+
+2019-11-27 Andrew Sutton <asutton@lock3software.com>
+
+ PR c++/92439
+ Improve quality of diagnostics for subexpressions that need parens.
+ * parser.c (cp_parser_requires_clause_opt): Add a flag to indicate
+ when parsing a requires-clause before lambda parameters, and...
+ (cp_parser_lambda_declarator_opt): ... use that here ...
+ (cp_parser_type_parameter): ... and here ...
+ (cp_parser_late_return_type_opt): ... and here ...
+ (cp_parser_explicit_template_declaration): ... and here.
+ (cp_parser_diagnose_ungrouped_constraint_plain): Adjust the message
+ because this can apply to subexpressions that are not immediately
+ after a requires-clause.
+ (cp_parser_diagnose_ungrouped_constraint_rich): Likewise.
+ (primary_constraint_error): New.
+ (cp_parser_constraint_requires_parens): New.
+ (cp_parser_unary_constraint_requires_parens): New.
+ (cp_parser_constraint_primary_expression): Check for unary expressions
+ before parsing the primary expression. Also check for binary and
+ postfix operators after a successful parse of the primary expression.
+ Force a re-parse if the result would form a lower-precedence string.
+ (cp_parser_constraint_logical_and_expression): Propagate lambda flag;
+ move checks for ill-formed constraints into the constraint primary
+ expression.
+ (cp_parser_constraint_logical_or_expression): Likewise.
+ (cp_parser_requires_clause_expression): Propagate lambda flag.
+
+2019-11-27 Andrew Sutton <asutton@lock3software.com>
+
+ PR c++/88395
+ * constraint.cc (satisfy_declaration_constraints): Push tinst levels
+ around satisfaction.
+
+2019-11-27 Andrew Sutton <asutton@lock3software.com>
+
+ Diagnose certain constraint errors as hard errors, but otherwise treat
+ them the same as normal SFINAE-type errors. Also, generally clean up
+ the satisfaction functions.
+
+ * constexpr.c (cxx_eval_constant_expression): Use
+ evaluate_concept_check.
+ * constraint.cc (normalize_concept_definition): Accept a diagnostic
+ flag and only cache when not diagnosing errors.
+ (decl_satisfied_cache): Map to trees instead of bools.
+ (satisfy_atom): Guarantee a location for the errors, propagate complain
+ flags to force_rvalue, and emit errors for non-boolean constraints.
+ (get_normalized_constraints_and_args): New overloads. Factored out of
+ satisfy_constraint_expression and satisfy_declaration_constraints.
+ (satisfy_constraint_expression): Propagate diagnostic info to
+ normalization.
+ (satisfy_declaration_constraints): New. Factored out of
+ constraints_satisfied_p.
+ (constraint_satisfaction_value): New. Calls
+ satisfy_constraint_expression or satisfy_declaration_constraints.
+ (constraints_satisfied_p): Call constraint_satisfaction_value.
+ (evaluate_concept_check): Don't take tsubst_falgs_t. Replay
+ satisfaction if an error is encountered.
+ (current_failed_constraint): Moved from pt.c.
+ (diagnose_constraints): Call constraint_satisfaction_value.
+ * cp-tree.h: Update declarations.
+ * pt.c (current_failed_constraint): Moved to constraint.cc.
+ * semantics.c (finish_id_expression_1): Remove a duplicate case.
+
+2019-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/92524
+ * tree.c (replace_placeholders_r): Don't walk constructor elts with
+ RANGE_EXPR indexes.
+
+2019-11-26 Jason Merrill <jason@redhat.com>
+
+ * pt.c (tsubst_copy_and_build) [TEMPLATE_ID_EXPR]: Remember the
+ location of a variable template-id.
+ * constexpr.c (cxx_eval_constant_expression): Get expr location
+ before stripping location wrappers.
+ (non_const_var_error): Take location argument.
+
+2019-11-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * typeck.c (cp_build_unary_op): Consistently use the accurate
+ location in seven additional diagnostic messages.
+ (cp_build_compound_expr): Use cp_expr_loc_or_input_loc in one place.
+
+2019-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/92648
+ * parser.c (cp_parser_std_attribute): For unknown attributes,
+ skip balanced token seq instead of trying to parse
+ attribute-argument-clause as expression list. Formatting fix.
+
+ PR c++/61414
+ * class.c (enum_to_min_precision): New hash_map.
+ (enum_min_precision): New function.
+ (check_bitfield_decl): Use it.
+
+2019-11-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * typeck.c (cp_build_indirect_ref_1): Add location_t parameter
+ and use it in error messages.
+ (build_x_indirect_ref): Adjust call.
+ (build_indirect_ref): Likewise.
+ (cp_build_fold_indirect_ref): Likewise.
+ (cp_build_array_ref): Likewise.
+ * call.c (build_new_op_1): Likewise.
+ * semantics.c (finish_omp_clauses): Likewise.
+ (finish_omp_depobj): Likewise.
+ * typeck2.c (build_x_arrow): Likewise.
+ * cp-tree.h (cp_build_indirect_ref): Update declaration.
+
+ * call.c (build_new_op_1): Use location argument in warning_at.
+
+ * typeck.c (cp_build_modify_expr): Consistently use the
+ location_t argument.
+
2019-11-23 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR c++/92365
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 93517d3c425..46ffad2ddf1 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -4399,7 +4399,7 @@ build_converted_constant_bool_expr (tree expr, tsubst_flags_t complain)
/* Do any initial processing on the arguments to a function call. */
-static vec<tree, va_gc> *
+vec<tree, va_gc> *
resolve_args (vec<tree, va_gc> *args, tsubst_flags_t complain)
{
unsigned int ix;
@@ -6366,11 +6366,9 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags,
&& (TYPE_MAIN_VARIANT (arg1_type)
!= TYPE_MAIN_VARIANT (arg2_type))
&& (complain & tf_warning))
- {
- warning (OPT_Wenum_compare,
- "comparison between %q#T and %q#T",
- arg1_type, arg2_type);
- }
+ warning_at (loc, OPT_Wenum_compare,
+ "comparison between %q#T and %q#T",
+ arg1_type, arg2_type);
break;
default:
break;
@@ -6428,7 +6426,7 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags,
return cp_build_modify_expr (loc, arg1, code2, arg2, complain);
case INDIRECT_REF:
- return cp_build_indirect_ref (arg1, RO_UNARY_STAR, complain);
+ return cp_build_indirect_ref (loc, arg1, RO_UNARY_STAR, complain);
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
@@ -6485,8 +6483,9 @@ build_new_op_1 (const op_location_t &loc, enum tree_code code, int flags,
return cp_build_array_ref (input_location, arg1, arg2, complain);
case MEMBER_REF:
- return build_m_component_ref (cp_build_indirect_ref (arg1, RO_ARROW_STAR,
- complain),
+ return build_m_component_ref (cp_build_indirect_ref (loc, arg1,
+ RO_ARROW_STAR,
+ complain),
arg2, complain);
/* The caller will deal with these. */
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index ef1d5136963..f36f75fa0db 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3265,6 +3265,60 @@ add_implicitly_declared_members (tree t, tree* access_decls,
}
}
+/* Cache of enum_min_precision values. */
+static GTY((deletable)) hash_map<tree, int> *enum_to_min_precision;
+
+/* Return the minimum precision of a bit-field needed to store all
+ enumerators of ENUMERAL_TYPE TYPE. */
+
+static int
+enum_min_precision (tree type)
+{
+ type = TYPE_MAIN_VARIANT (type);
+ /* For unscoped enums without fixed underlying type and without mode
+ attribute we can just use precision of the underlying type. */
+ if (UNSCOPED_ENUM_P (type)
+ && !ENUM_FIXED_UNDERLYING_TYPE_P (type)
+ && !lookup_attribute ("mode", TYPE_ATTRIBUTES (type)))
+ return TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type));
+
+ if (enum_to_min_precision == NULL)
+ enum_to_min_precision = hash_map<tree, int>::create_ggc (37);
+
+ bool existed;
+ int prec = enum_to_min_precision->get_or_insert (type, &existed);
+ if (existed)
+ return prec;
+
+ tree minnode, maxnode;
+ if (TYPE_VALUES (type))
+ {
+ minnode = maxnode = NULL_TREE;
+ for (tree values = TYPE_VALUES (type);
+ values; values = TREE_CHAIN (values))
+ {
+ tree decl = TREE_VALUE (values);
+ tree value = DECL_INITIAL (decl);
+ if (value == error_mark_node)
+ value = integer_zero_node;
+ if (!minnode)
+ minnode = maxnode = value;
+ else if (tree_int_cst_lt (maxnode, value))
+ maxnode = value;
+ else if (tree_int_cst_lt (value, minnode))
+ minnode = value;
+ }
+ }
+ else
+ minnode = maxnode = integer_zero_node;
+
+ signop sgn = tree_int_cst_sgn (minnode) >= 0 ? UNSIGNED : SIGNED;
+ int lowprec = tree_int_cst_min_precision (minnode, sgn);
+ int highprec = tree_int_cst_min_precision (maxnode, sgn);
+ prec = MAX (lowprec, highprec);
+ return prec;
+}
+
/* FIELD is a bit-field. We are finishing the processing for its
enclosing type. Issue any appropriate messages and set appropriate
flags. Returns false if an error has been diagnosed. */
@@ -3326,7 +3380,7 @@ check_bitfield_decl (tree field)
"width of %qD exceeds its type", field);
else if (TREE_CODE (type) == ENUMERAL_TYPE)
{
- int prec = TYPE_PRECISION (ENUM_UNDERLYING_TYPE (type));
+ int prec = enum_min_precision (type);
if (compare_tree_int (w, prec) < 0)
warning_at (DECL_SOURCE_LOCATION (field), 0,
"%qD is too small to hold all values of %q#T",
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index f2628a07626..36f8c81c9c0 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1672,6 +1672,10 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
bool lval,
bool *non_constant_p, bool *overflow_p)
{
+ /* Handle concept checks separately. */
+ if (concept_check_p (t))
+ return evaluate_concept_check (t, tf_warning_or_error);
+
location_t loc = cp_expr_loc_or_input_loc (t);
tree fun = get_function_named_in_call (t);
constexpr_call new_call
@@ -3786,27 +3790,27 @@ cxx_eval_indirect_ref (const constexpr_ctx *ctx, tree t,
cxx_eval_constant_expression. */
static void
-non_const_var_error (tree r)
+non_const_var_error (location_t loc, tree r)
{
auto_diagnostic_group d;
tree type = TREE_TYPE (r);
if (DECL_NAME (r) == heap_uninit_identifier
|| DECL_NAME (r) == heap_identifier)
{
- error ("the content of uninitialized storage is not usable "
- "in a constant expression");
+ error_at (loc, "the content of uninitialized storage is not usable "
+ "in a constant expression");
inform (DECL_SOURCE_LOCATION (r), "allocated here");
return;
}
if (DECL_NAME (r) == heap_deleted_identifier)
{
- error ("use of allocated storage after deallocation in a "
- "constant expression");
+ error_at (loc, "use of allocated storage after deallocation in a "
+ "constant expression");
inform (DECL_SOURCE_LOCATION (r), "allocated here");
return;
}
- error ("the value of %qD is not usable in a constant "
- "expression", r);
+ error_at (loc, "the value of %qD is not usable in a constant "
+ "expression", r);
/* Avoid error cascade. */
if (DECL_INITIAL (r) == error_mark_node)
return;
@@ -4765,6 +4769,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
return t;
}
+ location_t loc = cp_expr_loc_or_input_loc (t);
+
STRIP_ANY_LOCATION_WRAPPER (t);
if (CONSTANT_CLASS_P (t))
@@ -4794,7 +4800,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (++ctx->global->constexpr_ops_count >= constexpr_ops_limit)
{
if (!ctx->quiet)
- error_at (cp_expr_loc_or_input_loc (t),
+ error_at (loc,
"%<constexpr%> evaluation operation count exceeds limit of "
"%wd (use %<-fconstexpr-ops-limit=%> to increase the limit)",
constexpr_ops_limit);
@@ -4877,7 +4883,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (DECL_P (r))
{
if (!ctx->quiet)
- non_const_var_error (r);
+ non_const_var_error (loc, r);
*non_constant_p = true;
}
break;
@@ -5086,9 +5092,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
jump_target);
if (!CLEANUP_EH_ONLY (t) && !*non_constant_p)
{
- location_t loc = input_location;
- if (EXPR_HAS_LOCATION (t))
- input_location = EXPR_LOCATION (t);
+ iloc_sentinel ils (loc);
/* Also evaluate the cleanup. If we weren't skipping at the
start of the CLEANUP_BODY, change jump_target temporarily
to &initial_jump_target, so that even a return or break or
@@ -5097,7 +5101,6 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
non_constant_p, overflow_p,
jump_target ? &initial_jump_target
: NULL);
- input_location = loc;
}
}
break;
@@ -5365,7 +5368,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (REINTERPRET_CAST_P (t))
{
if (!ctx->quiet)
- error_at (cp_expr_loc_or_input_loc (t),
+ error_at (loc,
"%<reinterpret_cast%> is not a constant expression");
*non_constant_p = true;
return t;
@@ -5405,7 +5408,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (TYPE_REF_P (type))
{
if (!ctx->quiet)
- error_at (cp_expr_loc_or_input_loc (t),
+ error_at (loc,
"dereferencing a null pointer");
*non_constant_p = true;
return t;
@@ -5417,7 +5420,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
if (!can_convert (type, from, tf_none))
{
if (!ctx->quiet)
- error_at (cp_expr_loc_or_input_loc (t),
+ error_at (loc,
"conversion of %qT null pointer to %qT "
"is not a constant expression",
from, type);
@@ -5432,8 +5435,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
reinterpret_cast<void*>(sizeof 0)
*/
if (!ctx->quiet)
- error_at (cp_expr_loc_or_input_loc (t),
- "%<reinterpret_cast<%T>(%E)%> is not "
+ error_at (loc, "%<reinterpret_cast<%T>(%E)%> is not "
"a constant expression",
type, op);
*non_constant_p = true;
@@ -5534,8 +5536,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
case BASELINK:
case OFFSET_REF:
if (!ctx->quiet)
- error_at (cp_expr_loc_or_input_loc (t),
- "expression %qE is not a constant expression", t);
+ error_at (loc, "expression %qE is not a constant expression", t);
*non_constant_p = true;
break;
@@ -5552,8 +5553,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
|| !DECL_P (get_base_address (TREE_OPERAND (obj, 0))))
{
if (!ctx->quiet)
- error_at (cp_expr_loc_or_input_loc (t),
- "expression %qE is not a constant expression", t);
+ error_at (loc, "expression %qE is not a constant expression", t);
*non_constant_p = true;
return t;
}
@@ -5649,19 +5649,31 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
{
/* We can evaluate template-id that refers to a concept only if
the template arguments are non-dependent. */
- if (!concept_definition_p (TREE_OPERAND (t, 0)))
+ tree id = unpack_concept_check (t);
+ tree tmpl = TREE_OPERAND (id, 0);
+ if (!concept_definition_p (tmpl))
internal_error ("unexpected template-id %qE", t);
+ if (function_concept_p (tmpl))
+ {
+ if (!ctx->quiet)
+ error_at (cp_expr_loc_or_input_loc (t),
+ "function concept must be called");
+ r = error_mark_node;
+ break;
+ }
+
if (!processing_template_decl)
- return satisfy_constraint_expression (t);
+ r = evaluate_concept_check (t, tf_warning_or_error);
else
*non_constant_p = true;
- return t;
+
+ break;
}
case ASM_EXPR:
if (!ctx->quiet)
- inline_asm_in_constexpr_error (cp_expr_loc_or_input_loc (t));
+ inline_asm_in_constexpr_error (loc);
*non_constant_p = true;
return t;
@@ -5813,12 +5825,16 @@ cxx_eval_outermost_constant_expr (tree t, bool allow_non_constant,
|| TREE_CODE (t) == AGGR_INIT_EXPR
|| TREE_CODE (t) == TARGET_EXPR))
{
- tree x = t;
- if (TREE_CODE (x) == TARGET_EXPR)
- x = TARGET_EXPR_INITIAL (x);
- tree fndecl = cp_get_callee_fndecl_nofold (x);
- if (fndecl && DECL_IMMEDIATE_FUNCTION_P (fndecl))
- is_consteval = true;
+ /* For non-concept checks, determine if it is consteval. */
+ if (!concept_check_p (t))
+ {
+ tree x = t;
+ if (TREE_CODE (x) == TARGET_EXPR)
+ x = TARGET_EXPR_INITIAL (x);
+ tree fndecl = cp_get_callee_fndecl_nofold (x);
+ if (fndecl && DECL_IMMEDIATE_FUNCTION_P (fndecl))
+ is_consteval = true;
+ }
}
if (AGGREGATE_TYPE_P (type) || VECTOR_TYPE_P (type))
{
@@ -6724,7 +6740,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
&& !is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false))
{
if (flags & tf_error)
- non_const_var_error (t);
+ non_const_var_error (loc, t);
return false;
}
return true;
diff --git a/gcc/cp/constraint.cc b/gcc/cp/constraint.cc
index 171ca4e0ed4..533277a758f 100644
--- a/gcc/cp/constraint.cc
+++ b/gcc/cp/constraint.cc
@@ -849,10 +849,12 @@ get_normalized_constraints_from_decl (tree d, bool diag = false)
/* Returns the normal form of TMPL's definition. */
static tree
-normalize_concept_definition (tree tmpl)
+normalize_concept_definition (tree tmpl, bool diag = false)
{
- if (tree *p = hash_map_safe_get (normalized_map, tmpl))
- return *p;
+ if (!diag)
+ if (tree *p = hash_map_safe_get (normalized_map, tmpl))
+ return *p;
+
gcc_assert (concept_definition_p (tmpl));
if (OVL_P (tmpl))
tmpl = OVL_FIRST (tmpl);
@@ -860,10 +862,13 @@ normalize_concept_definition (tree tmpl)
tree args = generic_targs_for (tmpl);
tree def = get_concept_definition (DECL_TEMPLATE_RESULT (tmpl));
++processing_template_decl;
- norm_info info (tmpl, tf_none);
+ norm_info info (tmpl, diag ? tf_norm : tf_none);
tree norm = get_normalized_constraints (def, args, info);
--processing_template_decl;
- hash_map_safe_put<hm_ggc> (normalized_map, tmpl, norm);
+
+ if (!diag)
+ hash_map_safe_put<hm_ggc> (normalized_map, tmpl, norm);
+
return norm;
}
@@ -1111,6 +1116,25 @@ build_constraints (tree tr, tree dr)
return (tree)ci;
}
+/* Add constraint RHS to the end of CONSTRAINT_INFO ci. */
+
+tree
+append_constraint (tree ci, tree rhs)
+{
+ tree tr = ci ? CI_TEMPLATE_REQS (ci) : NULL_TREE;
+ tree dr = ci ? CI_DECLARATOR_REQS (ci) : NULL_TREE;
+ dr = combine_constraint_expressions (dr, rhs);
+ if (ci)
+ {
+ CI_DECLARATOR_REQS (ci) = dr;
+ tree ac = combine_constraint_expressions (tr, dr);
+ CI_ASSOCIATED_CONSTRAINTS (ci) = ac;
+ }
+ else
+ ci = build_constraints (tr, dr);
+ return ci;
+}
+
/* A mapping from declarations to constraint information. */
static GTY ((cache)) decl_tree_cache_map *decl_constraints;
@@ -1119,7 +1143,7 @@ static GTY ((cache)) decl_tree_cache_map *decl_constraints;
constrained, return NULL_TREE. Note that T must be non-null. */
tree
-get_constraints (tree t)
+get_constraints (const_tree t)
{
if (!flag_concepts)
return NULL_TREE;
@@ -1129,7 +1153,7 @@ get_constraints (tree t)
gcc_assert (DECL_P (t));
if (TREE_CODE (t) == TEMPLATE_DECL)
t = DECL_TEMPLATE_RESULT (t);
- tree* found = decl_constraints->get (t);
+ tree* found = decl_constraints->get (CONST_CAST_TREE (t));
if (found)
return *found;
else
@@ -1258,6 +1282,7 @@ build_function_check (tree tmpl, tree args, tsubst_flags_t /*complain*/)
++processing_template_decl;
vec<tree, va_gc> *fargs = make_tree_vector ();
tree call = build_min_nt_call_vec (id, fargs);
+ TREE_TYPE (call) = boolean_type_node;
release_tree_vector (fargs);
--processing_template_decl;
@@ -1392,6 +1417,7 @@ build_constrained_parameter (tree cnc, tree proto, tree args)
Note that the constraints are neither reduced nor decomposed. That is
done only after the requires clause has been parsed (or not). */
+
tree
finish_shorthand_constraint (tree decl, tree constr)
{
@@ -2231,8 +2257,8 @@ struct sat_hasher : ggc_ptr_hash<sat_entry>
/* Cache the result of satisfy_atom. */
static GTY((deletable)) hash_table<sat_hasher> *sat_cache;
-/* Cache the result of constraints_satisfied_p. */
-static GTY((deletable)) hash_map<tree,bool> *decl_satisfied_cache;
+/* Cache the result of constraint_satisfaction_value. */
+static GTY((deletable)) hash_map<tree, tree> *decl_satisfied_cache;
static tree
get_satisfaction (tree constr, tree args)
@@ -2481,21 +2507,17 @@ satisfy_atom (tree t, tree args, subst_info info)
return cache.save (boolean_false_node);
}
- location_t loc = cp_expr_location (expr);
+ location_t loc = cp_expr_loc_or_input_loc (expr);
/* [17.4.1.2] ... lvalue-to-value conversion is performed as necessary,
and EXPR shall be a constant expression of type bool. */
- result = force_rvalue (result, tf_error);
+ result = force_rvalue (result, info.complain);
if (result == error_mark_node)
- {
- if (info.noisy ())
- inform (loc, "cannot convert constraint to rvalue");
- return cache.save (error_mark_node);
- }
+ return cache.save (error_mark_node);
if (!same_type_p (TREE_TYPE (result), boolean_type_node))
{
if (info.noisy ())
- inform (loc, "constraint does not have type %<bool%>");
+ error_at (loc, "constraint does not have type %<bool%>");
return cache.save (error_mark_node);
}
@@ -2560,7 +2582,7 @@ satisfy_constraint (tree t, tree args, subst_info info)
static tree
satisfy_associated_constraints (tree t, tree args, subst_info info)
{
- /* If there are no constraints then this is trivially satisfied. */
+ /* If there are no constraints then this is trivially satisfied. */
if (!t)
return boolean_true_node;
@@ -2576,24 +2598,31 @@ satisfy_associated_constraints (tree t, tree args, subst_info info)
satisfaction value. */
static tree
-satisfy_constraint_expression (tree expr, tree args, subst_info info)
+satisfy_constraint_expression (tree t, tree args, subst_info info)
{
- /* Normalize the expression before satisfaction testing. */
+ if (t == error_mark_node)
+ return error_mark_node;
+
+ gcc_assert (EXPR_P (t));
+
+ /* Get the normalized constraints. */
tree norm;
- if (args == NULL_TREE && concept_check_p (expr))
+ if (args == NULL_TREE && concept_check_p (t))
{
- tree id = unpack_concept_check (expr);
+ tree id = unpack_concept_check (t);
args = TREE_OPERAND (id, 1);
tree tmpl = get_concept_check_template (id);
- norm = normalize_concept_definition (tmpl);
+ norm = normalize_concept_definition (tmpl, info.noisy ());
}
else
- norm = normalize_constraint_expression (expr);
+ norm = normalize_constraint_expression (t, info.noisy ());
+
+ /* Perform satisfaction. */
return satisfy_constraint (norm, args, info);
}
-/* Used to evaluate concept checks and requires-expressions during
- constant expression evaluation. */
+/* Used only to evaluate requires-expressions during constant expression
+ evaluation. */
tree
satisfy_constraint_expression (tree expr)
@@ -2602,20 +2631,10 @@ satisfy_constraint_expression (tree expr)
return satisfy_constraint_expression (expr, NULL_TREE, info);
}
-/* True if T is satisfied for ARGS. */
-
-static bool
-constraint_expression_satisfied_p (tree t, tree args, subst_info info)
-{
- tree r = satisfy_constraint_expression (t, args, info);
- return r == boolean_true_node;
-}
-
-static bool
-constraints_satisfied_p (tree t, subst_info info)
+static tree
+satisfy_declaration_constraints (tree t, subst_info info)
{
- if (!DECL_P (t))
- return constraint_expression_satisfied_p (t, NULL_TREE, info);
+ gcc_assert (DECL_P (t));
/* For inherited constructors, consider the original declaration;
it has the correct template information attached. */
@@ -2626,21 +2645,19 @@ constraints_satisfied_p (tree t, subst_info info)
info.in_decl = t;
if (info.quiet ())
- if (bool *p = hash_map_safe_get (decl_satisfied_cache, t))
- return *p;
+ if (tree *result = hash_map_safe_get (decl_satisfied_cache, t))
+ return *result;
- /* Get the constraints to check for satisfaction. This depends
- on whether we're looking at a template specialization or not. */
+ /* Get the normalized constraints. */
tree norm = NULL_TREE;
tree args = NULL_TREE;
- tree ti = DECL_TEMPLATE_INFO (t);
- if (ti)
+ if (tree ti = DECL_TEMPLATE_INFO (t))
{
tree tmpl = TI_TEMPLATE (ti);
norm = normalize_template_requirements (tmpl, info.noisy ());
/* The initial parameter mapping is the complete set of
- template arguments substituted into the declaration. */
+ template arguments substituted into the declaration. */
args = TI_ARGS (ti);
}
else
@@ -2649,44 +2666,25 @@ constraints_satisfied_p (tree t, subst_info info)
norm = normalize_nontemplate_requirements (t, info.noisy ());
}
- bool r = true;
+ tree result = boolean_true_node;
if (norm)
{
+ push_tinst_level (t);
push_access_scope (t);
- tree eval = satisfy_associated_constraints (norm, args, info);
+ result = satisfy_associated_constraints (norm, args, info);
pop_access_scope (t);
- r = (eval == boolean_true_node);
+ pop_tinst_level ();
}
if (info.quiet ())
- hash_map_safe_put<hm_ggc> (decl_satisfied_cache, t, r);
+ hash_map_safe_put<hm_ggc> (decl_satisfied_cache, t, result);
- return r;
-}
-
-/* Returns true if the T's constraints are satisfied, of if T is an expression,
- if T is satisfied. This is used in cases where the arguments can be
- determined from the declaration or expression.
-
- Note that T is typically a template specialization. */
-
-bool
-constraints_satisfied_p (tree t)
-{
- subst_info info (tf_none, NULL_TREE);
- return constraints_satisfied_p (t, info);
+ return result;
}
-/* Returns true if the expression or constrained declaration T is
- satisfied by ARGS. In this case, we don't have a specialization
- where we can cache the results (e.g., alias templates). */
-
-static bool
-constraints_satisfied_p (tree t, tree args, subst_info info)
+static tree
+satisfy_declaration_constraints (tree t, tree args, subst_info info)
{
- if (!DECL_P (t))
- return constraint_expression_satisfied_p (t, args, info);
-
/* Update the declaration for diagnostics. */
info.in_decl = t;
@@ -2695,46 +2693,72 @@ constraints_satisfied_p (tree t, tree args, subst_info info)
{
tree pattern = DECL_TEMPLATE_RESULT (t);
push_access_scope (pattern);
- tree eval = satisfy_associated_constraints (norm, args, info);
+ tree result = satisfy_associated_constraints (norm, args, info);
pop_access_scope (pattern);
- return eval == boolean_true_node;
+ return result;
}
- return true;
+ return boolean_true_node;
+}
+
+static tree
+constraint_satisfaction_value (tree t, tsubst_flags_t complain)
+{
+ subst_info info (complain, NULL_TREE);
+ if (DECL_P (t))
+ return satisfy_declaration_constraints (t, info);
+ else
+ return satisfy_constraint_expression (t, NULL_TREE, info);
+}
+
+static tree
+constraint_satisfaction_value (tree t, tree args, tsubst_flags_t complain)
+{
+ subst_info info (complain, NULL_TREE);
+ if (DECL_P (t))
+ return satisfy_declaration_constraints (t, args, info);
+ else
+ return satisfy_constraint_expression (t, args, info);
+}
+
+/* True iff the result of satisfying T is BOOLEAN_TRUE_NODE and false
+ otherwise, even in the case of errors. */
+
+bool
+constraints_satisfied_p (tree t)
+{
+ return constraint_satisfaction_value (t, tf_none) == boolean_true_node;
}
+/* True iff the result of satisfying T with ARGS is BOOLEAN_TRUE_NODE
+ and false otherwise, even in the case of errors. */
+
bool
constraints_satisfied_p (tree t, tree args)
{
- subst_info info (tf_none, NULL);
- return constraints_satisfied_p (t, args, info);
+ return constraint_satisfaction_value (t, args, tf_none) == boolean_true_node;
}
-/* Evaluate a concept check of the form C<ARGS>, returning either TRUE
- or FALSE. If ARGS contains any template parameters, this returns the
- check. If satisfaction yields a hard error, diagnose the error. */
+/* Evaluate a concept check of the form C<ARGS>. This is only used for the
+ evaluation of template-ids as id-expressions. */
tree
evaluate_concept_check (tree check, tsubst_flags_t complain)
{
- /* FIXME we ought to be able to pass complain into subst_info rather
- than repeat satisfaction, but currently that will complain about
- non-satisfaction as well as errors. */
if (check == error_mark_node)
return error_mark_node;
gcc_assert (concept_check_p (check));
- subst_info info (tf_none, NULL_TREE);
- tree result = satisfy_constraint_expression (check, NULL_TREE, info);
+ /* Check for satisfaction without diagnostics. */
+ subst_info quiet (tf_none, NULL_TREE);
+ tree result = satisfy_constraint_expression (check, NULL_TREE, quiet);
if (result == error_mark_node && (complain & tf_error))
- {
- location_t loc = cp_expr_loc_or_input_loc (check);
- error_at (loc, "concept satisfaction failed");
- info.complain = complain;
- satisfy_constraint_expression (check, NULL_TREE, info);
- }
-
+ {
+ /* Replay the error with re-normalized requirements. */
+ subst_info noisy (tf_warning_or_error, NULL_TREE);
+ satisfy_constraint_expression (check, NULL_TREE, noisy);
+ }
return result;
}
@@ -2961,6 +2985,17 @@ more_constrained (tree d1, tree d2)
return winner;
}
+/* Return whether D1 is at least as constrained as D2. */
+
+bool
+at_least_as_constrained (tree d1, tree d2)
+{
+ tree n1 = get_normalized_constraints_from_decl (d1);
+ tree n2 = get_normalized_constraints_from_decl (d2);
+
+ return subsumes (n1, n2);
+}
+
/*---------------------------------------------------------------------------
Constraint diagnostics
---------------------------------------------------------------------------*/
@@ -3275,6 +3310,8 @@ diagnose_atomic_constraint (tree t, tree args, subst_info info)
}
}
+GTY(()) tree current_failed_constraint;
+
diagnosing_failed_constraint::
diagnosing_failed_constraint (tree t, tree args, bool diag)
: diagnosing_error (diag)
@@ -3299,11 +3336,10 @@ diagnose_constraints (location_t loc, tree t, tree args)
inform (loc, "constraints not satisfied");
/* Replay satisfaction, but diagnose errors. */
- subst_info info (tf_warning_or_error, NULL_TREE);
if (!args)
- constraints_satisfied_p (t, info);
+ constraint_satisfaction_value (t, tf_warning_or_error);
else
- constraints_satisfied_p (t, args, info);
+ constraint_satisfaction_value (t, args, tf_warning_or_error);
}
#include "gt-cp-constraint.h"
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 60766978c71..7942afa7ece 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -1622,6 +1622,15 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
break;
case CALL_EXPR:
+ /* Evaluate function concept checks instead of treating them as
+ normal functions. */
+ if (concept_check_p (stmt))
+ {
+ *stmt_p = evaluate_concept_check (stmt, tf_warning_or_error);
+ * walk_subtrees = 0;
+ break;
+ }
+
if (!wtd->no_sanitize_p
&& sanitize_flags_p ((SANITIZE_NULL
| SANITIZE_ALIGNMENT | SANITIZE_VPTR)))
@@ -1679,6 +1688,13 @@ cp_genericize_r (tree *stmt_p, int *walk_subtrees, void *data)
TARGET_EXPR_NO_ELIDE (stmt) = 1;
break;
+ case TEMPLATE_ID_EXPR:
+ gcc_assert (concept_check_p (stmt));
+ /* Emit the value of the concept check. */
+ *stmt_p = evaluate_concept_check (stmt, tf_warning_or_error);
+ walk_subtrees = 0;
+ break;
+
default:
if (IS_TYPE_OR_DECL_P (stmt))
*walk_subtrees = 0;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a756e702c23..08ea2343200 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6329,6 +6329,7 @@ extern tree build_converted_constant_expr (tree, tree, tsubst_flags_t);
extern tree build_converted_constant_bool_expr (tree, tsubst_flags_t);
extern tree perform_direct_initialization_if_possible (tree, tree, bool,
tsubst_flags_t);
+extern vec<tree,va_gc> *resolve_args (vec<tree,va_gc>*, tsubst_flags_t);
extern tree in_charge_arg_for_name (tree);
extern tree build_cxx_call (tree, int, tree *,
tsubst_flags_t,
@@ -6829,6 +6830,7 @@ extern tree make_constrained_auto (tree, tree);
extern tree make_constrained_decltype_auto (tree, tree);
extern tree make_template_placeholder (tree);
extern bool template_placeholder_p (tree);
+extern bool ctad_template_p (tree);
extern tree do_auto_deduction (tree, tree, tree,
tsubst_flags_t
= tf_warning_or_error,
@@ -6947,8 +6949,9 @@ extern tree instantiate_non_dependent_expr_internal (tree, tsubst_flags_t);
extern tree instantiate_non_dependent_or_null (tree);
extern bool variable_template_specialization_p (tree);
extern bool alias_type_or_template_p (tree);
-extern bool alias_template_specialization_p (const_tree);
-extern bool dependent_alias_template_spec_p (const_tree);
+enum { nt_opaque = false, nt_transparent = true };
+extern tree alias_template_specialization_p (const_tree, bool);
+extern tree dependent_alias_template_spec_p (const_tree, bool);
extern bool template_parm_object_p (const_tree);
extern bool explicit_class_specialization_p (tree);
extern bool push_tinst_level (tree);
@@ -7491,9 +7494,11 @@ extern tree build_class_member_access_expr (cp_expr, tree, tree, bool,
extern tree finish_class_member_access_expr (cp_expr, tree, bool,
tsubst_flags_t);
extern tree build_x_indirect_ref (location_t, tree,
- ref_operator, tsubst_flags_t);
-extern tree cp_build_indirect_ref (tree, ref_operator,
- tsubst_flags_t);
+ ref_operator,
+ tsubst_flags_t);
+extern tree cp_build_indirect_ref (location_t, tree,
+ ref_operator,
+ tsubst_flags_t);
extern tree cp_build_fold_indirect_ref (tree);
extern tree build_array_ref (location_t, tree, tree);
extern tree cp_build_array_ref (location_t, tree, tree,
@@ -7778,7 +7783,8 @@ extern cp_expr finish_constraint_and_expr (location_t, cp_expr, cp_expr);
extern cp_expr finish_constraint_primary_expr (cp_expr);
extern tree finish_concept_definition (cp_expr, tree);
extern tree combine_constraint_expressions (tree, tree);
-extern tree get_constraints (tree);
+extern tree append_constraint (tree, tree);
+extern tree get_constraints (const_tree);
extern void set_constraints (tree, tree);
extern void remove_constraints (tree);
extern tree current_template_constraints (void);
@@ -7828,8 +7834,8 @@ extern bool processing_constraint_expression_p ();
extern tree unpack_concept_check (tree);
extern tree evaluate_concept_check (tree, tsubst_flags_t);
extern tree satisfy_constraint_expression (tree);
-extern bool constraints_satisfied_p (tree);
-extern bool constraints_satisfied_p (tree, tree);
+extern bool constraints_satisfied_p (tree);
+extern bool constraints_satisfied_p (tree, tree);
extern void clear_satisfaction_cache ();
extern bool* lookup_subsumption_result (tree, tree);
extern bool save_subsumption_result (tree, tree, bool);
@@ -7840,6 +7846,7 @@ extern bool subsumes_constraints (tree, tree);
extern bool strictly_subsumes (tree, tree, tree);
extern bool weakly_subsumes (tree, tree, tree);
extern int more_constrained (tree, tree);
+extern bool at_least_as_constrained (tree, tree);
extern bool constraints_equivalent_p (tree, tree);
extern bool atomic_constraints_identical_p (tree, tree);
extern hashval_t iterative_hash_constraint (tree, hashval_t);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index e67b32ea3b0..d916e39ee90 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1135,6 +1135,12 @@ convert_to_void (tree expr, impl_conv_void implicit, tsubst_flags_t complain)
error_at (loc, "pseudo-destructor is not called");
return error_mark_node;
}
+
+ /* Explicitly evaluate void-converted concept checks since their
+ satisfaction may produce ill-formed programs. */
+ if (concept_check_p (expr))
+ expr = evaluate_concept_check (expr, tf_warning_or_error);
+
if (VOID_TYPE_P (TREE_TYPE (expr)))
return expr;
switch (TREE_CODE (expr))
diff --git a/gcc/cp/cxx-pretty-print.c b/gcc/cp/cxx-pretty-print.c
index 8ece11d276e..909b2a4ef1d 100644
--- a/gcc/cp/cxx-pretty-print.c
+++ b/gcc/cp/cxx-pretty-print.c
@@ -172,11 +172,11 @@ pp_cxx_unqualified_id (cxx_pretty_printer *pp, tree t)
case TYPENAME_TYPE:
case UNBOUND_CLASS_TEMPLATE:
pp_cxx_unqualified_id (pp, TYPE_NAME (t));
- if (CLASS_TYPE_P (t) && CLASSTYPE_USE_TEMPLATE (t))
+ if (tree ti = TYPE_TEMPLATE_INFO_MAYBE_ALIAS (t))
{
pp_cxx_begin_template_argument_list (pp);
- pp_cxx_template_argument_list (pp, INNERMOST_TEMPLATE_ARGS
- (CLASSTYPE_TI_ARGS (t)));
+ tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (ti));
+ pp_cxx_template_argument_list (pp, args);
pp_cxx_end_template_argument_list (pp);
}
break;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 6fe20b2008d..70345eab2ed 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -14548,7 +14548,7 @@ check_elaborated_type_specifier (enum tag_types tag_code,
&& !DECL_SELF_REFERENCE_P (decl)
&& tag_code != typename_type)
{
- if (alias_template_specialization_p (type))
+ if (alias_template_specialization_p (type, nt_opaque))
error ("using alias template specialization %qT after %qs",
type, tag_name (tag_code));
else
@@ -16318,7 +16318,8 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
&& !implicit_default_ctor_p (decl1))
cp_ubsan_maybe_initialize_vtbl_ptrs (current_class_ptr);
- start_lambda_scope (decl1);
+ if (!DECL_OMP_DECLARE_REDUCTION_P (decl1))
+ start_lambda_scope (decl1);
return true;
}
@@ -16730,7 +16731,8 @@ finish_function (bool inline_p)
if (fndecl == NULL_TREE)
return error_mark_node;
- finish_lambda_scope ();
+ if (!DECL_OMP_DECLARE_REDUCTION_P (fndecl))
+ finish_lambda_scope ();
if (c_dialect_objc ())
objc_finish_function ();
@@ -16887,7 +16889,9 @@ finish_function (bool inline_p)
invoke_plugin_callbacks (PLUGIN_PRE_GENERICIZE, fndecl);
/* Perform delayed folding before NRV transformation. */
- if (!processing_template_decl && !DECL_IMMEDIATE_FUNCTION_P (fndecl))
+ if (!processing_template_decl
+ && !DECL_IMMEDIATE_FUNCTION_P (fndecl)
+ && !DECL_OMP_DECLARE_REDUCTION_P (fndecl))
cp_fold_function (fndecl);
/* Set up the named return value optimization, if we can. Candidate
@@ -17000,7 +17004,9 @@ finish_function (bool inline_p)
do_warn_unused_parameter (fndecl);
/* Genericize before inlining. */
- if (!processing_template_decl && !DECL_IMMEDIATE_FUNCTION_P (fndecl))
+ if (!processing_template_decl
+ && !DECL_IMMEDIATE_FUNCTION_P (fndecl)
+ && !DECL_OMP_DECLARE_REDUCTION_P (fndecl))
cp_genericize (fndecl);
/* Emit the resumer and destroyer functions now. */
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f164494afdc..46cc58265a6 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -5596,8 +5596,11 @@ mark_used (tree decl, tsubst_flags_t complain)
vec_safe_push (no_linkage_decls, decl);
}
- if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
- && !DECL_INITIAL (decl) && !DECL_ARTIFICIAL (decl))
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (decl)
+ && !DECL_INITIAL (decl)
+ && !DECL_ARTIFICIAL (decl)
+ && !DECL_PURE_VIRTUAL_P (decl))
/* Remember it, so we can check it was defined. */
note_vague_linkage_fn (decl);
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index c06776f565a..a15230a1f01 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -421,7 +421,7 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args,
static void
dump_alias_template_specialization (cxx_pretty_printer *pp, tree t, int flags)
{
- gcc_assert (alias_template_specialization_p (t));
+ gcc_assert (alias_template_specialization_p (t, nt_opaque));
tree decl = TYPE_NAME (t);
if (!(flags & TFF_UNQUALIFIED_NAME))
@@ -454,7 +454,7 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)
? STF_USER_VISIBLE : 0);
t = strip_typedefs (t, NULL, stf_flags);
}
- else if (alias_template_specialization_p (t))
+ else if (alias_template_specialization_p (t, nt_opaque))
{
dump_alias_template_specialization (pp, t, flags);
return;
@@ -711,7 +711,7 @@ dump_aggr_type (cxx_pretty_printer *pp, tree t, int flags)
typdef = (!DECL_ARTIFICIAL (name)
/* An alias specialization is not considered to be a
typedef. */
- && !alias_template_specialization_p (t));
+ && !alias_template_specialization_p (t, nt_opaque));
if ((typdef
&& ((flags & TFF_CHASE_TYPEDEF)
@@ -3358,6 +3358,9 @@ cp_print_error_function (diagnostic_context *context,
to be wrong, so just rely on print_instantiation_full_context. */
if (current_instantiation ())
return;
+ /* The above is true for constraint satisfaction also. */
+ if (current_failed_constraint)
+ return;
if (diagnostic_last_function_changed (context, diagnostic))
{
char *old_prefix = pp_take_prefix (context->printer);
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index 0ac04514e8e..88c5fa2c622 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -873,7 +873,16 @@ decl_mangling_context (tree decl)
else if (template_type_parameter_p (decl))
/* template type parms have no mangling context. */
return NULL_TREE;
- return CP_DECL_CONTEXT (decl);
+
+ tcontext = CP_DECL_CONTEXT (decl);
+
+ /* Ignore the artificial declare reduction functions. */
+ if (tcontext
+ && TREE_CODE (tcontext) == FUNCTION_DECL
+ && DECL_OMP_DECLARE_REDUCTION_P (tcontext))
+ return decl_mangling_context (tcontext);
+
+ return tcontext;
}
/* <name> ::= <unscoped-name>
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 13e79c4dcc2..3b68f964d2a 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -2442,7 +2442,7 @@ static tree cp_parser_concept_definition
static tree cp_parser_constraint_expression
(cp_parser *);
static tree cp_parser_requires_clause_opt
- (cp_parser *);
+ (cp_parser *, bool);
static tree cp_parser_requires_expression
(cp_parser *);
static tree cp_parser_requirement_parameter_list
@@ -10927,7 +10927,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
/* We may have a constrained generic lambda; parse the requires-clause
immediately after the template-parameter-list and combine with any
shorthand constraints present. */
- tree dreqs = cp_parser_requires_clause_opt (parser);
+ tree dreqs = cp_parser_requires_clause_opt (parser, true);
if (flag_concepts)
{
tree reqs = get_shorthand_constraints (current_template_parms);
@@ -11020,7 +11020,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
gnu_attrs = cp_parser_gnu_attributes_opt (parser);
/* Parse optional trailing requires clause. */
- trailing_requires_clause = cp_parser_requires_clause_opt (parser);
+ trailing_requires_clause = cp_parser_requires_clause_opt (parser, false);
/* The function parameters must be in scope all the way until after the
trailing-return-type in case of decltype. */
@@ -16367,11 +16367,11 @@ cp_parser_type_parameter (cp_parser* parser, bool *is_parameter_pack)
/* Look for the `>'. */
cp_parser_require (parser, CPP_GREATER, RT_GREATER);
- // If template requirements are present, parse them.
+ /* If template requirements are present, parse them. */
if (flag_concepts)
{
tree reqs = get_shorthand_constraints (current_template_parms);
- if (tree dreqs = cp_parser_requires_clause_opt (parser))
+ if (tree dreqs = cp_parser_requires_clause_opt (parser, false))
reqs = combine_constraint_expressions (reqs, dreqs);
TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = reqs;
}
@@ -18121,8 +18121,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
/*ambiguous_decls=*/NULL,
token->location);
if (tmpl && tmpl != error_mark_node
- && (DECL_CLASS_TEMPLATE_P (tmpl)
- || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))
+ && ctad_template_p (tmpl))
type = make_template_placeholder (tmpl);
else if (flag_concepts && tmpl && concept_definition_p (tmpl))
type = cp_parser_placeholder_type_specifier (parser, loc,
@@ -19940,14 +19939,6 @@ cp_parser_alias_declaration (cp_parser* parser)
if (decl == error_mark_node)
return decl;
- /* Attach constraints to the alias declaration. */
- if (flag_concepts && current_template_parms)
- {
- tree reqs = TEMPLATE_PARMS_CONSTRAINTS (current_template_parms);
- tree constr = build_constraints (reqs, NULL_TREE);
- set_constraints (decl, constr);
- }
-
cp_finish_decl (decl, NULL_TREE, 0, NULL_TREE, 0);
if (pushed_scope)
@@ -21979,7 +21970,7 @@ cp_parser_late_return_type_opt (cp_parser* parser, cp_declarator *declarator,
/* Function declarations may be followed by a trailing
requires-clause. */
- requires_clause = cp_parser_requires_clause_opt (parser);
+ requires_clause = cp_parser_requires_clause_opt (parser, false);
if (declare_simd_p)
declarator->attributes
@@ -26703,6 +26694,15 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
/* A GNU attribute that takes an identifier in parameter. */
attr_flag = id_attr;
+ if (as == NULL)
+ {
+ /* For unknown attributes, just skip balanced tokens instead of
+ trying to parse the arguments. */
+ for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n)
+ cp_lexer_consume_token (parser->lexer);
+ return attribute;
+ }
+
vec = cp_parser_parenthesized_expression_list
(parser, attr_flag, /*cast_p=*/false,
/*allow_expansion_p=*/true,
@@ -26711,7 +26711,7 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
arguments = error_mark_node;
else
{
- if (vec->is_empty())
+ if (vec->is_empty ())
/* e.g. [[attr()]]. */
error_at (token->location, "parentheses must be omitted if "
"%qE attribute argument list is empty",
@@ -27187,8 +27187,7 @@ cp_parser_concept_definition (cp_parser *parser)
static void
cp_parser_diagnose_ungrouped_constraint_plain (location_t loc)
{
- error_at (loc, "expression after %<requires%> must be enclosed "
- "in parentheses");
+ error_at (loc, "expression must be enclosed in parentheses");
}
static void
@@ -27197,56 +27196,48 @@ cp_parser_diagnose_ungrouped_constraint_rich (location_t loc)
gcc_rich_location richloc (loc);
richloc.add_fixit_insert_before ("(");
richloc.add_fixit_insert_after (")");
- error_at (&richloc, "expression after %<requires%> must be enclosed "
- "in parentheses");
+ error_at (&richloc, "expression must be enclosed in parentheses");
}
-/* Parse a primary expression within a constraint. */
-
-static cp_expr
-cp_parser_constraint_primary_expression (cp_parser *parser)
+/* Characterizes the likely kind of expression intended by a mis-written
+ primary constraint. */
+enum primary_constraint_error
{
- cp_parser_parse_tentatively (parser);
- cp_id_kind idk;
- location_t loc = input_location;
- cp_expr expr = cp_parser_primary_expression (parser,
- /*address_p=*/false,
- /*cast_p=*/false,
- /*template_arg_p=*/false,
- &idk);
- expr.maybe_add_location_wrapper ();
- if (expr != error_mark_node)
- expr = finish_constraint_primary_expr (expr);
- if (cp_parser_parse_definitely (parser))
- return expr;
-
- /* Retry the parse at a lower precedence. If that succeeds, diagnose the
- error, but return the expression as if it were valid. */
- cp_parser_parse_tentatively (parser);
- expr = cp_parser_simple_cast_expression (parser);
- if (cp_parser_parse_definitely (parser))
- {
- cp_parser_diagnose_ungrouped_constraint_rich (expr.get_location());
- return expr;
- }
-
- /* Otherwise, something has gone wrong, but we can't generate a more
- meaningful diagnostic or recover. */
- cp_parser_diagnose_ungrouped_constraint_plain (loc);
- return error_mark_node;
-}
+ pce_ok,
+ pce_maybe_operator,
+ pce_maybe_postfix,
+};
-/* Examine the token following EXPR. If it is an operator in a non-logical
- binary expression, diagnose that as an error. Returns ERROR_MARK_NODE. */
+/* Returns true if the token(s) following a primary-expression in a
+ constraint-logical-* expression would require parentheses. */
-static cp_expr
-cp_parser_check_non_logical_constraint (cp_parser *parser, cp_expr lhs)
+static primary_constraint_error
+cp_parser_constraint_requires_parens (cp_parser *parser, bool lambda_p)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
switch (token->type)
{
default:
- return lhs;
+ return pce_ok;
+
+ case CPP_EQ:
+ {
+ /* An equal sign may be part of the the definition of a function,
+ and not an assignment operator, when parsing the expression
+ for a trailing requires-clause. For example:
+
+ template<typename T>
+ struct S {
+ S() requires C<T> = default;
+ };
+
+ Don't try to reparse this a binary operator. */
+ if (cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_DELETE)
+ || cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_DEFAULT))
+ return pce_ok;
+
+ gcc_fallthrough ();
+ }
/* Arithmetic operators. */
case CPP_PLUS:
@@ -27261,15 +27252,13 @@ cp_parser_check_non_logical_constraint (cp_parser *parser, cp_expr lhs)
case CPP_RSHIFT:
case CPP_LSHIFT:
/* Relational operators. */
- /* FIXME: Handle '<=>'. */
case CPP_EQ_EQ:
case CPP_NOT_EQ:
case CPP_LESS:
case CPP_GREATER:
case CPP_LESS_EQ:
case CPP_GREATER_EQ:
- /* Conditional operator */
- case CPP_QUERY:
+ case CPP_SPACESHIP:
/* Pointer-to-member. */
case CPP_DOT_STAR:
case CPP_DEREF_STAR:
@@ -27284,52 +27273,138 @@ cp_parser_check_non_logical_constraint (cp_parser *parser, cp_expr lhs)
case CPP_XOR_EQ:
case CPP_RSHIFT_EQ:
case CPP_LSHIFT_EQ:
- break;
+ /* Conditional operator */
+ case CPP_QUERY:
+ /* Unenclosed binary or conditional operator. */
+ return pce_maybe_operator;
- case CPP_EQ: {
- /* An equal sign may be part of the the definition of a function,
- and not an assignment operator, when parsing the expression
- for a trailing requires-clause. For example:
+ case CPP_OPEN_PAREN:
+ {
+ /* A primary constraint that precedes the parameter-list of a
+ lambda expression is followed by an open paren.
- template<typename T>
- struct S {
- S() requires C<T> = default;
- }
+ []<typename T> requires C (T a, T b) { ... }
- This is not an error. */
- if (cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_DELETE)
- || cp_lexer_nth_token_is_keyword (parser->lexer, 2, RID_DEFAULT))
- return lhs;
+ Don't try to re-parse this as a postfix expression. */
+ if (lambda_p)
+ return pce_ok;
- break;
- }
+ gcc_fallthrough ();
+ }
+ case CPP_OPEN_SQUARE:
+ case CPP_PLUS_PLUS:
+ case CPP_MINUS_MINUS:
+ case CPP_DOT:
+ case CPP_DEREF:
+ /* Unenclosed postfix operator. */
+ return pce_maybe_postfix;
}
+}
+
+/* Returns true if the next token begins a unary expression, preceded by
+ an operator or keyword. */
+
+static bool
+cp_parser_unary_constraint_requires_parens (cp_parser *parser)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ switch (token->type)
+ {
+ case CPP_NOT:
+ case CPP_PLUS:
+ case CPP_MINUS:
+ case CPP_MULT:
+ case CPP_COMPL:
+ case CPP_PLUS_PLUS:
+ case CPP_MINUS_MINUS:
+ return true;
+
+ case CPP_KEYWORD:
+ {
+ switch (token->keyword)
+ {
+ case RID_STATCAST:
+ case RID_DYNCAST:
+ case RID_REINTCAST:
+ case RID_CONSTCAST:
+ case RID_TYPEID:
+ case RID_SIZEOF:
+ case RID_ALIGNOF:
+ case RID_NOEXCEPT:
+ case RID_NEW:
+ case RID_DELETE:
+ case RID_THROW:
+ return true;
+
+ default:
+ break;
+ }
+ }
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/* Parse a primary expression within a constraint. */
+
+static cp_expr
+cp_parser_constraint_primary_expression (cp_parser *parser, bool lambda_p)
+{
+ /* If this looks like a unary expression, parse it as such, but diagnose
+ it as ill-formed; it requires parens. */
+ if (cp_parser_unary_constraint_requires_parens (parser))
+ {
+ cp_expr e = cp_parser_assignment_expression (parser, NULL, false, false);
+ cp_parser_diagnose_ungrouped_constraint_rich (e.get_location());
+ return e;
+ }
- /* Try to parse the RHS as either the remainder of a conditional-expression
- or a logical-or-expression so we can form a good diagnostic. */
cp_parser_parse_tentatively (parser);
- cp_expr rhs;
- if (token->type == CPP_QUERY)
- rhs = cp_parser_question_colon_clause (parser, lhs);
- else
+ cp_id_kind idk;
+ location_t loc = input_location;
+ cp_expr expr = cp_parser_primary_expression (parser,
+ /*address_p=*/false,
+ /*cast_p=*/false,
+ /*template_arg_p=*/false,
+ &idk);
+ expr.maybe_add_location_wrapper ();
+
+ primary_constraint_error pce = pce_ok;
+ if (expr != error_mark_node)
{
- cp_lexer_consume_token (parser->lexer);
- rhs = cp_parser_binary_expression (parser, false, false, false,
- PREC_NOT_OPERATOR, NULL);
+ /* The primary-expression could be part of an unenclosed non-logical
+ compound expression. */
+ pce = cp_parser_constraint_requires_parens (parser, lambda_p);
+ if (pce != pce_ok)
+ cp_parser_simulate_error (parser);
+ else
+ expr = finish_constraint_primary_expr (expr);
}
+ if (cp_parser_parse_definitely (parser))
+ return expr;
+ if (expr == error_mark_node)
+ return error_mark_node;
- /* If we couldn't parse the RHS, then emit the best diagnostic we can. */
- if (!cp_parser_parse_definitely (parser))
+ /* Retry the parse at a lower precedence. If that succeeds, diagnose the
+ error, but return the expression as if it were valid. */
+ gcc_assert (pce != pce_ok);
+ cp_parser_parse_tentatively (parser);
+ if (pce == pce_maybe_operator)
+ expr = cp_parser_assignment_expression (parser, NULL, false, false);
+ else
+ expr = cp_parser_simple_cast_expression (parser);
+ if (cp_parser_parse_definitely (parser))
{
- cp_parser_diagnose_ungrouped_constraint_plain (token->location);
- return error_mark_node;
+ cp_parser_diagnose_ungrouped_constraint_rich (expr.get_location());
+ return expr;
}
- /* Otherwise, emit a fixit for the complete binary expression. */
- location_t loc = make_location (token->location,
- lhs.get_start(),
- rhs.get_finish());
- cp_parser_diagnose_ungrouped_constraint_rich (loc);
+ /* Otherwise, something has gone very wrong, and we can't generate a more
+ meaningful diagnostic or recover. */
+ cp_parser_diagnose_ungrouped_constraint_plain (loc);
return error_mark_node;
}
@@ -27340,16 +27415,16 @@ cp_parser_check_non_logical_constraint (cp_parser *parser, cp_expr lhs)
constraint-logical-and-expression '&&' primary-expression */
static cp_expr
-cp_parser_constraint_logical_and_expression (cp_parser *parser)
+cp_parser_constraint_logical_and_expression (cp_parser *parser, bool lambda_p)
{
- cp_expr lhs = cp_parser_constraint_primary_expression (parser);
+ cp_expr lhs = cp_parser_constraint_primary_expression (parser, lambda_p);
while (cp_lexer_next_token_is (parser->lexer, CPP_AND_AND))
{
cp_token *op = cp_lexer_consume_token (parser->lexer);
- tree rhs = cp_parser_constraint_primary_expression (parser);
+ tree rhs = cp_parser_constraint_primary_expression (parser, lambda_p);
lhs = finish_constraint_and_expr (op->location, lhs, rhs);
}
- return cp_parser_check_non_logical_constraint (parser, lhs);
+ return lhs;
}
/* Parse a constraint-logical-or-expression.
@@ -27359,27 +27434,27 @@ cp_parser_constraint_logical_and_expression (cp_parser *parser)
constraint-logical-or-expression '||' constraint-logical-and-expression */
static cp_expr
-cp_parser_constraint_logical_or_expression (cp_parser *parser)
+cp_parser_constraint_logical_or_expression (cp_parser *parser, bool lambda_p)
{
- cp_expr lhs = cp_parser_constraint_logical_and_expression (parser);
+ cp_expr lhs = cp_parser_constraint_logical_and_expression (parser, lambda_p);
while (cp_lexer_next_token_is (parser->lexer, CPP_OR_OR))
{
cp_token *op = cp_lexer_consume_token (parser->lexer);
- cp_expr rhs = cp_parser_constraint_logical_and_expression (parser);
+ cp_expr rhs = cp_parser_constraint_logical_and_expression (parser, lambda_p);
lhs = finish_constraint_or_expr (op->location, lhs, rhs);
}
- return cp_parser_check_non_logical_constraint (parser, lhs);
+ return lhs;
}
/* Parse the expression after a requires-clause. This has a different grammar
than that in the concepts TS. */
static tree
-cp_parser_requires_clause_expression (cp_parser *parser)
+cp_parser_requires_clause_expression (cp_parser *parser, bool lambda_p)
{
processing_constraint_expression_sentinel parsing_constraint;
++processing_template_decl;
- cp_expr expr = cp_parser_constraint_logical_or_expression (parser);
+ cp_expr expr = cp_parser_constraint_logical_or_expression (parser, lambda_p);
if (check_for_bare_parameter_packs (expr))
expr = error_mark_node;
--processing_template_decl;
@@ -27412,12 +27487,15 @@ cp_parser_constraint_expression (cp_parser *parser)
/* Optionally parse a requires clause:
requires-clause:
- `requires` constraint-logical-or-expression.
+ `requires` constraint-logical-or-expression.
[ConceptsTS]
- `requires constraint-expression. */
+ `requires constraint-expression.
+
+ LAMBDA_P is true when the requires-clause is parsed before the
+ parameter-list of a lambda-declarator. */
static tree
-cp_parser_requires_clause_opt (cp_parser *parser)
+cp_parser_requires_clause_opt (cp_parser *parser, bool lambda_p)
{
cp_token *tok = cp_lexer_peek_token (parser->lexer);
if (tok->keyword != RID_REQUIRES)
@@ -27437,7 +27515,7 @@ cp_parser_requires_clause_opt (cp_parser *parser)
cp_lexer_consume_token (parser->lexer);
if (!flag_concepts_ts)
- return cp_parser_requires_clause_expression (parser);
+ return cp_parser_requires_clause_expression (parser, lambda_p);
else
return cp_parser_constraint_expression (parser);
}
@@ -28992,7 +29070,7 @@ cp_parser_explicit_template_declaration (cp_parser* parser, bool member_p)
if (flag_concepts)
{
tree reqs = get_shorthand_constraints (current_template_parms);
- if (tree treqs = cp_parser_requires_clause_opt (parser))
+ if (tree treqs = cp_parser_requires_clause_opt (parser, false))
reqs = combine_constraint_expressions (reqs, treqs);
TEMPLATE_PARMS_CONSTRAINTS (current_template_parms) = reqs;
}
@@ -41243,6 +41321,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
combiner = cp_parser_expression (parser);
finish_expr_stmt (combiner);
block = finish_omp_structured_block (block);
+ if (processing_template_decl)
+ block = build_stmt (input_location, EXPR_STMT, block);
add_stmt (block);
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN))
@@ -41347,6 +41427,8 @@ cp_parser_omp_declare_reduction_exprs (tree fndecl, cp_parser *parser)
block = finish_omp_structured_block (block);
cp_walk_tree (&block, cp_remove_omp_priv_cleanup_stmt, omp_priv, NULL);
+ if (processing_template_decl)
+ block = build_stmt (input_location, EXPR_STMT, block);
add_stmt (block);
if (ctor)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 24be9310bc0..808e4d2cdcc 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -215,6 +215,7 @@ static tree listify_autos (tree, tree);
static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
static tree instantiate_alias_template (tree, tree, tsubst_flags_t);
static bool complex_alias_template_p (const_tree tmpl);
+static tree get_underlying_template (tree);
static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree);
static tree canonicalize_expr_argument (tree, tsubst_flags_t);
static tree make_argument_pack (tree);
@@ -1882,7 +1883,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)
switch (tclass)
{
case tcc_type:
- if (alias_template_specialization_p (arg))
+ if (tree ats = alias_template_specialization_p (arg, nt_transparent))
{
// We want an alias specialization that survived strip_typedefs
// to hash differently from its TYPE_CANONICAL, to avoid hash
@@ -1891,7 +1892,7 @@ iterative_hash_template_arg (tree arg, hashval_t val)
// left alone, or untouched specializations because
// coerce_template_parms returns the unconverted template
// arguments if it sees incomplete argument packs.
- tree ti = TYPE_ALIAS_TEMPLATE_INFO (arg);
+ tree ti = TYPE_ALIAS_TEMPLATE_INFO (ats);
return hash_tmpl_and_args (TI_TEMPLATE (ti), TI_ARGS (ti));
}
if (TYPE_CANONICAL (arg))
@@ -3575,7 +3576,7 @@ primary_template_specialization_p (const_tree t)
return (CLASSTYPE_TEMPLATE_INFO (t)
&& CLASSTYPE_USE_TEMPLATE (t)
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)));
- else if (alias_template_specialization_p (t))
+ else if (alias_template_specialization_p (t, nt_transparent))
return true;
return false;
}
@@ -5989,9 +5990,18 @@ push_template_decl_real (tree decl, bool is_friend)
}
if (TREE_CODE (decl) == TYPE_DECL
- && TYPE_DECL_ALIAS_P (decl)
- && complex_alias_template_p (tmpl))
- TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
+ && TYPE_DECL_ALIAS_P (decl))
+ {
+ if (tree constr
+ = TEMPLATE_PARMS_CONSTRAINTS (DECL_TEMPLATE_PARMS (tmpl)))
+ {
+ /* ??? Why don't we do this here for all templates? */
+ constr = build_constraints (constr, NULL_TREE);
+ set_constraints (decl, constr);
+ }
+ if (complex_alias_template_p (tmpl))
+ TEMPLATE_DECL_COMPLEX_ALIAS_P (tmpl) = true;
+ }
}
/* The DECL_TI_ARGS of DECL contains full set of arguments referring
@@ -6298,18 +6308,30 @@ alias_type_or_template_p (tree t)
|| DECL_ALIAS_TEMPLATE_P (t));
}
-/* Return TRUE iff T is a specialization of an alias template. */
+/* If T is a specialization of an alias template, return it; otherwise return
+ NULL_TREE. If TRANSPARENT_TYPEDEFS is true, look through other aliases. */
-bool
-alias_template_specialization_p (const_tree t)
+tree
+alias_template_specialization_p (const_tree t,
+ bool transparent_typedefs)
{
+ if (!TYPE_P (t))
+ return NULL_TREE;
+
/* It's an alias template specialization if it's an alias and its
TYPE_NAME is a specialization of a primary template. */
- if (TYPE_ALIAS_P (t))
- if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
- return PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo));
+ if (typedef_variant_p (t))
+ {
+ if (tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t))
+ if (PRIMARY_TEMPLATE_P (TI_TEMPLATE (tinfo)))
+ return CONST_CAST_TREE (t);
+ if (transparent_typedefs)
+ return alias_template_specialization_p (DECL_ORIGINAL_TYPE
+ (TYPE_NAME (t)),
+ transparent_typedefs);
+ }
- return false;
+ return NULL_TREE;
}
/* An alias template is complex from a SFINAE perspective if a template-id
@@ -6338,6 +6360,14 @@ uses_all_template_parms_r (tree t, void *data_)
static bool
complex_alias_template_p (const_tree tmpl)
{
+ /* A renaming alias isn't complex. */
+ if (get_underlying_template (CONST_CAST_TREE (tmpl)) != tmpl)
+ return false;
+
+ /* Any other constrained alias is complex. */
+ if (get_constraints (tmpl))
+ return true;
+
struct uses_all_template_parms_data data;
tree pat = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
tree parms = DECL_TEMPLATE_PARMS (tmpl);
@@ -6354,30 +6384,36 @@ complex_alias_template_p (const_tree tmpl)
return false;
}
-/* Return TRUE iff T is a specialization of a complex alias template with
- dependent template-arguments. */
+/* If T is a specialization of a complex alias template with dependent
+ template-arguments, return it; otherwise return NULL_TREE. If T is a
+ typedef to such a specialization, return the specialization. */
-bool
-dependent_alias_template_spec_p (const_tree t)
+tree
+dependent_alias_template_spec_p (const_tree t, bool transparent_typedefs)
{
- if (!alias_template_specialization_p (t))
- return false;
+ if (!TYPE_P (t) || !typedef_variant_p (t))
+ return NULL_TREE;
tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t);
- if (!TEMPLATE_DECL_COMPLEX_ALIAS_P (TI_TEMPLATE (tinfo)))
- return false;
+ if (tinfo
+ && TEMPLATE_DECL_COMPLEX_ALIAS_P (TI_TEMPLATE (tinfo))
+ && (any_dependent_template_arguments_p
+ (INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo)))))
+ return CONST_CAST_TREE (t);
- tree args = INNERMOST_TEMPLATE_ARGS (TI_ARGS (tinfo));
- if (!any_dependent_template_arguments_p (args))
- return false;
+ if (transparent_typedefs)
+ {
+ tree utype = DECL_ORIGINAL_TYPE (TYPE_NAME (t));
+ return dependent_alias_template_spec_p (utype, transparent_typedefs);
+ }
- return true;
+ return NULL_TREE;
}
/* Return the number of innermost template parameters in TMPL. */
static int
-num_innermost_template_parms (tree tmpl)
+num_innermost_template_parms (const_tree tmpl)
{
tree parms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
return TREE_VEC_LENGTH (parms);
@@ -6412,6 +6448,11 @@ get_underlying_template (tree tmpl)
if (!comp_template_args (TI_ARGS (tinfo), alias_args))
break;
+ /* If TMPL adds or changes any constraints, it isn't equivalent. I think
+ it's appropriate to treat a less-constrained alias as equivalent. */
+ if (!at_least_as_constrained (underlying, tmpl))
+ break;
+
/* Alias is equivalent. Strip it and repeat. */
tmpl = underlying;
}
@@ -9661,7 +9702,9 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
Note that the check is deferred until after the hash
lookup. This prevents redundant checks on previously
instantiated specializations. */
- if (flag_concepts && !constraints_satisfied_p (gen_tmpl, arglist))
+ if (flag_concepts
+ && !DECL_ALIAS_TEMPLATE_P (gen_tmpl)
+ && !constraints_satisfied_p (gen_tmpl, arglist))
{
if (complain & tf_error)
{
@@ -10384,9 +10427,9 @@ any_template_parm_r (tree t, void *data)
case UNION_TYPE:
case ENUMERAL_TYPE:
/* Search for template parameters in type aliases. */
- if (alias_template_specialization_p (t))
+ if (tree ats = alias_template_specialization_p (t, nt_opaque))
{
- tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (t);
+ tree tinfo = TYPE_ALIAS_TEMPLATE_INFO (ats);
WALK_SUBTREE (TI_ARGS (tinfo));
}
break;
@@ -14896,7 +14939,7 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
{
tree decl = TYPE_NAME (t);
- if (alias_template_specialization_p (t))
+ if (alias_template_specialization_p (t, nt_opaque))
{
/* DECL represents an alias template and we want to
instantiate it. */
@@ -18881,17 +18924,16 @@ tsubst_copy_and_build (tree t,
if (function_concept_p (TREE_OPERAND (id, 0)))
RETURN (id);
- /* Evaluate the concept, if needed. */
- tree args = TREE_OPERAND (id, 1);
- if (!uses_template_parms (args)
- && !processing_constraint_expression_p ())
- RETURN (evaluate_concept_check (check, complain));
-
RETURN (check);
}
if (variable_template_p (templ))
- RETURN (lookup_and_finish_template_variable (templ, targs, complain));
+ {
+ tree r = lookup_and_finish_template_variable (templ, targs,
+ complain);
+ r = maybe_wrap_with_location (r, EXPR_LOCATION (t));
+ RETURN (r);
+ }
if (TREE_CODE (templ) == COMPONENT_REF)
{
@@ -19666,11 +19708,6 @@ tsubst_copy_and_build (tree t,
/* Ensure the result is wrapped as a call expression. */
ret = build_concept_check (tmpl, args, tf_warning_or_error);
-
- /* Possibly evaluate the check if it is non-dependent. */
- if (!uses_template_parms (args)
- && !processing_constraint_expression_p ())
- ret = evaluate_concept_check (ret, complain);
}
else
ret = finish_call_expr (function, &call_args,
@@ -20508,8 +20545,6 @@ instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain)
{
if (tmpl == error_mark_node || args == error_mark_node)
return error_mark_node;
- if (!push_tinst_level (tmpl, args))
- return error_mark_node;
args =
coerce_innermost_template_parms (DECL_TEMPLATE_PARMS (tmpl),
@@ -20517,6 +20552,22 @@ instantiate_alias_template (tree tmpl, tree args, tsubst_flags_t complain)
/*require_all_args=*/true,
/*use_default_args=*/true);
+ /* FIXME check for satisfaction in check_instantiated_args. */
+ if (flag_concepts
+ && !any_dependent_template_arguments_p (args)
+ && !constraints_satisfied_p (tmpl, args))
+ {
+ if (complain & tf_error)
+ {
+ auto_diagnostic_group d;
+ error ("template constraint failure for %qD", tmpl);
+ diagnose_constraints (input_location, tmpl, args);
+ }
+ return error_mark_node;
+ }
+
+ if (!push_tinst_level (tmpl, args))
+ return error_mark_node;
tree r = instantiate_template (tmpl, args, complain);
pop_tinst_level ();
@@ -25842,7 +25893,7 @@ dependent_type_p_r (tree type)
/* An alias template specialization can be dependent even if the
resulting type is not. */
- if (dependent_alias_template_spec_p (type))
+ if (dependent_alias_template_spec_p (type, nt_transparent))
return true;
/* -- a cv-qualified type where the cv-unqualified type is
@@ -27754,6 +27805,29 @@ rewrite_template_parm (tree olddecl, unsigned index, unsigned level,
return newdecl;
}
+/* As rewrite_template_parm, but for the whole TREE_LIST representing a
+ template parameter. */
+
+static tree
+rewrite_tparm_list (tree oldelt, unsigned index, unsigned level,
+ tree targs, unsigned targs_index, tsubst_flags_t complain)
+{
+ tree olddecl = TREE_VALUE (oldelt);
+ tree newdecl = rewrite_template_parm (olddecl, index, level,
+ targs, complain);
+ if (newdecl == error_mark_node)
+ return error_mark_node;
+ tree newdef = tsubst_template_arg (TREE_PURPOSE (oldelt),
+ targs, complain, NULL_TREE);
+ tree list = build_tree_list (newdef, newdecl);
+ TEMPLATE_PARM_CONSTRAINTS (list)
+ = tsubst_constraint_info (TEMPLATE_PARM_CONSTRAINTS (oldelt),
+ targs, complain, NULL_TREE);
+ int depth = TMPL_ARGS_DEPTH (targs);
+ TMPL_ARG (targs, depth, targs_index) = template_parm_to_arg (list);
+ return list;
+}
+
/* Returns a C++17 class deduction guide template based on the constructor
CTOR. As a special case, CTOR can be a RECORD_TYPE for an implicit default
guide, REFERENCE_TYPE for an implicit copy/move guide, or TREE_LIST for an
@@ -27867,19 +27941,12 @@ build_deduction_guide (tree type, tree ctor, tree outer_args, tsubst_flags_t com
unsigned index = i + clen;
unsigned level = 1;
tree oldelt = TREE_VEC_ELT (ftparms, i);
- tree olddecl = TREE_VALUE (oldelt);
- tree newdecl = rewrite_template_parm (olddecl, index, level,
- tsubst_args, complain);
- if (newdecl == error_mark_node)
+ tree newelt
+ = rewrite_tparm_list (oldelt, index, level,
+ tsubst_args, i, complain);
+ if (newelt == error_mark_node)
ok = false;
- tree newdef = tsubst_template_arg (TREE_PURPOSE (oldelt),
- tsubst_args, complain, ctor);
- tree list = build_tree_list (newdef, newdecl);
- TEMPLATE_PARM_CONSTRAINTS (list)
- = tsubst_constraint_info (TEMPLATE_PARM_CONSTRAINTS (oldelt),
- tsubst_args, complain, ctor);
- TREE_VEC_ELT (new_vec, index) = list;
- TMPL_ARG (tsubst_args, depth, i) = template_parm_to_arg (list);
+ TREE_VEC_ELT (new_vec, index) = newelt;
}
/* Now we have a final set of template parms to substitute into the
@@ -27954,20 +28021,48 @@ collect_ctor_idx_types (tree ctor, tree list)
return list;
}
+/* Return whether ETYPE is, or is derived from, a specialization of TMPL. */
+
+static bool
+is_spec_or_derived (tree etype, tree tmpl)
+{
+ if (!etype || !CLASS_TYPE_P (etype))
+ return false;
+
+ tree type = TREE_TYPE (tmpl);
+ tree tparms = (INNERMOST_TEMPLATE_PARMS
+ (DECL_TEMPLATE_PARMS (tmpl)));
+ tree targs = make_tree_vec (TREE_VEC_LENGTH (tparms));
+ int err = unify (tparms, targs, type, etype,
+ UNIFY_ALLOW_DERIVED, /*explain*/false);
+ ggc_free (targs);
+ return !err;
+}
+
/* Return a C++20 aggregate deduction candidate for TYPE initialized from
INIT. */
static tree
-maybe_aggr_guide (tree type, tree init)
+maybe_aggr_guide (tree tmpl, tree init, vec<tree,va_gc> *args)
{
if (cxx_dialect < cxx2a)
return NULL_TREE;
if (init == NULL_TREE)
return NULL_TREE;
+
+ tree type = TREE_TYPE (tmpl);
if (!CP_AGGREGATE_TYPE_P (type))
return NULL_TREE;
+ /* No aggregate candidate for copy-initialization. */
+ if (args->length() == 1)
+ {
+ tree val = (*args)[0];
+ if (is_spec_or_derived (tmpl, TREE_TYPE (val)))
+ return NULL_TREE;
+ }
+
/* If we encounter a problem, we just won't add the candidate. */
tsubst_flags_t complain = tf_none;
@@ -28009,22 +28104,292 @@ maybe_aggr_guide (tree type, tree init)
return NULL_TREE;
}
-/* Return whether ETYPE is, or is derived from, a specialization of TMPL. */
+/* UGUIDES are the deduction guides for the underlying template of alias
+ template TMPL; adjust them to be deduction guides for TMPL. */
-static bool
-is_spec_or_derived (tree etype, tree tmpl)
-{
- if (!etype || !CLASS_TYPE_P (etype))
- return false;
+static tree
+alias_ctad_tweaks (tree tmpl, tree uguides)
+{
+ /* [over.match.class.deduct]: When resolving a placeholder for a deduced
+ class type (9.2.8.2) where the template-name names an alias template A,
+ the defining-type-id of A must be of the form
+
+ typename(opt) nested-name-specifier(opt) template(opt) simple-template-id
+
+ as specified in 9.2.8.2. The guides of A are the set of functions or
+ function templates formed as follows. For each function or function
+ template f in the guides of the template named by the simple-template-id
+ of the defining-type-id, the template arguments of the return type of f
+ are deduced from the defining-type-id of A according to the process in
+ 13.10.2.5 with the exception that deduction does not fail if not all
+ template arguments are deduced. Let g denote the result of substituting
+ these deductions into f. If substitution succeeds, form a function or
+ function template f' with the following properties and add it to the set
+ of guides of A:
+
+ * The function type of f' is the function type of g.
+
+ * If f is a function template, f' is a function template whose template
+ parameter list consists of all the template parameters of A (including
+ their default template arguments) that appear in the above deductions or
+ (recursively) in their default template arguments, followed by the
+ template parameters of f that were not deduced (including their default
+ template arguments), otherwise f' is not a function template.
+
+ * The associated constraints (13.5.2) are the conjunction of the
+ associated constraints of g and a constraint that is satisfied if and only
+ if the arguments of A are deducible (see below) from the return type.
+
+ * If f is a copy deduction candidate (12.4.1.8), then f' is considered to
+ be so as well.
+
+ * If f was generated from a deduction-guide (12.4.1.8), then f' is
+ considered to be so as well.
+
+ * The explicit-specifier of f' is the explicit-specifier of g (if
+ any). */
+
+ /* This implementation differs from the above in two significant ways:
+
+ 1) We include all template parameters of A, not just some.
+ 2) The added constraint is same_type instead of deducible.
+
+ I believe that while it's probably possible to construct a testcase that
+ behaves differently with this simplification, it should have the same
+ effect for real uses. Including all template parameters means that we
+ deduce all parameters of A when resolving the call, so when we're in the
+ constraint we don't need to deduce them again, we can just check whether
+ the deduction produced the desired result. */
+
+ tsubst_flags_t complain = tf_warning_or_error;
+ tree atype = TREE_TYPE (tmpl);
+ tree aguides = NULL_TREE;
+ tree atparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (tmpl));
+ unsigned natparms = TREE_VEC_LENGTH (atparms);
+ tree utype = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+ for (ovl_iterator iter (uguides); iter; ++iter)
+ {
+ tree f = *iter;
+ tree in_decl = f;
+ location_t loc = DECL_SOURCE_LOCATION (f);
+ tree ret = TREE_TYPE (TREE_TYPE (f));
+ tree fprime = f;
+ if (TREE_CODE (f) == TEMPLATE_DECL)
+ {
+ processing_template_decl_sentinel ptds (/*reset*/false);
+ ++processing_template_decl;
+
+ /* Deduce template arguments for f from the type-id of A. */
+ tree ftparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (f));
+ unsigned len = TREE_VEC_LENGTH (ftparms);
+ tree targs = make_tree_vec (len);
+ int err = unify (ftparms, targs, ret, utype, UNIFY_ALLOW_NONE, false);
+ gcc_assert (!err);
+
+ /* The number of parms for f' is the number of parms for A plus
+ non-deduced parms of f. */
+ unsigned ndlen = 0;
+ unsigned j;
+ for (unsigned i = 0; i < len; ++i)
+ if (TREE_VEC_ELT (targs, i) == NULL_TREE)
+ ++ndlen;
+ tree gtparms = make_tree_vec (natparms + ndlen);
+
+ /* First copy over the parms of A. */
+ for (j = 0; j < natparms; ++j)
+ TREE_VEC_ELT (gtparms, j) = TREE_VEC_ELT (atparms, j);
+ /* Now rewrite the non-deduced parms of f. */
+ for (unsigned i = 0; ndlen && i < len; ++i)
+ if (TREE_VEC_ELT (targs, i) == NULL_TREE)
+ {
+ --ndlen;
+ unsigned index = j++;
+ unsigned level = 1;
+ tree oldlist = TREE_VEC_ELT (ftparms, i);
+ tree list = rewrite_tparm_list (oldlist, index, level,
+ targs, i, complain);
+ TREE_VEC_ELT (gtparms, index) = list;
+ }
+ gtparms = build_tree_list (size_one_node, gtparms);
+
+ /* Substitute the deduced arguments plus the rewritten template
+ parameters into f to get g. This covers the type, copyness,
+ guideness, and explicit-specifier. */
+ tree g = tsubst_decl (DECL_TEMPLATE_RESULT (f), targs, complain);
+ if (g == error_mark_node)
+ return error_mark_node;
+ DECL_USE_TEMPLATE (g) = 0;
+ fprime = build_template_decl (g, gtparms, false);
+ DECL_TEMPLATE_RESULT (fprime) = g;
+ TREE_TYPE (fprime) = TREE_TYPE (g);
+ tree gtargs = template_parms_to_args (gtparms);
+ DECL_TEMPLATE_INFO (g) = build_template_info (fprime, gtargs);
+ DECL_PRIMARY_TEMPLATE (fprime) = fprime;
+
+ /* Substitute the associated constraints. */
+ tree ci = get_constraints (f);
+ if (ci)
+ ci = tsubst_constraint_info (ci, targs, complain, in_decl);
+ if (ci == error_mark_node)
+ return error_mark_node;
+
+ /* Add a constraint that the return type matches the instantiation of
+ A with the same template arguments. */
+ ret = TREE_TYPE (TREE_TYPE (fprime));
+ if (!same_type_p (atype, ret)
+ /* FIXME this should mean they don't compare as equivalent. */
+ || dependent_alias_template_spec_p (atype, nt_opaque))
+ {
+ tree same = finish_trait_expr (loc, CPTK_IS_SAME_AS, atype, ret);
+ ci = append_constraint (ci, same);
+ }
+
+ if (ci)
+ set_constraints (fprime, ci);
+ }
+ else
+ {
+ /* For a non-template deduction guide, if the arguments of A aren't
+ deducible from the return type, don't add the candidate. */
+ tree targs = make_tree_vec (natparms);
+ int err = unify (atparms, targs, utype, ret, UNIFY_ALLOW_NONE, false);
+ for (unsigned i = 0; !err && i < natparms; ++i)
+ if (TREE_VEC_ELT (targs, i) == NULL_TREE)
+ err = true;
+ if (err)
+ continue;
+ }
+
+ aguides = lookup_add (fprime, aguides);
+ }
+
+ return aguides;
+}
+
+/* Return artificial deduction guides built from the constructors of class
+ template TMPL. */
+static tree
+ctor_deduction_guides_for (tree tmpl, tsubst_flags_t complain)
+{
tree type = TREE_TYPE (tmpl);
- tree tparms = (INNERMOST_TEMPLATE_PARMS
- (DECL_TEMPLATE_PARMS (tmpl)));
- tree targs = make_tree_vec (TREE_VEC_LENGTH (tparms));
- int err = unify (tparms, targs, type, etype,
- UNIFY_ALLOW_DERIVED, /*explain*/false);
- ggc_free (targs);
- return !err;
+ tree outer_args = NULL_TREE;
+ if (DECL_CLASS_SCOPE_P (tmpl)
+ && CLASSTYPE_TEMPLATE_INSTANTIATION (DECL_CONTEXT (tmpl)))
+ {
+ outer_args = CLASSTYPE_TI_ARGS (DECL_CONTEXT (tmpl));
+ type = TREE_TYPE (most_general_template (tmpl));
+ }
+
+ tree cands = NULL_TREE;
+
+ for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (type)); iter; ++iter)
+ {
+ /* Skip inherited constructors. */
+ if (iter.using_p ())
+ continue;
+
+ tree guide = build_deduction_guide (type, *iter, outer_args, complain);
+ cands = lookup_add (guide, cands);
+ }
+
+ /* Add implicit default constructor deduction guide. */
+ if (!TYPE_HAS_USER_CONSTRUCTOR (type))
+ {
+ tree guide = build_deduction_guide (type, type, outer_args,
+ complain);
+ cands = lookup_add (guide, cands);
+ }
+
+ /* Add copy guide. */
+ {
+ tree gtype = build_reference_type (type);
+ tree guide = build_deduction_guide (type, gtype, outer_args,
+ complain);
+ cands = lookup_add (guide, cands);
+ }
+
+ return cands;
+}
+
+static GTY((deletable)) hash_map<tree, tree_pair_p> *dguide_cache;
+
+/* Return the non-aggregate deduction guides for deducible template TMPL. The
+ aggregate candidate is added separately because it depends on the
+ initializer. */
+
+static tree
+deduction_guides_for (tree tmpl, tsubst_flags_t complain)
+{
+ tree guides = NULL_TREE;
+ if (DECL_ALIAS_TEMPLATE_P (tmpl))
+ {
+ tree under = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+ tree tinfo = get_template_info (under);
+ guides = deduction_guides_for (TI_TEMPLATE (tinfo), complain);
+ }
+ else
+ {
+ guides = lookup_qualified_name (CP_DECL_CONTEXT (tmpl),
+ dguide_name (tmpl),
+ /*type*/false, /*complain*/false,
+ /*hidden*/false);
+ if (guides == error_mark_node)
+ guides = NULL_TREE;
+ }
+
+ /* Cache the deduction guides for a template. We also remember the result of
+ lookup, and rebuild everything if it changes; should be very rare. */
+ tree_pair_p cache = NULL;
+ if (tree_pair_p &r
+ = hash_map_safe_get_or_insert<hm_ggc> (dguide_cache, tmpl))
+ {
+ cache = r;
+ if (cache->purpose == guides)
+ return cache->value;
+ }
+ else
+ {
+ r = cache = ggc_cleared_alloc<tree_pair_s> ();
+ cache->purpose = guides;
+ }
+
+ tree cands = NULL_TREE;
+ if (DECL_ALIAS_TEMPLATE_P (tmpl))
+ cands = alias_ctad_tweaks (tmpl, guides);
+ else
+ {
+ cands = ctor_deduction_guides_for (tmpl, complain);
+ for (ovl_iterator it (guides); it; ++it)
+ cands = lookup_add (*it, cands);
+ }
+
+ cache->value = cands;
+ return cands;
+}
+
+/* Return whether TMPL is a (class template argument-) deducible template. */
+
+bool
+ctad_template_p (tree tmpl)
+{
+ /* A deducible template is either a class template or is an alias template
+ whose defining-type-id is of the form
+
+ typename(opt) nested-name-specifier(opt) template(opt) simple-template-id
+
+ where the nested-name-specifier (if any) is non-dependent and the
+ template-name of the simple-template-id names a deducible template. */
+
+ if (DECL_CLASS_TEMPLATE_P (tmpl)
+ || DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
+ return true;
+ if (!DECL_ALIAS_TEMPLATE_P (tmpl))
+ return false;
+ tree orig = DECL_ORIGINAL_TYPE (DECL_TEMPLATE_RESULT (tmpl));
+ if (tree tinfo = get_template_info (orig))
+ return ctad_template_p (TI_TEMPLATE (tinfo));
+ return false;
}
/* Deduce template arguments for the class template placeholder PTYPE for
@@ -28032,18 +28397,29 @@ is_spec_or_derived (tree etype, tree tmpl)
type. */
static tree
-do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
- tsubst_flags_t complain)
+do_class_deduction (tree ptype, tree tmpl, tree init,
+ int flags, tsubst_flags_t complain)
{
- if (!DECL_CLASS_TEMPLATE_P (tmpl))
+ /* We should have handled this in the caller. */
+ if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
+ return ptype;
+
+ /* Look through alias templates that just rename another template. */
+ tmpl = get_underlying_template (tmpl);
+ if (!ctad_template_p (tmpl))
{
- /* We should have handled this in the caller. */
- if (DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl))
- return ptype;
if (complain & tf_error)
- error ("non-class template %qT used without template arguments", tmpl);
+ error ("non-deducible template %qT used without template arguments", tmpl);
return error_mark_node;
}
+ else if (cxx_dialect < cxx2a && DECL_ALIAS_TEMPLATE_P (tmpl))
+ {
+ /* This doesn't affect conforming C++17 code, so just pedwarn. */
+ if (complain & tf_warning_or_error)
+ pedwarn (input_location, 0, "alias template deduction only available "
+ "with %<-std=c++2a%> or %<-std=gnu++2a%>");
+ }
+
if (init && TREE_TYPE (init) == ptype)
/* Using the template parm as its own argument. */
return ptype;
@@ -28051,7 +28427,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
tree type = TREE_TYPE (tmpl);
bool try_list_ctor = false;
- bool copy_init = false;
releasing_vec rv_args = NULL;
vec<tree,va_gc> *&args = *&rv_args;
@@ -28059,7 +28434,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
args = make_tree_vector ();
else if (BRACE_ENCLOSED_INITIALIZER_P (init))
{
- if (CONSTRUCTOR_NELTS (init) == 1)
+ try_list_ctor = TYPE_HAS_LIST_CTOR (type);
+ if (try_list_ctor && CONSTRUCTOR_NELTS (init) == 1)
{
/* As an exception, the first phase in 16.3.1.7 (considering the
initializer list as a single argument) is omitted if the
@@ -28067,34 +28443,30 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
where U is a specialization of C or a class derived from a
specialization of C. */
tree elt = CONSTRUCTOR_ELT (init, 0)->value;
- copy_init = is_spec_or_derived (TREE_TYPE (elt), tmpl);
+ if (is_spec_or_derived (TREE_TYPE (elt), tmpl))
+ try_list_ctor = false;
}
- try_list_ctor = !copy_init && TYPE_HAS_LIST_CTOR (type);
if (try_list_ctor || is_std_init_list (type))
args = make_tree_vector_single (init);
else
args = make_tree_vector_from_ctor (init);
}
+ else if (TREE_CODE (init) == TREE_LIST)
+ args = make_tree_vector_from_list (init);
else
- {
- if (TREE_CODE (init) == TREE_LIST)
- args = make_tree_vector_from_list (init);
- else
- args = make_tree_vector_single (init);
+ args = make_tree_vector_single (init);
- if (args->length() == 1)
- copy_init = is_spec_or_derived (TREE_TYPE ((*args)[0]), tmpl);
- }
+ /* Do this now to avoid problems with erroneous args later on. */
+ args = resolve_args (args, complain);
+ if (args == NULL)
+ return error_mark_node;
- tree dname = dguide_name (tmpl);
- tree cands = lookup_qualified_name (CP_DECL_CONTEXT (tmpl), dname,
- /*type*/false, /*complain*/false,
- /*hidden*/false);
- bool elided = false;
+ tree cands = deduction_guides_for (tmpl, complain);
if (cands == error_mark_node)
- cands = NULL_TREE;
+ return error_mark_node;
/* Prune explicit deduction guides in copy-initialization context. */
+ bool elided = false;
if (flags & LOOKUP_ONLYCONVERTING)
{
for (lkp_iterator iter (cands); !elided && iter; ++iter)
@@ -28113,37 +28485,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
}
}
- tree outer_args = NULL_TREE;
- if (DECL_CLASS_SCOPE_P (tmpl)
- && CLASSTYPE_TEMPLATE_INSTANTIATION (DECL_CONTEXT (tmpl)))
- {
- outer_args = CLASSTYPE_TI_ARGS (DECL_CONTEXT (tmpl));
- type = TREE_TYPE (most_general_template (tmpl));
- }
-
- bool saw_ctor = false;
- // FIXME cache artificial deduction guides
- for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (type)); iter; ++iter)
- {
- /* Skip inherited constructors. */
- if (iter.using_p ())
- continue;
-
- tree guide = build_deduction_guide (type, *iter, outer_args, complain);
- if (guide == error_mark_node)
- return error_mark_node;
- if ((flags & LOOKUP_ONLYCONVERTING)
- && DECL_NONCONVERTING_P (STRIP_TEMPLATE (guide)))
- elided = true;
- else
- cands = lookup_add (guide, cands);
-
- saw_ctor = true;
- }
-
- if (!copy_init)
- if (tree guide = maybe_aggr_guide (type, init))
- cands = lookup_add (guide, cands);
+ if (tree guide = maybe_aggr_guide (tmpl, init, args))
+ cands = lookup_add (guide, cands);
tree call = error_mark_node;
@@ -28172,28 +28515,6 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
}
}
- /* Maybe generate an implicit deduction guide. */
- if (call == error_mark_node && args->length () < 2)
- {
- tree gtype = NULL_TREE;
-
- if (args->length () == 1)
- /* Generate a copy guide. */
- gtype = build_reference_type (type);
- else if (!saw_ctor)
- /* Generate a default guide. */
- gtype = type;
-
- if (gtype)
- {
- tree guide = build_deduction_guide (type, gtype, outer_args,
- complain);
- if (guide == error_mark_node)
- return error_mark_node;
- cands = lookup_add (guide, cands);
- }
- }
-
if (elided && !cands)
{
error ("cannot deduce template arguments for copy-initialization"
@@ -28215,7 +28536,8 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
--cp_unevaluated_operand;
}
- if (call == error_mark_node && (complain & tf_warning_or_error))
+ if (call == error_mark_node
+ && (complain & tf_warning_or_error))
{
error ("class template argument deduction failed:");
@@ -28752,8 +29074,6 @@ convert_generic_types_to_packs (tree parm, int start_idx, int end_idx)
return tsubst (parm, replacement, tf_none, NULL_TREE);
}
-GTY(()) tree current_failed_constraint;
-
/* __integer_pack(N) in a pack expansion expands to a sequence of numbers from
0..N-1. */
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 2adc9ef792b..17de39eea54 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2605,10 +2605,6 @@ finish_call_expr (tree fn, vec<tree, va_gc> **args, bool disallow_virtual,
/* Ensure the result is wrapped as a call expression. */
result = build_concept_check (tmpl, args, tf_warning_or_error);
-
- /* Evaluate the check if it is non-dependent. */
- if (!uses_template_parms (args))
- result = evaluate_concept_check (result, complain);
}
else if (is_overloaded_fn (fn))
{
@@ -3890,13 +3886,8 @@ finish_id_expression_1 (tree id_expression,
}
else if (concept_check_p (decl))
{
- /* If this is a standard or variable concept check, potentially
- evaluate it. Function concepts need to be called as functions,
- so don't try evaluating them here. */
- tree tmpl = TREE_OPERAND (decl, 0);
- tree args = TREE_OPERAND (decl, 1);
- if (!function_concept_p (tmpl) && !uses_template_parms (args))
- decl = evaluate_concept_check (decl, tf_warning_or_error);
+ /* Nothing more to do. All of the analysis for concept checks
+ is done by build_conept_id, called from the parser. */
}
else if (scope)
{
@@ -3970,16 +3961,6 @@ finish_id_expression_1 (tree id_expression,
decl = baselink_for_fns (decl);
}
- else if (concept_check_p (decl))
- {
- /* If this is a standard or variable concept check, potentially
- evaluate it. Function concepts need to be called as functions,
- so don't try evaluating them here. */
- tree tmpl = TREE_OPERAND (decl, 0);
- tree args = TREE_OPERAND (decl, 1);
- if (!function_concept_p (tmpl) && !uses_template_parms (args))
- decl = evaluate_concept_check (decl, tf_warning_or_error);
- }
else
{
if (DECL_P (decl) && DECL_NONLOCAL (decl)
@@ -4436,7 +4417,9 @@ expand_or_defer_fn_1 (tree fn)
if (DECL_INTERFACE_KNOWN (fn))
/* We've already made a decision as to how this function will
be handled. */;
- else if (!at_eof || DECL_IMMEDIATE_FUNCTION_P (fn))
+ else if (!at_eof
+ || DECL_IMMEDIATE_FUNCTION_P (fn)
+ || DECL_OMP_DECLARE_REDUCTION_P (fn))
tentative_decl_linkage (fn);
else
import_export_decl (fn);
@@ -4448,6 +4431,7 @@ expand_or_defer_fn_1 (tree fn)
if (DECL_DECLARED_INLINE_P (fn)
&& !DECL_REALLY_EXTERN (fn)
&& !DECL_IMMEDIATE_FUNCTION_P (fn)
+ && !DECL_OMP_DECLARE_REDUCTION_P (fn)
&& (flag_keep_inline_functions
|| (flag_keep_inline_dllexport
&& lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))))
@@ -4480,6 +4464,9 @@ expand_or_defer_fn_1 (tree fn)
return false;
}
+ if (DECL_OMP_DECLARE_REDUCTION_P (fn))
+ return false;
+
return true;
}
@@ -7193,7 +7180,8 @@ finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
remove = true;
else
{
- t = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+ t = cp_build_indirect_ref (OMP_CLAUSE_LOCATION (c),
+ addr, RO_UNARY_STAR,
tf_warning_or_error);
if (t == error_mark_node)
remove = true;
@@ -9328,7 +9316,7 @@ finish_omp_depobj (location_t loc, tree depobj,
if (addr == error_mark_node)
depobj = error_mark_node;
else
- depobj = cp_build_indirect_ref (addr, RO_UNARY_STAR,
+ depobj = cp_build_indirect_ref (loc, addr, RO_UNARY_STAR,
tf_warning_or_error);
}
@@ -9573,6 +9561,9 @@ finish_static_assert (tree condition, tree message, location_t location,
return;
}
+ /* Save the condition in case it was a concept check. */
+ tree orig_condition = condition;
+
/* Fold the expression and convert it to a boolean value. */
condition = perform_implicit_conversion_flags (boolean_type_node, condition,
complain, LOOKUP_NORMAL);
@@ -9599,6 +9590,10 @@ finish_static_assert (tree condition, tree message, location_t location,
else
error ("static assertion failed: %s",
TREE_STRING_POINTER (message));
+
+ /* Actually explain the failure if this is a concept check. */
+ if (concept_check_p (orig_condition))
+ diagnose_constraints (location, orig_condition, NULL_TREE);
}
else if (condition && condition != error_mark_node)
{
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 9eb8b82f7a0..408aeb0dbbc 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1489,7 +1489,7 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags)
return t;
if (!(flags & STF_STRIP_DEPENDENT)
- && dependent_alias_template_spec_p (t))
+ && dependent_alias_template_spec_p (t, nt_opaque))
/* DR 1558: However, if the template-id is dependent, subsequent
template argument substitution still applies to the template-id. */
return t;
@@ -1673,14 +1673,19 @@ strip_typedefs (tree t, bool *remove_attributes, unsigned int flags)
if ((flags & STF_USER_VISIBLE)
&& !user_facing_original_type_p (t))
return t;
+ /* If T is a non-template alias or typedef, we can assume that
+ instantiating its definition will hit any substitution failure,
+ so we don't need to retain it here as well. */
+ if (!alias_template_specialization_p (t, nt_opaque))
+ flags |= STF_STRIP_DEPENDENT;
result = strip_typedefs (DECL_ORIGINAL_TYPE (TYPE_NAME (t)),
- remove_attributes,
- flags | STF_STRIP_DEPENDENT);
+ remove_attributes, flags);
}
else
result = TYPE_MAIN_VARIANT (t);
}
gcc_assert (!typedef_variant_p (result)
+ || dependent_alias_template_spec_p (result, nt_opaque)
|| ((flags & STF_USER_VISIBLE)
&& !user_facing_original_type_p (result)));
@@ -2333,6 +2338,9 @@ lookup_mark (tree ovl, bool val)
tree
lookup_add (tree fns, tree lookup)
{
+ if (fns == error_mark_node || lookup == error_mark_node)
+ return error_mark_node;
+
if (lookup || TREE_CODE (fns) == TEMPLATE_DECL)
{
lookup = ovl_make (fns, lookup);
@@ -3144,6 +3152,11 @@ replace_placeholders_r (tree* t, int* walk_subtrees, void* data_)
tree type = TREE_TYPE (*valp);
tree subob = obj;
+ /* Elements with RANGE_EXPR index shouldn't have any
+ placeholders in them. */
+ if (ce->index && TREE_CODE (ce->index) == RANGE_EXPR)
+ continue;
+
if (TREE_CODE (*valp) == CONSTRUCTOR
&& AGGREGATE_TYPE_P (type))
{
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 100ae8f8186..a9b87ea8caf 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -1463,10 +1463,13 @@ structural_comptypes (tree t1, tree t2, int strict)
substitute into the specialization arguments at instantiation
time. And aliases can't be equivalent without being ==, so
we don't need to look any deeper. */
- if (comparing_specializations
- && (dependent_alias_template_spec_p (t1)
- || dependent_alias_template_spec_p (t2)))
- return false;
+ if (comparing_specializations)
+ {
+ tree dep1 = dependent_alias_template_spec_p (t1, nt_transparent);
+ tree dep2 = dependent_alias_template_spec_p (t2, nt_transparent);
+ if ((dep1 || dep2) && dep1 != dep2)
+ return false;
+ }
/* If we get here, we know that from a target independent POV the
types are the same. Make sure the target attributes are also
@@ -3278,7 +3281,7 @@ build_x_indirect_ref (location_t loc, tree expr, ref_operator errorstring,
rval = build_new_op (loc, INDIRECT_REF, LOOKUP_NORMAL, expr,
NULL_TREE, NULL_TREE, &overload, complain);
if (!rval)
- rval = cp_build_indirect_ref (expr, errorstring, complain);
+ rval = cp_build_indirect_ref (loc, expr, errorstring, complain);
if (processing_template_decl && rval != error_mark_node)
{
@@ -3296,7 +3299,7 @@ build_x_indirect_ref (location_t loc, tree expr, ref_operator errorstring,
constructs. If DO_FOLD is true, fold away INDIRECT_REF of ADDR_EXPR. */
static tree
-cp_build_indirect_ref_1 (tree ptr, ref_operator errorstring,
+cp_build_indirect_ref_1 (location_t loc, tree ptr, ref_operator errorstring,
tsubst_flags_t complain, bool do_fold)
{
tree pointer, type;
@@ -3345,7 +3348,7 @@ cp_build_indirect_ref_1 (tree ptr, ref_operator errorstring,
/* A pointer to incomplete type (other than cv void) can be
dereferenced [expr.unary.op]/1 */
if (complain & tf_error)
- error ("%qT is not a pointer-to-object type", type);
+ error_at (loc, "%qT is not a pointer-to-object type", type);
return error_mark_node;
}
else if (do_fold && TREE_CODE (pointer) == ADDR_EXPR
@@ -3376,23 +3379,25 @@ cp_build_indirect_ref_1 (tree ptr, ref_operator errorstring,
switch (errorstring)
{
case RO_ARRAY_INDEXING:
- error ("invalid use of array indexing on pointer to member");
+ error_at (loc,
+ "invalid use of array indexing on pointer to member");
break;
case RO_UNARY_STAR:
- error ("invalid use of unary %<*%> on pointer to member");
+ error_at (loc, "invalid use of unary %<*%> on pointer to member");
break;
case RO_IMPLICIT_CONVERSION:
- error ("invalid use of implicit conversion on pointer to member");
+ error_at (loc, "invalid use of implicit conversion on pointer "
+ "to member");
break;
case RO_ARROW_STAR:
- error ("left hand operand of %<->*%> must be a pointer to class, "
- "but is a pointer to member of type %qT", type);
+ error_at (loc, "left hand operand of %<->*%> must be a pointer to "
+ "class, but is a pointer to member of type %qT", type);
break;
default:
gcc_unreachable ();
}
else if (pointer != error_mark_node)
- invalid_indirection_error (input_location, type, errorstring);
+ invalid_indirection_error (loc, type, errorstring);
return error_mark_node;
}
@@ -3400,10 +3405,10 @@ cp_build_indirect_ref_1 (tree ptr, ref_operator errorstring,
/* Entry point used by c-common, which expects folding. */
tree
-build_indirect_ref (location_t /*loc*/,
- tree ptr, ref_operator errorstring)
+build_indirect_ref (location_t loc, tree ptr, ref_operator errorstring)
{
- return cp_build_indirect_ref_1 (ptr, errorstring, tf_warning_or_error, true);
+ return cp_build_indirect_ref_1 (loc, ptr, errorstring,
+ tf_warning_or_error, true);
}
/* Entry point used by internal indirection needs that don't correspond to any
@@ -3412,17 +3417,18 @@ build_indirect_ref (location_t /*loc*/,
tree
cp_build_fold_indirect_ref (tree pointer)
{
- return cp_build_indirect_ref_1 (pointer, RO_NULL, tf_warning_or_error, true);
+ return cp_build_indirect_ref_1 (input_location, pointer, RO_NULL,
+ tf_warning_or_error, true);
}
/* Entry point used by indirection needs that correspond to some syntactic
construct. */
tree
-cp_build_indirect_ref (tree ptr, ref_operator errorstring,
+cp_build_indirect_ref (location_t loc, tree ptr, ref_operator errorstring,
tsubst_flags_t complain)
{
- return cp_build_indirect_ref_1 (ptr, errorstring, complain, false);
+ return cp_build_indirect_ref_1 (loc, ptr, errorstring, complain, false);
}
/* This handles expressions of the form "a[i]", which denotes
@@ -3599,7 +3605,7 @@ cp_build_array_ref (location_t loc, tree array, tree idx,
ret = cp_build_binary_op (input_location, PLUS_EXPR, ar, ind, complain);
if (first)
ret = build2_loc (loc, COMPOUND_EXPR, TREE_TYPE (ret), first, ret);
- ret = cp_build_indirect_ref (ret, RO_ARRAY_INDEXING, complain);
+ ret = cp_build_indirect_ref (loc, ret, RO_ARRAY_INDEXING, complain);
protected_set_expr_location (ret, loc);
if (non_lvalue)
ret = non_lvalue_loc (loc, ret);
@@ -6517,7 +6523,8 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
if (TREE_CODE (argtype) == ENUMERAL_TYPE)
{
if (complain & tf_error)
- permerror (input_location, (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
+ permerror (location, (code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)
? G_("ISO C++ forbids incrementing an enum")
: G_("ISO C++ forbids decrementing an enum"));
else
@@ -6533,22 +6540,26 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
if (!COMPLETE_OR_VOID_TYPE_P (type))
{
if (complain & tf_error)
- error (((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR))
- ? G_("cannot increment a pointer to incomplete type %qT")
- : G_("cannot decrement a pointer to incomplete type %qT"),
- TREE_TYPE (argtype));
+ error_at (location, ((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR))
+ ? G_("cannot increment a pointer to incomplete "
+ "type %qT")
+ : G_("cannot decrement a pointer to incomplete "
+ "type %qT"),
+ TREE_TYPE (argtype));
else
return error_mark_node;
}
else if (!TYPE_PTROB_P (argtype))
{
if (complain & tf_error)
- pedwarn (input_location, OPT_Wpointer_arith,
+ pedwarn (location, OPT_Wpointer_arith,
(code == PREINCREMENT_EXPR
|| code == POSTINCREMENT_EXPR)
- ? G_("ISO C++ forbids incrementing a pointer of type %qT")
- : G_("ISO C++ forbids decrementing a pointer of type %qT"),
+ ? G_("ISO C++ forbids incrementing a pointer "
+ "of type %qT")
+ : G_("ISO C++ forbids decrementing a pointer "
+ "of type %qT"),
argtype);
else
return error_mark_node;
@@ -6594,8 +6605,9 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
if (code == POSTDECREMENT_EXPR || code == PREDECREMENT_EXPR)
{
if (complain & tf_error)
- error ("use of an operand of type %qT in %<operator--%> "
- "is forbidden", boolean_type_node);
+ error_at (location,
+ "use of an operand of type %qT in %<operator--%> "
+ "is forbidden", boolean_type_node);
return error_mark_node;
}
else
@@ -6603,16 +6615,18 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
if (cxx_dialect >= cxx17)
{
if (complain & tf_error)
- error ("use of an operand of type %qT in "
- "%<operator++%> is forbidden in C++17",
- boolean_type_node);
+ error_at (location,
+ "use of an operand of type %qT in "
+ "%<operator++%> is forbidden in C++17",
+ boolean_type_node);
return error_mark_node;
}
/* Otherwise, [depr.incr.bool] says this is deprecated. */
else
- warning (OPT_Wdeprecated, "use of an operand of type %qT "
- "in %<operator++%> is deprecated",
- boolean_type_node);
+ warning_at (location, OPT_Wdeprecated,
+ "use of an operand of type %qT "
+ "in %<operator++%> is deprecated",
+ boolean_type_node);
}
val = boolean_increment (code, arg);
}
@@ -6643,7 +6657,7 @@ cp_build_unary_op (enum tree_code code, tree xarg, bool noconvert,
}
if (complain & tf_error)
- error ("%s", errstring);
+ error_at (location, "%s", errstring);
return error_mark_node;
}
@@ -7035,7 +7049,8 @@ cp_build_compound_expr (tree lhs, tree rhs, tsubst_flags_t complain)
if (type_unknown_p (rhs))
{
if (complain & tf_error)
- error ("no context to resolve type of %qE", rhs);
+ error_at (cp_expr_loc_or_input_loc (rhs),
+ "no context to resolve type of %qE", rhs);
return error_mark_node;
}
@@ -8280,7 +8295,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
if (VOID_TYPE_P (TREE_TYPE (rhs)))
{
if (complain & tf_error)
- error ("void value not ignored as it ought to be");
+ error_at (cp_expr_loc_or_loc (rhs, loc),
+ "void value not ignored as it ought to be");
return error_mark_node;
}
@@ -8493,7 +8509,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
if (modifycode != INIT_EXPR)
{
if (complain & tf_error)
- error ("assigning to an array from an initializer list");
+ error_at (loc,
+ "assigning to an array from an initializer list");
return error_mark_node;
}
if (check_array_initializer (lhs, lhstype, newrhs))
@@ -8520,8 +8537,8 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))))
{
if (complain & tf_error)
- error ("incompatible types in assignment of %qT to %qT",
- TREE_TYPE (rhs), lhstype);
+ error_at (loc, "incompatible types in assignment of %qT to %qT",
+ TREE_TYPE (rhs), lhstype);
return error_mark_node;
}
@@ -8534,9 +8551,9 @@ cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
if (complain & tf_error)
{
if (modifycode == INIT_EXPR)
- error ("array used as initializer");
+ error_at (loc, "array used as initializer");
else
- error ("invalid array assignment");
+ error_at (loc, "invalid array assignment");
}
return error_mark_node;
}
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 7a8de4b7c2c..b8868546444 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -2060,7 +2060,7 @@ build_x_arrow (location_t loc, tree expr, tsubst_flags_t complain)
return expr;
}
- return cp_build_indirect_ref (last_rval, RO_ARROW, complain);
+ return cp_build_indirect_ref (loc, last_rval, RO_ARROW, complain);
}
if (complain & tf_error)
diff --git a/gcc/dbgcnt.c b/gcc/dbgcnt.c
index f58ef8fd00e..2b6b8801c32 100644
--- a/gcc/dbgcnt.c
+++ b/gcc/dbgcnt.c
@@ -25,6 +25,7 @@ See dbgcnt.def for usage information. */
#include "diagnostic-core.h"
#include "dumpfile.h"
#include "selftest.h"
+#include "intl.h"
#include "dbgcnt.h"
@@ -222,7 +223,7 @@ void
dbg_cnt_list_all_counters (void)
{
int i;
- printf (" %-30s %s\n", "counter name", "closed intervals");
+ printf (" %-30s %s\n", G_("counter name"), G_("closed intervals"));
printf ("-----------------------------------------------------------------\n");
for (i = 0; i < debug_counter_number_of_counters; i++)
{
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 56a3d60a947..b487e03fa96 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -3711,6 +3711,41 @@ Function Attributes}, @ref{PowerPC Function Attributes},
@ref{Nios II Function Attributes}, and @ref{S/390 Function Attributes}
for details.
+@item symver ("@var{name2}@@@var{nodename}")
+On ELF targets this attribute creates a symbol version. The @var{name2} part
+of the parameter is the actual name of the symbol by which it will be
+externally referenced. The @code{nodename} portion should be the name of a
+node specified in the version script supplied to the linker when building a
+shared library. Versioned symbol must be defined and must be exported with
+default visibility.
+
+@smallexample
+__attribute__ ((__symver__ ("foo@@VERS_1"))) int
+foo_v1 (void)
+@{
+@}
+@end smallexample
+
+Will produce a @code{.symver foo_v1, foo@@VERS_1} directive in the assembler
+output.
+
+It's an error to define multiple version of a given symbol. In such case
+an alias can be used.
+
+@smallexample
+__attribute__ ((__symver__ ("foo@@VERS_2")))
+__attribute__ ((alias ("foo_v1")))
+int symver_foo_v1 (void);
+@end smallexample
+
+This example creates an alias of @code{foo_v1} with symbol name
+@code{symver_foo_v1} which will be version @code{VERS_2} of @code{foo}.
+
+Finally if the parameter is @code{"@var{name2}@@@@@var{nodename}"} then in
+addition to creating a symbol version (as if
+@code{"@var{name2}@@@var{nodename}"} was used) the version will be also used
+to resolve @var{name2} by the linker.
+
@item target_clones (@var{options})
@cindex @code{target_clones} function attribute
The @code{target_clones} attribute is used to specify that a function
diff --git a/gcc/doc/install.texi b/gcc/doc/install.texi
index be203023da5..80b47812fe6 100644
--- a/gcc/doc/install.texi
+++ b/gcc/doc/install.texi
@@ -1559,8 +1559,8 @@ addition, @samp{libstdc++}'s include files will be installed into
@file{@var{libdir}} unless you overruled it by using
@option{--with-gxx-include-dir=@var{dirname}}. Using this option is
particularly useful if you intend to use several versions of GCC in
-parallel. This is currently supported by @samp{libgfortran},
-@samp{libstdc++}, and @samp{libobjc}.
+parallel. The default is @samp{yes} for @samp{libada}, and @samp{no} for
+the remaining libraries.
@item @anchor{WithAixSoname}--with-aix-soname=@samp{aix}, @samp{svr4} or @samp{both}
Traditional AIX shared library versioning (versioned @code{Shared Object}
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index b7c18103ef2..81a869419a0 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -12039,6 +12039,13 @@ IPA-CP calculates its own score of cloning profitability heuristics
and performs those cloning opportunities with scores that exceed
@option{ipa-cp-eval-threshold}.
+@item ipa-cp-max-recursive-depth
+Maximum depth of recursive cloning for self-recursive function.
+
+@item ipa-cp-min-recursive-probability
+Recursive cloning only when the probability of call being executed exceeds
+the parameter.
+
@item ipa-cp-recursion-penalty
Percentage penalty the recursive functions will receive when they
are evaluated for cloning.
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index a30db0de88f..3950c82c685 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1522,6 +1522,10 @@ Target does not support a vector add instruction on @code{int}.
@item vect_no_bitwise
Target does not support vector bitwise instructions.
+@item vect_bool_cmp
+Target supports comparison of @code{bool} vectors for at least one
+vector length.
+
@item vect_char_add
Target supports addition of @code{char} vectors for at least one
vector length.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 2244df4dc5b..5b8b68bd710 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -5959,18 +5959,6 @@ instruction pattern. There is no need for the hook to handle these two
implementation approaches itself.
@end deftypefn
-@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_CONVERSION (unsigned @var{code}, tree @var{dest_type}, tree @var{src_type})
-This hook should return the DECL of a function that implements conversion of the
-input vector of type @var{src_type} to type @var{dest_type}.
-The value of @var{code} is one of the enumerators in @code{enum tree_code} and
-specifies how the conversion is to be applied
-(truncation, rounding, etc.).
-
-If this hook is defined, the autovectorizer will use the
-@code{TARGET_VECTORIZE_BUILTIN_CONVERSION} target hook when vectorizing
-conversion. Otherwise, it will return @code{NULL_TREE}.
-@end deftypefn
-
@deftypefn {Target Hook} tree TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION (unsigned @var{code}, tree @var{vec_type_out}, tree @var{vec_type_in})
This hook should return the decl of a function that implements the
vectorized variant of the function with the @code{combined_fn} code
@@ -11988,6 +11976,19 @@ conversion rules.
This is currently used only by the C and C++ front ends.
@end deftypefn
+@deftypefn {Target Hook} bool TARGET_VERIFY_TYPE_CONTEXT (location_t @var{loc}, type_context_kind @var{context}, const_tree @var{type}, bool @var{silent_p})
+If defined, this hook returns false if there is a target-specific reason
+why type @var{type} cannot be used in the source language context described
+by @var{context}. When @var{silent_p} is false, the hook also reports an
+error against @var{loc} for invalid uses of @var{type}.
+
+Calls to this hook should be made through the global function
+@code{verify_type_context}, which makes the @var{silent_p} parameter
+default to false and also handles @code{error_mark_node}.
+
+The default implementation always returns true.
+@end deftypefn
+
@defmac OBJC_JBLEN
This macro determines the size of the objective C jump buffer for the
NeXT runtime. By default, OBJC_JBLEN is defined to an innocuous value.
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 52cd603dc4e..1b061d70127 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -4163,8 +4163,6 @@ address; but often a machine-dependent strategy can generate better code.
@hook TARGET_VECTORIZE_VEC_PERM_CONST
-@hook TARGET_VECTORIZE_BUILTIN_CONVERSION
-
@hook TARGET_VECTORIZE_BUILTIN_VECTORIZED_FUNCTION
@hook TARGET_VECTORIZE_BUILTIN_MD_VECTORIZED_FUNCTION
@@ -8089,6 +8087,8 @@ and scanf formatter settings.
@hook TARGET_CONVERT_TO_TYPE
+@hook TARGET_VERIFY_TYPE_CONTEXT
+
@defmac OBJC_JBLEN
This macro determines the size of the objective C jump buffer for the
NeXT runtime. By default, OBJC_JBLEN is defined to an innocuous value.
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 9f1d921ddad..6fb345b38b0 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -27118,6 +27118,9 @@ lookup_filename (const char *file_name)
if (!file_name)
return NULL;
+ if (!file_name[0])
+ file_name = "<stdin>";
+
dwarf_file_data **slot
= file_table->find_slot_with_hash (file_name, htab_hash_string (file_name),
INSERT);
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 3a14d2a41c1..c4f52fb3c15 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -99,7 +99,7 @@ do_mpfr_ckconv (real_value *result, mpfr_srcptr m, bool inexact,
return false;
REAL_VALUE_TYPE tmp;
- real_from_mpfr (&tmp, m, format, GMP_RNDN);
+ real_from_mpfr (&tmp, m, format, MPFR_RNDN);
/* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we
@@ -130,11 +130,11 @@ do_mpfr_arg1 (real_value *result,
return false;
int prec = format->p;
- mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
+ mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
mpfr_t m;
mpfr_init2 (m, prec);
- mpfr_from_real (m, arg, GMP_RNDN);
+ mpfr_from_real (m, arg, MPFR_RNDN);
mpfr_clear_flags ();
bool inexact = func (m, m, rnd);
bool ok = do_mpfr_ckconv (result, m, inexact, format);
@@ -160,11 +160,11 @@ do_mpfr_sincos (real_value *result_sin, real_value *result_cos,
return false;
int prec = format->p;
- mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
+ mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
mpfr_t m, ms, mc;
mpfr_inits2 (prec, m, ms, mc, NULL);
- mpfr_from_real (m, arg, GMP_RNDN);
+ mpfr_from_real (m, arg, MPFR_RNDN);
mpfr_clear_flags ();
bool inexact = mpfr_sin_cos (ms, mc, m, rnd);
bool ok = (do_mpfr_ckconv (result_sin, ms, inexact, format)
@@ -193,12 +193,12 @@ do_mpfr_arg2 (real_value *result,
return false;
int prec = format->p;
- mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
+ mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
mpfr_t m0, m1;
mpfr_inits2 (prec, m0, m1, NULL);
- mpfr_from_real (m0, arg0, GMP_RNDN);
- mpfr_from_real (m1, arg1, GMP_RNDN);
+ mpfr_from_real (m0, arg0, MPFR_RNDN);
+ mpfr_from_real (m1, arg1, MPFR_RNDN);
mpfr_clear_flags ();
bool inexact = func (m0, m0, m1, rnd);
bool ok = do_mpfr_ckconv (result, m0, inexact, format);
@@ -216,7 +216,7 @@ do_mpfr_arg2 (real_value *result,
static bool
do_mpfr_arg2 (real_value *result,
- int (*func) (mpfr_ptr, long, mpfr_srcptr, mp_rnd_t),
+ int (*func) (mpfr_ptr, long, mpfr_srcptr, mpfr_rnd_t),
const wide_int_ref &arg0, const real_value *arg1,
const real_format *format)
{
@@ -224,11 +224,11 @@ do_mpfr_arg2 (real_value *result,
return false;
int prec = format->p;
- mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
+ mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
mpfr_t m;
mpfr_init2 (m, prec);
- mpfr_from_real (m, arg1, GMP_RNDN);
+ mpfr_from_real (m, arg1, MPFR_RNDN);
mpfr_clear_flags ();
bool inexact = func (m, arg0.to_shwi (), m, rnd);
bool ok = do_mpfr_ckconv (result, m, inexact, format);
@@ -260,13 +260,13 @@ do_mpfr_arg3 (real_value *result,
return false;
int prec = format->p;
- mp_rnd_t rnd = format->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
+ mpfr_rnd_t rnd = format->round_towards_zero ? MPFR_RNDZ : MPFR_RNDN;
mpfr_t m0, m1, m2;
mpfr_inits2 (prec, m0, m1, m2, NULL);
- mpfr_from_real (m0, arg0, GMP_RNDN);
- mpfr_from_real (m1, arg1, GMP_RNDN);
- mpfr_from_real (m2, arg2, GMP_RNDN);
+ mpfr_from_real (m0, arg0, MPFR_RNDN);
+ mpfr_from_real (m1, arg1, MPFR_RNDN);
+ mpfr_from_real (m2, arg2, MPFR_RNDN);
mpfr_clear_flags ();
bool inexact = func (m0, m0, m1, m2, rnd);
bool ok = do_mpfr_ckconv (result, m0, inexact, format);
@@ -296,8 +296,8 @@ do_mpc_ckconv (real_value *result_real, real_value *result_imag,
return false;
REAL_VALUE_TYPE tmp_real, tmp_imag;
- real_from_mpfr (&tmp_real, mpc_realref (m), format, GMP_RNDN);
- real_from_mpfr (&tmp_imag, mpc_imagref (m), format, GMP_RNDN);
+ real_from_mpfr (&tmp_real, mpc_realref (m), format, MPFR_RNDN);
+ real_from_mpfr (&tmp_imag, mpc_imagref (m), format, MPFR_RNDN);
/* Proceed iff GCC's REAL_VALUE_TYPE can hold the MPFR values.
If the REAL_VALUE_TYPE is zero but the mpft_t is not, then we
@@ -341,8 +341,8 @@ do_mpc_arg1 (real_value *result_real, real_value *result_imag,
mpc_t m;
mpc_init2 (m, prec);
- mpfr_from_real (mpc_realref (m), arg_real, GMP_RNDN);
- mpfr_from_real (mpc_imagref (m), arg_imag, GMP_RNDN);
+ mpfr_from_real (mpc_realref (m), arg_real, MPFR_RNDN);
+ mpfr_from_real (mpc_imagref (m), arg_imag, MPFR_RNDN);
mpfr_clear_flags ();
bool inexact = func (m, m, crnd);
bool ok = do_mpc_ckconv (result_real, result_imag, m, inexact, format);
@@ -378,10 +378,10 @@ do_mpc_arg2 (real_value *result_real, real_value *result_imag,
mpc_init2 (m0, prec);
mpc_init2 (m1, prec);
- mpfr_from_real (mpc_realref (m0), arg0_real, GMP_RNDN);
- mpfr_from_real (mpc_imagref (m0), arg0_imag, GMP_RNDN);
- mpfr_from_real (mpc_realref (m1), arg1_real, GMP_RNDN);
- mpfr_from_real (mpc_imagref (m1), arg1_imag, GMP_RNDN);
+ mpfr_from_real (mpc_realref (m0), arg0_real, MPFR_RNDN);
+ mpfr_from_real (mpc_imagref (m0), arg0_imag, MPFR_RNDN);
+ mpfr_from_real (mpc_realref (m1), arg1_real, MPFR_RNDN);
+ mpfr_from_real (mpc_imagref (m1), arg1_imag, MPFR_RNDN);
mpfr_clear_flags ();
bool inexact = func (m0, m0, m1, crnd);
bool ok = do_mpc_ckconv (result_real, result_imag, m0, inexact, format);
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 95e22137bca..a29d4229c7e 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,31 @@
+2019-11-30 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/91783
+ * dependency.c (gfc_dep_resolver): Do not look at _data
+ component if present.
+
+2019-11-28 Jerry DeLisle <jvdelisle@gcc.ngu.org>
+
+ PR fortran/90374
+ * io.c (check_format): Allow zero width expoenent with e0.
+
+2019-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/91944
+ * simplify.c (gfc_simplify_spread): Check gfc_init_expr_flag instead
+ of gfc_current_ns->sym_root->n.sym->attr.flavor == FL_PARAMETER.
+
+2019-11-27 Tobias Burnus <tobias@codesourcery.com>
+
+ PR middle-end/92463
+ * arith.c (gfc_check_real_range): Replace mp_exp_t by mpfr_exp_t.
+
+2019-11-25 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/92629
+ * simplify.c (convert_mpz_to_unsigned): Skip assert for argument
+ range when -fno-range-check is specified.
+
2019-11-25 Mark Eggleston <mark.eggleston@codethink.com>
Jim MacArthur <jim.macarthur@codethink.co.uk>
diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c
index cf480779709..7f048da9583 100644
--- a/gcc/fortran/arith.c
+++ b/gcc/fortran/arith.c
@@ -385,8 +385,8 @@ gfc_check_real_range (mpfr_t p, int kind)
/* Set emin and emax for the current model number. */
en = gfc_real_kinds[i].min_exponent - gfc_real_kinds[i].digits + 1;
- mpfr_set_emin ((mp_exp_t) en);
- mpfr_set_emax ((mp_exp_t) gfc_real_kinds[i].max_exponent);
+ mpfr_set_emin ((mpfr_exp_t) en);
+ mpfr_set_emax ((mpfr_exp_t) gfc_real_kinds[i].max_exponent);
mpfr_check_range (q, 0, GFC_RND_MODE);
mpfr_subnormalize (q, 0, GFC_RND_MODE);
diff --git a/gcc/fortran/dependency.c b/gcc/fortran/dependency.c
index 51148709766..02e4b4f7a65 100644
--- a/gcc/fortran/dependency.c
+++ b/gcc/fortran/dependency.c
@@ -2098,6 +2098,18 @@ gfc_dep_resolver (gfc_ref *lref, gfc_ref *rref, gfc_reverse *reverse,
gfc_dependency this_dep;
bool same_component = false;
+ /* The refs might come in mixed, one with a _data component and one
+ without. Look at their next reference in order to avoid an
+ ICE. */
+
+ if (lref && lref->type == REF_COMPONENT && lref->u.c.component
+ && strcmp (lref->u.c.component->name, "_data") == 0)
+ lref = lref->next;
+
+ if (rref && rref->type == REF_COMPONENT && rref->u.c.component
+ && strcmp (rref->u.c.component->name, "_data") == 0)
+ rref = rref->next;
+
this_dep = GFC_DEP_ERROR;
fin_dep = GFC_DEP_ERROR;
/* Dependencies due to pointers should already have been identified.
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c
index 57a3fdd5152..8cf8c2d96af 100644
--- a/gcc/fortran/io.c
+++ b/gcc/fortran/io.c
@@ -1007,9 +1007,22 @@ data_desc:
goto fail;
if (u != FMT_POSINT)
{
- error = G_("Positive exponent width required in format string "
- "at %L");
- goto syntax;
+ if (u == FMT_ZERO)
+ {
+ if (!gfc_notify_std (GFC_STD_F2018,
+ "Positive exponent width required in "
+ "format string at %L", &format_locus))
+ {
+ saved_token = u;
+ goto fail;
+ }
+ }
+ else
+ {
+ error = G_("Positive exponent width required in format "
+ "string at %L");
+ goto syntax;
+ }
}
}
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index b48bf014121..93f3da38af6 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -169,8 +169,10 @@ convert_mpz_to_unsigned (mpz_t x, int bitsize)
}
else
{
- /* Confirm that no bits above the signed range are set. */
- gcc_assert (mpz_scan1 (x, bitsize-1) == ULONG_MAX);
+ /* Confirm that no bits above the signed range are set if we
+ are doing range checking. */
+ if (flag_range_check != 0)
+ gcc_assert (mpz_scan1 (x, bitsize-1) == ULONG_MAX);
}
}
@@ -7654,7 +7656,7 @@ gfc_simplify_spread (gfc_expr *source, gfc_expr *dim_expr, gfc_expr *ncopies_exp
nelem = mpz_get_si (size) * ncopies;
if (nelem > flag_max_array_constructor)
{
- if (gfc_current_ns->sym_root->n.sym->attr.flavor == FL_PARAMETER)
+ if (gfc_init_expr_flag)
{
gfc_error ("The number of elements (%d) in the array constructor "
"at %L requires an increase of the allowed %d upper "
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 539ded01ce6..4428d50c390 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -4741,7 +4741,7 @@ process_command (unsigned int decoded_options_count,
/* More prefixes are enabled in main, after we read the specs file
and determine whether this is cross-compilation or not. */
- if (n_infiles == last_language_n_infiles && spec_lang != 0)
+ if (n_infiles != 0 && n_infiles == last_language_n_infiles && spec_lang != 0)
warning (0, "%<-x %s%> after last input file has no effect", spec_lang);
/* Synthesize -fcompare-debug flag from the GCC_COMPARE_DEBUG
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index fadc422aed8..849bee2e069 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -2346,18 +2346,19 @@ gimple_fold_builtin_string_compare (gimple_stmt_iterator *gsi)
tree str1 = gimple_call_arg (stmt, 0);
tree str2 = gimple_call_arg (stmt, 1);
tree lhs = gimple_call_lhs (stmt);
- tree len = NULL_TREE;
+
+ tree bound_node = NULL_TREE;
unsigned HOST_WIDE_INT bound = HOST_WIDE_INT_M1U;
/* Handle strncmp and strncasecmp functions. */
if (gimple_call_num_args (stmt) == 3)
{
- len = gimple_call_arg (stmt, 2);
- if (tree_fits_uhwi_p (len))
- bound = tree_to_uhwi (len);
+ bound_node = gimple_call_arg (stmt, 2);
+ if (tree_fits_uhwi_p (bound_node))
+ bound = tree_to_uhwi (bound_node);
}
- /* If the LEN parameter is zero, return zero. */
+ /* If the BOUND parameter is zero, return zero. */
if (bound == 0)
{
replace_call_with_value (gsi, integer_zero_node);
@@ -2418,6 +2419,9 @@ gimple_fold_builtin_string_compare (gimple_stmt_iterator *gsi)
case BUILT_IN_STRNCMP:
case BUILT_IN_STRNCMP_EQ:
{
+ if (bound == HOST_WIDE_INT_M1U)
+ break;
+
/* Reduce the bound to be no more than the length
of the shorter of the two strings, or the sizes
of the unterminated arrays. */
diff --git a/gcc/gimple-match-head.c b/gcc/gimple-match-head.c
index 2996bade301..9010f11621e 100644
--- a/gcc/gimple-match-head.c
+++ b/gcc/gimple-match-head.c
@@ -144,9 +144,21 @@ maybe_resimplify_conditional_op (gimple_seq *seq, gimple_match_op *res_op,
/* Likewise if the operation would not trap. */
bool honor_trapv = (INTEGRAL_TYPE_P (res_op->type)
&& TYPE_OVERFLOW_TRAPS (res_op->type));
- if (!operation_could_trap_p ((tree_code) res_op->code,
- FLOAT_TYPE_P (res_op->type),
- honor_trapv, res_op->op_or_null (1)))
+ tree_code op_code = (tree_code) res_op->code;
+ bool op_could_trap;
+
+ /* COND_EXPR and VEC_COND_EXPR will trap if, and only if, the condition
+ traps and hence we have to check this. For all other operations, we
+ don't need to consider the operands. */
+ if (op_code == COND_EXPR || op_code == VEC_COND_EXPR)
+ op_could_trap = generic_expr_could_trap_p (res_op->ops[0]);
+ else
+ op_could_trap = operation_could_trap_p ((tree_code) res_op->code,
+ FLOAT_TYPE_P (res_op->type),
+ honor_trapv,
+ res_op->op_or_null (1));
+
+ if (!op_could_trap)
{
res_op->cond.cond = NULL_TREE;
return false;
diff --git a/gcc/gimple-ssa-sprintf.c b/gcc/gimple-ssa-sprintf.c
index 804a0867587..2bbb2b37ac3 100644
--- a/gcc/gimple-ssa-sprintf.c
+++ b/gcc/gimple-ssa-sprintf.c
@@ -1606,7 +1606,7 @@ format_floating_max (tree type, char spec, HOST_WIDE_INT prec)
round-to-nearest mode. */
mpfr_t x;
mpfr_init2 (x, rfmt->p);
- mpfr_from_real (x, &rv, GMP_RNDN);
+ mpfr_from_real (x, &rv, MPFR_RNDN);
/* Return a value one greater to account for the leading minus sign. */
unsigned HOST_WIDE_INT r
@@ -1953,7 +1953,7 @@ format_floating (const directive &dir, tree arg, const vr_values *)
rounding in either direction can result in longer output. */
mpfr_t mpfrval;
mpfr_init2 (mpfrval, rfmt->p);
- mpfr_from_real (mpfrval, rvp, i ? GMP_RNDU : GMP_RNDD);
+ mpfr_from_real (mpfrval, rvp, i ? MPFR_RNDU : MPFR_RNDD);
/* Use the MPFR rounding specifier to round down in the first
iteration and then up. In most but not all cases this will
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 31a98a3d98a..693c7a2fdc5 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -228,7 +228,9 @@ public:
inline bool set_contains_variable ();
bool add_value (valtype newval, cgraph_edge *cs,
ipcp_value<valtype> *src_val = NULL,
- int src_idx = 0, HOST_WIDE_INT offset = -1);
+ int src_idx = 0, HOST_WIDE_INT offset = -1,
+ ipcp_value<valtype> **val_p = NULL,
+ bool unlimited = false);
void print (FILE * f, bool dump_sources, bool dump_benefits);
};
@@ -1165,7 +1167,7 @@ set_single_call_flag (cgraph_node *node, void *)
/* Local thunks can be handled transparently, skip them. */
while (cs && cs->caller->thunk.thunk_p && cs->caller->local)
cs = cs->next_caller;
- if (cs)
+ if (cs && IPA_NODE_REF (cs->caller))
{
IPA_NODE_REF (cs->caller)->node_calling_single_call = true;
return true;
@@ -1817,22 +1819,32 @@ allocate_and_init_ipcp_value (ipa_polymorphic_call_context source)
/* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS,
SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same
meaning. OFFSET -1 means the source is scalar and not a part of an
- aggregate. */
+ aggregate. If non-NULL, VAL_P records address of existing or newly added
+ ipcp_value. UNLIMITED means whether value count should not exceed the limit
+ given by PARAM_IPA_CP_VALUE_LIST_SIZE. */
template <typename valtype>
bool
ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
ipcp_value<valtype> *src_val,
- int src_idx, HOST_WIDE_INT offset)
+ int src_idx, HOST_WIDE_INT offset,
+ ipcp_value<valtype> **val_p,
+ bool unlimited)
{
- ipcp_value<valtype> *val;
+ ipcp_value<valtype> *val, *last_val = NULL;
+
+ if (val_p)
+ *val_p = NULL;
if (bottom)
return false;
- for (val = values; val; val = val->next)
+ for (val = values; val; last_val = val, val = val->next)
if (values_equal_for_ipcp_p (val->value, newval))
{
+ if (val_p)
+ *val_p = val;
+
if (ipa_edge_within_scc (cs))
{
ipcp_value_source<valtype> *s;
@@ -1847,7 +1859,7 @@ ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
return false;
}
- if (values_count == param_ipa_cp_value_list_size)
+ if (!unlimited && values_count == param_ipa_cp_value_list_size)
{
/* We can only free sources, not the values themselves, because sources
of other values in this SCC might point to them. */
@@ -1860,7 +1872,6 @@ ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src);
}
}
-
values = NULL;
return set_to_bottom ();
}
@@ -1868,11 +1879,81 @@ ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs,
values_count++;
val = allocate_and_init_ipcp_value (newval);
val->add_source (cs, src_val, src_idx, offset);
- val->next = values;
- values = val;
+ val->next = NULL;
+
+ /* Add the new value to end of value list, which can reduce iterations
+ of propagation stage for recursive function. */
+ if (last_val)
+ last_val->next = val;
+ else
+ values = val;
+
+ if (val_p)
+ *val_p = val;
+
return true;
}
+/* Return true, if a ipcp_value VAL is orginated from parameter value of
+ self-feeding recursive function by applying non-passthrough arithmetic
+ transformation. */
+
+static bool
+self_recursively_generated_p (ipcp_value<tree> *val)
+{
+ class ipa_node_params *info = NULL;
+
+ for (ipcp_value_source<tree> *src = val->sources; src; src = src->next)
+ {
+ cgraph_edge *cs = src->cs;
+
+ if (!src->val || cs->caller != cs->callee->function_symbol ()
+ || src->val == val)
+ return false;
+
+ if (!info)
+ info = IPA_NODE_REF (cs->caller);
+
+ class ipcp_param_lattices *plats = ipa_get_parm_lattices (info,
+ src->index);
+ ipcp_lattice<tree> *src_lat = src->offset == -1 ? &plats->itself
+ : plats->aggs;
+ ipcp_value<tree> *src_val;
+
+ for (src_val = src_lat->values; src_val; src_val = src_val->next)
+ if (src_val == val)
+ break;
+
+ if (!src_val)
+ return false;
+ }
+
+ return true;
+}
+
+/* A helper function that returns result of operation specified by OPCODE on
+ the value of SRC_VAL. If non-NULL, OPND1_TYPE is expected type for the
+ value of SRC_VAL. If the operation is binary, OPND2 is a constant value
+ acting as its second operand. If non-NULL, RES_TYPE is expected type of
+ the result. */
+
+static tree
+get_val_across_arith_op (enum tree_code opcode,
+ tree opnd1_type,
+ tree opnd2,
+ ipcp_value<tree> *src_val,
+ tree res_type)
+{
+ tree opnd1 = src_val->value;
+
+ /* Skip source values that is incompatible with specified type. */
+ if (opnd1_type
+ && !useless_type_conversion_p (opnd1_type, TREE_TYPE (opnd1)))
+ return NULL_TREE;
+
+ return ipa_get_jf_arith_result (opcode, opnd1, opnd2, res_type);
+}
+
/* Propagate values through an arithmetic transformation described by a jump
function associated with edge CS, taking values from SRC_LAT and putting
them into DEST_LAT. OPND1_TYPE is expected type for the values in SRC_LAT.
@@ -1896,24 +1977,76 @@ propagate_vals_across_arith_jfunc (cgraph_edge *cs,
ipcp_value<tree> *src_val;
bool ret = false;
- /* Do not create new values when propagating within an SCC because if there
- are arithmetic functions with circular dependencies, there is infinite
- number of them and we would just make lattices bottom. If this condition
- is ever relaxed we have to detect self-feeding recursive calls in
- cgraph_edge_brings_value_p in a smarter way. */
+ /* Due to circular dependencies, propagating within an SCC through arithmetic
+ transformation would create infinite number of values. But for
+ self-feeding recursive function, we could allow propagation in a limited
+ count, and this can enable a simple kind of recursive function versioning.
+ For other scenario, we would just make lattices bottom. */
if (opcode != NOP_EXPR && ipa_edge_within_scc (cs))
- ret = dest_lat->set_contains_variable ();
+ {
+ int i;
+
+ if (src_lat != dest_lat || param_ipa_cp_max_recursive_depth < 1)
+ return dest_lat->set_contains_variable ();
+
+ /* No benefit if recursive execution is in low probability. */
+ if (cs->sreal_frequency () * 100
+ <= ((sreal) 1) * param_ipa_cp_min_recursive_probability)
+ return dest_lat->set_contains_variable ();
+
+ auto_vec<ipcp_value<tree> *, 8> val_seeds;
+
+ for (src_val = src_lat->values; src_val; src_val = src_val->next)
+ {
+ /* Now we do not use self-recursively generated value as propagation
+ source, this is absolutely conservative, but could avoid explosion
+ of lattice's value space, especially when one recursive function
+ calls another recursive. */
+ if (self_recursively_generated_p (src_val))
+ {
+ ipcp_value_source<tree> *s;
+
+ /* If the lattice has already been propagated for the call site,
+ no need to do that again. */
+ for (s = src_val->sources; s; s = s->next)
+ if (s->cs == cs)
+ return dest_lat->set_contains_variable ();
+ }
+ else
+ val_seeds.safe_push (src_val);
+ }
+
+ /* Recursively generate lattice values with a limited count. */
+ FOR_EACH_VEC_ELT (val_seeds, i, src_val)
+ {
+ for (int j = 1; j < param_ipa_cp_max_recursive_depth; j++)
+ {
+ tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
+ src_val, res_type);
+ if (!cstval)
+ break;
+
+ ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
+ src_offset, &src_val, true);
+ gcc_checking_assert (src_val);
+ }
+ }
+ ret |= dest_lat->set_contains_variable ();
+ }
else
for (src_val = src_lat->values; src_val; src_val = src_val->next)
{
- tree opnd1 = src_val->value;
- tree cstval = NULL_TREE;
-
- /* Skip source values that is incompatible with specified type. */
- if (!opnd1_type
- || useless_type_conversion_p (opnd1_type, TREE_TYPE (opnd1)))
- cstval = ipa_get_jf_arith_result (opcode, opnd1, opnd2, res_type);
+ /* Now we do not use self-recursively generated value as propagation
+ source, otherwise it is easy to make value space of normal lattice
+ overflow. */
+ if (self_recursively_generated_p (src_val))
+ {
+ ret |= dest_lat->set_contains_variable ();
+ continue;
+ }
+ tree cstval = get_val_across_arith_op (opcode, opnd1_type, opnd2,
+ src_val, res_type);
if (cstval)
ret |= dest_lat->add_value (cstval, cs, src_val, src_idx,
src_offset);
@@ -3038,7 +3171,7 @@ hint_time_bonus (ipa_hints hints)
static inline int64_t
incorporate_penalties (ipa_node_params *info, int64_t evaluation)
{
- if (info->node_within_scc)
+ if (info->node_within_scc && !info->node_is_self_scc)
evaluation = (evaluation
* (100 - param_ipa_cp_recursion_penalty)) / 100;
@@ -3082,7 +3215,8 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
count_sum.dump (dump_file);
fprintf (dump_file, "%s%s) -> evaluation: " "%" PRId64
", threshold: %i\n",
- info->node_within_scc ? ", scc" : "",
+ info->node_within_scc
+ ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
info->node_calling_single_call ? ", single_call" : "",
evaluation, param_ipa_cp_eval_threshold);
}
@@ -3100,7 +3234,8 @@ good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit,
"size: %i, freq_sum: %i%s%s) -> evaluation: "
"%" PRId64 ", threshold: %i\n",
time_benefit, size_cost, freq_sum,
- info->node_within_scc ? ", scc" : "",
+ info->node_within_scc
+ ? (info->node_is_self_scc ? ", self_scc" : ", scc") : "",
info->node_calling_single_call ? ", single_call" : "",
evaluation, param_ipa_cp_eval_threshold);
@@ -3594,14 +3729,30 @@ propagate_constants_topo (class ipa_topo_info *topo)
while (v)
{
struct cgraph_edge *cs;
+ class ipa_node_params *info = NULL;
+ bool self_scc = true;
for (cs = v->callees; cs; cs = cs->next_callee)
if (ipa_edge_within_scc (cs))
{
- IPA_NODE_REF (v)->node_within_scc = true;
+ cgraph_node *callee = cs->callee->function_symbol ();
+
+ if (v != callee)
+ self_scc = false;
+
+ if (!info)
+ {
+ info = IPA_NODE_REF (v);
+ info->node_within_scc = true;
+ }
+
if (propagate_constants_across_call (cs))
- push_node_to_stack (topo, cs->callee->function_symbol ());
+ push_node_to_stack (topo, callee);
}
+
+ if (info)
+ info->node_is_self_scc = self_scc;
+
v = pop_node_from_stack (topo);
}
@@ -3983,6 +4134,9 @@ get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
hot |= cs->maybe_hot_p ();
if (cs->caller != dest)
non_self_recursive = true;
+ else if (src->val)
+ gcc_assert (values_equal_for_ipcp_p (src->val->value,
+ val->value));
}
cs = get_next_cgraph_edge_clone (cs);
}
@@ -3996,6 +4150,19 @@ get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest,
*freq_sum = freq;
*count_sum = cnt;
*caller_count = count;
+
+ if (!hot && IPA_NODE_REF (dest)->node_within_scc)
+ {
+ struct cgraph_edge *cs;
+
+ /* Cold non-SCC source edge could trigger hot recursive execution of
+ function. Consider the case as hot and rely on following cost model
+ computation to further select right one. */
+ for (cs = dest->callers; cs; cs = cs->next_caller)
+ if (cs->caller == dest && cs->maybe_hot_p ())
+ return true;
+ }
+
return hot;
}
@@ -4091,6 +4258,7 @@ update_profiling_info (struct cgraph_node *orig_node,
struct caller_statistics stats;
profile_count new_sum, orig_sum;
profile_count remainder, orig_node_count = orig_node->count;
+ profile_count orig_new_node_count = new_node->count;
if (!(orig_node_count.ipa () > profile_count::zero ()))
return;
@@ -4128,15 +4296,20 @@ update_profiling_info (struct cgraph_node *orig_node,
remainder = orig_node_count.combine_with_ipa_count (orig_node_count.ipa ()
- new_sum.ipa ());
new_sum = orig_node_count.combine_with_ipa_count (new_sum);
+ new_node->count = new_sum;
orig_node->count = remainder;
- profile_count::adjust_for_ipa_scaling (&new_sum, &orig_node_count);
+ profile_count::adjust_for_ipa_scaling (&new_sum, &orig_new_node_count);
for (cs = new_node->callees; cs; cs = cs->next_callee)
- cs->count = cs->count.apply_scale (new_sum, orig_node_count);
+ cs->count = cs->count.apply_scale (new_sum, orig_new_node_count);
+ for (cs = new_node->indirect_calls; cs; cs = cs->next_callee)
+ cs->count = cs->count.apply_scale (new_sum, orig_new_node_count);
profile_count::adjust_for_ipa_scaling (&remainder, &orig_node_count);
for (cs = orig_node->callees; cs; cs = cs->next_callee)
cs->count = cs->count.apply_scale (remainder, orig_node_count);
+ for (cs = orig_node->indirect_calls; cs; cs = cs->next_callee)
+ cs->count = cs->count.apply_scale (remainder, orig_node_count);
if (dump_file)
dump_profile_updates (orig_node, new_node);
@@ -4411,7 +4584,7 @@ find_more_scalar_values_for_callers_subset (struct cgraph_node *node,
struct ipa_jump_func *jump_func;
tree t;
- if (IPA_NODE_REF (cs->caller)->node_dead)
+ if (IPA_NODE_REF (cs->caller) && IPA_NODE_REF (cs->caller)->node_dead)
continue;
if (!IPA_EDGE_REF (cs)
@@ -5416,6 +5589,9 @@ ipcp_store_bits_results (void)
if (info->ipcp_orig_node)
info = IPA_NODE_REF (info->ipcp_orig_node);
+ if (!info->lattices)
+ /* Newly expanded artificial thunks do not have lattices. */
+ continue;
unsigned count = ipa_get_param_count (info);
for (unsigned i = 0; i < count; i++)
@@ -5489,6 +5665,9 @@ ipcp_store_vr_results (void)
if (info->ipcp_orig_node)
info = IPA_NODE_REF (info->ipcp_orig_node);
+ if (!info->lattices)
+ /* Newly expanded artificial thunks do not have lattices. */
+ continue;
unsigned count = ipa_get_param_count (info);
for (unsigned i = 0; i < count; i++)
diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
index c158d3c968d..a884a465a5d 100644
--- a/gcc/ipa-devirt.c
+++ b/gcc/ipa-devirt.c
@@ -356,6 +356,13 @@ types_same_for_odr (const_tree type1, const_tree type2)
|| (type_with_linkage_p (type2) && type_in_anonymous_namespace_p (type2)))
return false;
+ /* If both type has mangled defined check if they are same.
+ Watch for anonymous types which are all mangled as "<anon">. */
+ if (!type_with_linkage_p (type1) || !type_with_linkage_p (type2))
+ return false;
+ if (type_in_anonymous_namespace_p (type1)
+ || type_in_anonymous_namespace_p (type2))
+ return false;
return (DECL_ASSEMBLER_NAME (TYPE_NAME (type1))
== DECL_ASSEMBLER_NAME (TYPE_NAME (type2)));
}
@@ -986,21 +993,24 @@ warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2)
/* It is a quite common bug to reference anonymous namespace type in
non-anonymous namespace class. */
- if ((type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
- && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
- || (type_with_linkage_p (TYPE_MAIN_VARIANT (t2))
- && type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t2))))
+ tree mt1 = TYPE_MAIN_VARIANT (t1);
+ tree mt2 = TYPE_MAIN_VARIANT (t2);
+ if ((type_with_linkage_p (mt1)
+ && type_in_anonymous_namespace_p (mt1))
+ || (type_with_linkage_p (mt2)
+ && type_in_anonymous_namespace_p (mt2)))
{
- if (!type_with_linkage_p (TYPE_MAIN_VARIANT (t1))
- || !type_in_anonymous_namespace_p (TYPE_MAIN_VARIANT (t1)))
+ if (!type_with_linkage_p (mt1)
+ || !type_in_anonymous_namespace_p (mt1))
{
std::swap (t1, t2);
+ std::swap (mt1, mt2);
std::swap (loc_t1, loc_t2);
}
- gcc_assert (TYPE_NAME (t1)
- && TREE_CODE (TYPE_NAME (t1)) == TYPE_DECL);
- tree n1 = TYPE_NAME (t1);
- tree n2 = TYPE_NAME (t2) ? TYPE_NAME (t2) : NULL;
+ gcc_assert (TYPE_NAME (mt1)
+ && TREE_CODE (TYPE_NAME (mt1)) == TYPE_DECL);
+ tree n1 = TYPE_NAME (mt1);
+ tree n2 = TYPE_NAME (mt2) ? TYPE_NAME (mt2) : NULL;
if (TREE_CODE (n1) == TYPE_DECL)
n1 = DECL_NAME (n1);
@@ -1023,8 +1033,6 @@ warn_types_mismatch (tree t1, tree t2, location_t loc1, location_t loc2)
"the incompatible type defined in another translation unit");
return;
}
- tree mt1 = TYPE_MAIN_VARIANT (t1);
- tree mt2 = TYPE_MAIN_VARIANT (t2);
/* If types have mangled ODR names and they are different, it is most
informative to output those.
This also covers types defined in different namespaces. */
diff --git a/gcc/ipa-fnsummary.c b/gcc/ipa-fnsummary.c
index 122a369abb4..9d160266589 100644
--- a/gcc/ipa-fnsummary.c
+++ b/gcc/ipa-fnsummary.c
@@ -227,7 +227,7 @@ ipa_fn_summary::account_size_time (int size, sreal time,
{
e->size += size;
e->time += time;
- gcc_checking_assert (e->time >= -1);
+ /* FIXME: PR bootstrap/92653 gcc_checking_assert (e->time >= -1); */
/* Tolerate small roundoff issues. */
if (e->time < 0)
e->time = 0;
@@ -913,6 +913,9 @@ dump_ipa_call_summary (FILE *f, int indent, struct cgraph_node *node,
? "inlined" : cgraph_inline_failed_string (edge-> inline_failed),
indent, "", edge->sreal_frequency ().to_double ());
+ if (cross_module_call_p (edge))
+ fprintf (f, " cross module");
+
if (es)
fprintf (f, " loop depth:%2i size:%2i time: %2i",
es->loop_depth, es->call_stmt_size, es->call_stmt_time);
diff --git a/gcc/ipa-fnsummary.h b/gcc/ipa-fnsummary.h
index 21ecd54293f..e43003212a8 100644
--- a/gcc/ipa-fnsummary.h
+++ b/gcc/ipa-fnsummary.h
@@ -375,4 +375,21 @@ void ipa_fnsummary_c_finalize (void);
HOST_WIDE_INT ipa_get_stack_frame_offset (struct cgraph_node *node);
void ipa_remove_from_growth_caches (struct cgraph_edge *edge);
+/* Return true if EDGE is a cross module call. */
+
+static inline bool
+cross_module_call_p (struct cgraph_edge *edge)
+{
+ /* Here we do not want to walk to alias target becuase ICF may create
+ cross-unit aliases. */
+ if (edge->caller->unit_id == edge->callee->unit_id)
+ return false;
+ /* If the call is to a (former) comdat function or s symbol with mutiple
+ extern inline definitions then treat is as in-module call. */
+ if (edge->callee->merged_extern_inline || edge->callee->merged_comdat
+ || DECL_COMDAT (edge->callee->decl))
+ return false;
+ return true;
+}
+
#endif /* GCC_IPA_FNSUMMARY_H */
diff --git a/gcc/ipa-icf.c b/gcc/ipa-icf.c
index 20e92e12bab..bec7cbc7201 100644
--- a/gcc/ipa-icf.c
+++ b/gcc/ipa-icf.c
@@ -3151,8 +3151,7 @@ sem_item_optimizer::dump_cong_classes (void)
"class: %u)\n", (unsigned long) m_classes.elements (),
m_items.length (), m_items.length () - single_element_classes);
fprintf (dump_file,
- "Class size histogram [num of members]: number of classe number "
- "of classess\n");
+ "Class size histogram [number of members]: number of classes\n");
for (unsigned int i = 0; i <= max_index; i++)
if (histogram[i])
fprintf (dump_file, "%6u: %6u\n", i, histogram[i]);
diff --git a/gcc/ipa-inline-analysis.c b/gcc/ipa-inline-analysis.c
index ae8e5db3d9c..75c6399d35d 100644
--- a/gcc/ipa-inline-analysis.c
+++ b/gcc/ipa-inline-analysis.c
@@ -163,9 +163,7 @@ simple_edge_hints (struct cgraph_edge *edge)
if (to_scc_no && to_scc_no == callee_scc_no && !edge->recursive_p ())
hints |= INLINE_HINT_same_scc;
- if (callee->lto_file_data && edge->caller->lto_file_data
- && edge->caller->lto_file_data != callee->lto_file_data
- && !callee->merged_comdat && !callee->icf_merged)
+ if (cross_module_call_p (edge))
hints |= INLINE_HINT_cross_module;
return hints;
diff --git a/gcc/ipa-inline-transform.c b/gcc/ipa-inline-transform.c
index e7ec7f911e1..6ec843a23b7 100644
--- a/gcc/ipa-inline-transform.c
+++ b/gcc/ipa-inline-transform.c
@@ -681,6 +681,31 @@ inline_transform (struct cgraph_node *node)
if (preserve_function_body_p (node))
save_inline_function_body (node);
+ profile_count num = node->count;
+ profile_count den = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
+ bool scale = num.initialized_p () && !(num == den);
+ if (scale)
+ {
+ profile_count::adjust_for_ipa_scaling (&num, &den);
+ if (dump_file)
+ {
+ fprintf (dump_file, "Applying count scale ");
+ num.dump (dump_file);
+ fprintf (dump_file, "/");
+ den.dump (dump_file);
+ fprintf (dump_file, "\n");
+ }
+
+ basic_block bb;
+ cfun->cfg->count_max = profile_count::uninitialized ();
+ FOR_ALL_BB_FN (bb, cfun)
+ {
+ bb->count = bb->count.apply_scale (num, den);
+ cfun->cfg->count_max = cfun->cfg->count_max.max (bb->count);
+ }
+ ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = node->count;
+ }
+
for (e = node->callees; e; e = next)
{
if (!e->inline_failed)
@@ -693,32 +718,8 @@ inline_transform (struct cgraph_node *node)
timevar_push (TV_INTEGRATION);
if (node->callees && (opt_for_fn (node->decl, optimize) || has_inline))
{
- profile_count num = node->count;
- profile_count den = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
- bool scale = num.initialized_p () && !(num == den);
- if (scale)
- {
- profile_count::adjust_for_ipa_scaling (&num, &den);
- if (dump_file)
- {
- fprintf (dump_file, "Applying count scale ");
- num.dump (dump_file);
- fprintf (dump_file, "/");
- den.dump (dump_file);
- fprintf (dump_file, "\n");
- }
-
- basic_block bb;
- cfun->cfg->count_max = profile_count::uninitialized ();
- FOR_ALL_BB_FN (bb, cfun)
- {
- bb->count = bb->count.apply_scale (num, den);
- cfun->cfg->count_max = cfun->cfg->count_max.max (bb->count);
- }
- ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = node->count;
- }
todo = optimize_inline_calls (current_function_decl);
- }
+ }
timevar_pop (TV_INTEGRATION);
cfun->always_inline_functions_inlined = true;
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 08612e79eb0..0f87c476dde 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -701,10 +701,8 @@ want_early_inline_function_p (struct cgraph_edge *e)
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, e->call_stmt,
" will not early inline: %C->%C, "
- "growth %i exceeds --param early-inlining-insns%s\n",
- e->caller, callee, growth,
- opt_for_fn (e->caller->decl, optimize) >= 3
- ? "" : "-O2");
+ "growth %i exceeds --param early-inlining-insns\n",
+ e->caller, callee, growth);
want_inline = false;
}
else if ((n = num_calls (callee)) != 0
@@ -713,11 +711,9 @@ want_early_inline_function_p (struct cgraph_edge *e)
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, e->call_stmt,
" will not early inline: %C->%C, "
- "growth %i exceeds --param early-inlining-insns%s "
+ "growth %i exceeds --param early-inlining-insns "
"divided by number of calls\n",
- e->caller, callee, growth,
- opt_for_fn (e->caller->decl, optimize) >= 3
- ? "" : "-O2");
+ e->caller, callee, growth);
want_inline = false;
}
}
@@ -861,12 +857,9 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report)
- ipa_call_summaries->get (e)->call_stmt_size
> inline_insns_single (e->caller, true))
{
- if (opt_for_fn (e->caller->decl, optimize) >= 3)
- e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl)
- ? CIF_MAX_INLINE_INSNS_SINGLE_LIMIT
- : CIF_MAX_INLINE_INSNS_AUTO_LIMIT);
- else
- e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
+ e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl)
+ ? CIF_MAX_INLINE_INSNS_SINGLE_LIMIT
+ : CIF_MAX_INLINE_INSNS_AUTO_LIMIT);
want_inline = false;
}
else
@@ -1729,7 +1722,7 @@ recursive_inlining (struct cgraph_edge *edge,
/* Given whole compilation unit estimate of INSNS, compute how large we can
allow the unit to grow. */
-static int
+static int64_t
compute_max_insns (cgraph_node *node, int insns)
{
int max_insns = insns;
@@ -1984,9 +1977,8 @@ inline_small_functions (void)
if (dump_file)
fprintf (dump_file, "Enqueueing calls in %s.\n", node->dump_name ());
- for (edge = node->callees; edge; edge = next)
+ for (edge = node->callees; edge; edge = edge->next_callee)
{
- next = edge->next_callee;
if (edge->inline_failed
&& !edge->aux
&& can_inline_edge_p (edge, true)
@@ -2264,11 +2256,12 @@ inline_small_functions (void)
dump_printf_loc (MSG_OPTIMIZED_LOCATIONS, edge->call_stmt,
" Inlined %C into %C which now has time %f and "
- "size %i, net change of %s.\n",
+ "size %i, net change of %s%s.\n",
edge->callee, edge->caller,
s->time.to_double (),
ipa_size_summaries->get (edge->caller)->size,
- buf_net_change);
+ buf_net_change,
+ cross_module_call_p (edge) ? " (cross module)":"");
}
if (min_size > overall_size)
{
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index e9d6a5e8305..1958e1ee9cc 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -497,6 +497,8 @@ public:
unsigned node_dead : 1;
/* Node is involved in a recursion, potentionally indirect. */
unsigned node_within_scc : 1;
+ /* Node contains only direct recursion. */
+ unsigned node_is_self_scc : 1;
/* Node is calling a private function called only once. */
unsigned node_calling_single_call : 1;
/* False when there is something makes versioning impossible. */
diff --git a/gcc/ipa-utils.c b/gcc/ipa-utils.c
index 2830d41026a..fdbecdb7b35 100644
--- a/gcc/ipa-utils.c
+++ b/gcc/ipa-utils.c
@@ -398,6 +398,7 @@ ipa_merge_profiles (struct cgraph_node *dst,
tree oldsrcdecl = src->decl;
struct function *srccfun, *dstcfun;
bool match = true;
+ bool copy_counts = false;
if (!src->definition
|| !dst->definition)
@@ -429,10 +430,26 @@ ipa_merge_profiles (struct cgraph_node *dst,
}
profile_count orig_count = dst->count;
- if (dst->count.initialized_p () && dst->count.ipa () == dst->count)
- dst->count += src->count.ipa ();
- else
- dst->count = src->count.ipa ();
+ /* Either sum the profiles if both are IPA and not global0, or
+ pick more informative one (that is nonzero IPA if other is
+ uninitialized, guessed or global0). */
+
+ if ((dst->count.ipa ().nonzero_p ()
+ || src->count.ipa ().nonzero_p ())
+ && dst->count.ipa ().initialized_p ()
+ && src->count.ipa ().initialized_p ())
+ dst->count = dst->count.ipa () + src->count.ipa ();
+ else if (dst->count.ipa ().initialized_p ())
+ ;
+ else if (src->count.ipa ().initialized_p ())
+ {
+ copy_counts = true;
+ dst->count = src->count.ipa ();
+ }
+
+ /* If no updating needed return early. */
+ if (dst->count == orig_count)
+ return;
/* First handle functions with no gimple body. */
if (dst->thunk.thunk_p || dst->alias
@@ -544,6 +561,16 @@ ipa_merge_profiles (struct cgraph_node *dst,
struct cgraph_edge *e, *e2;
basic_block srcbb, dstbb;
+ /* Function and global profile may be out of sync. First scale it same
+ way as fixup_cfg would. */
+ profile_count srcnum = src->count;
+ profile_count srcden = ENTRY_BLOCK_PTR_FOR_FN (srccfun)->count;
+ bool srcscale = srcnum.initialized_p () && !(srcnum == srcden);
+ profile_count dstnum = orig_count;
+ profile_count dstden = ENTRY_BLOCK_PTR_FOR_FN (dstcfun)->count;
+ bool dstscale = !copy_counts
+ && dstnum.initialized_p () && !(dstnum == dstden);
+
/* TODO: merge also statement histograms. */
FOR_ALL_BB_FN (srcbb, srccfun)
{
@@ -551,15 +578,15 @@ ipa_merge_profiles (struct cgraph_node *dst,
dstbb = BASIC_BLOCK_FOR_FN (dstcfun, srcbb->index);
- /* Either sum the profiles if both are IPA and not global0, or
- pick more informative one (that is nonzero IPA if other is
- uninitialized, guessed or global0). */
- if (!dstbb->count.ipa ().initialized_p ()
- || (dstbb->count.ipa () == profile_count::zero ()
- && (srcbb->count.ipa ().initialized_p ()
- && !(srcbb->count.ipa () == profile_count::zero ()))))
+ profile_count srccount = srcbb->count;
+ if (srcscale)
+ srccount = srccount.apply_scale (srcnum, srcden);
+ if (dstscale)
+ dstbb->count = dstbb->count.apply_scale (dstnum, dstden);
+
+ if (copy_counts)
{
- dstbb->count = srcbb->count;
+ dstbb->count = srccount;
for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
{
edge srce = EDGE_SUCC (srcbb, i);
@@ -568,18 +595,21 @@ ipa_merge_profiles (struct cgraph_node *dst,
dste->probability = srce->probability;
}
}
- else if (srcbb->count.ipa ().initialized_p ()
- && !(srcbb->count.ipa () == profile_count::zero ()))
+ else
{
for (i = 0; i < EDGE_COUNT (srcbb->succs); i++)
{
edge srce = EDGE_SUCC (srcbb, i);
edge dste = EDGE_SUCC (dstbb, i);
dste->probability =
- dste->probability * dstbb->count.probability_in (dstbb->count + srcbb->count)
- + srce->probability * srcbb->count.probability_in (dstbb->count + srcbb->count);
+ dste->probability * dstbb->count.ipa ().probability_in
+ (dstbb->count.ipa ()
+ + srccount.ipa ())
+ + srce->probability * srcbb->count.ipa ().probability_in
+ (dstbb->count.ipa ()
+ + srccount.ipa ());
}
- dstbb->count += srcbb->count;
+ dstbb->count = dstbb->count.ipa () + srccount.ipa ();
}
}
push_cfun (dstcfun);
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog
index 8eb6a7f5df8..6e8e09330a1 100644
--- a/gcc/jit/ChangeLog
+++ b/gcc/jit/ChangeLog
@@ -1,3 +1,8 @@
+2019-11-29 Julian Brown <julian@codesourcery.com>
+
+ * jit-builtins.c (BT_DFLOAT32_PTR, BT_DFLOAT64_PTR, BT_DFLOAT128_PTR):
+ Remove commented-out cases.
+
2019-11-20 David Malcolm <dmalcolm@redhat.com>
PR jit/92483
diff --git a/gcc/jit/jit-builtins.c b/gcc/jit/jit-builtins.c
index 850329c7b36..93d48c64c40 100644
--- a/gcc/jit/jit-builtins.c
+++ b/gcc/jit/jit-builtins.c
@@ -434,9 +434,6 @@ builtins_manager::make_primitive_type (enum jit_builtin_type type_id)
// case BT_DFLOAT32:
// case BT_DFLOAT64:
// case BT_DFLOAT128:
- // case BT_DFLOAT32_PTR:
- // case BT_DFLOAT64_PTR:
- // case BT_DFLOAT128_PTR:
// case BT_VALIST_REF:
// case BT_VALIST_ARG:
// case BT_I1:
diff --git a/gcc/lra.c b/gcc/lra.c
index ec20aed4492..42b58714d41 100644
--- a/gcc/lra.c
+++ b/gcc/lra.c
@@ -2473,7 +2473,7 @@ lra (FILE *f)
But don't remove dead insns or change global live
info as we can undo inheritance transformations after
inheritance pseudo assigning. */
- lra_create_live_ranges (true, false);
+ lra_create_live_ranges (true, !lra_simple_p);
live_p = true;
/* If we don't spill non-reload and non-inheritance
pseudos, there is no sense to run memory-memory move
@@ -2514,6 +2514,11 @@ lra (FILE *f)
}
}
while (fails_p);
+ if (! live_p) {
+ /* We need the correct reg notes for work of constraint sub-pass. */
+ lra_create_live_ranges (true, true);
+ live_p = true;
+ }
}
/* Don't clear optional reloads bitmap until all constraints are
satisfied as we need to differ them from regular reloads. */
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index a4a70e7848c..b5221cd41f9 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -526,6 +526,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
bp_pack_value (&bp, node->alias, 1);
bp_pack_value (&bp, node->transparent_alias, 1);
bp_pack_value (&bp, node->weakref, 1);
+ bp_pack_value (&bp, node->symver, 1);
bp_pack_value (&bp, node->frequency, 2);
bp_pack_value (&bp, node->only_called_at_startup, 1);
bp_pack_value (&bp, node->only_called_at_exit, 1);
@@ -533,6 +534,8 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
bp_pack_value (&bp, node->calls_comdat_local, 1);
bp_pack_value (&bp, node->icf_merged, 1);
bp_pack_value (&bp, node->nonfreeing_fn, 1);
+ bp_pack_value (&bp, node->merged_comdat, 1);
+ bp_pack_value (&bp, node->merged_extern_inline, 1);
bp_pack_value (&bp, node->thunk.thunk_p, 1);
bp_pack_value (&bp, node->parallelized_function, 1);
bp_pack_enum (&bp, ld_plugin_symbol_resolution,
@@ -559,6 +562,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
streamer_write_uhwi_stream (ob->main_stream, node->thunk.indirect_offset);
}
streamer_write_hwi_stream (ob->main_stream, node->profile_id);
+ streamer_write_hwi_stream (ob->main_stream, node->unit_id);
if (DECL_STATIC_CONSTRUCTOR (node->decl))
streamer_write_hwi_stream (ob->main_stream, node->get_init_priority ());
if (DECL_STATIC_DESTRUCTOR (node->decl))
@@ -606,6 +610,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
bp_pack_value (&bp, node->alias, 1);
bp_pack_value (&bp, node->transparent_alias, 1);
bp_pack_value (&bp, node->weakref, 1);
+ bp_pack_value (&bp, node->symver, 1);
bp_pack_value (&bp, node->analyzed && (!boundary_p || node->alias), 1);
gcc_assert (node->definition || !node->analyzed);
/* Constant pool initializers can be de-unified into individual ltrans units.
@@ -1170,6 +1175,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->alias = bp_unpack_value (bp, 1);
node->transparent_alias = bp_unpack_value (bp, 1);
node->weakref = bp_unpack_value (bp, 1);
+ node->symver = bp_unpack_value (bp, 1);
node->frequency = (enum node_frequency)bp_unpack_value (bp, 2);
node->only_called_at_startup = bp_unpack_value (bp, 1);
node->only_called_at_exit = bp_unpack_value (bp, 1);
@@ -1177,6 +1183,8 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->calls_comdat_local = bp_unpack_value (bp, 1);
node->icf_merged = bp_unpack_value (bp, 1);
node->nonfreeing_fn = bp_unpack_value (bp, 1);
+ node->merged_comdat = bp_unpack_value (bp, 1);
+ node->merged_extern_inline = bp_unpack_value (bp, 1);
node->thunk.thunk_p = bp_unpack_value (bp, 1);
node->parallelized_function = bp_unpack_value (bp, 1);
node->resolution = bp_unpack_enum (bp, ld_plugin_symbol_resolution,
@@ -1310,6 +1318,9 @@ input_node (struct lto_file_decl_data *file_data,
if (node->alias && !node->analyzed && node->weakref)
node->alias_target = get_alias_symbol (node->decl);
node->profile_id = streamer_read_hwi (ib);
+ node->unit_id = streamer_read_hwi (ib) + file_data->unit_base;
+ if (symtab->max_unit < node->unit_id)
+ symtab->max_unit = node->unit_id;
if (DECL_STATIC_CONSTRUCTOR (node->decl))
node->set_init_priority (streamer_read_hwi (ib));
if (DECL_STATIC_DESTRUCTOR (node->decl))
@@ -1363,6 +1374,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
node->alias = bp_unpack_value (&bp, 1);
node->transparent_alias = bp_unpack_value (&bp, 1);
node->weakref = bp_unpack_value (&bp, 1);
+ node->symver = bp_unpack_value (&bp, 1);
node->analyzed = bp_unpack_value (&bp, 1);
node->used_from_other_partition = bp_unpack_value (&bp, 1);
node->in_other_partition = bp_unpack_value (&bp, 1);
@@ -1502,6 +1514,7 @@ input_cgraph_1 (struct lto_file_decl_data *file_data,
tag = streamer_read_enum (ib, LTO_symtab_tags, LTO_symtab_last_tag);
file_data->order_base = symtab->order;
+ file_data->unit_base = symtab->max_unit + 1;
while (tag)
{
if (tag == LTO_symtab_edge)
diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h
index 7b712808bd5..dba195d3884 100644
--- a/gcc/lto-streamer.h
+++ b/gcc/lto-streamer.h
@@ -626,6 +626,8 @@ struct GTY(()) lto_file_decl_data
lto_section lto_section_header;
int order_base;
+
+ int unit_base;
};
typedef struct lto_file_decl_data *lto_file_decl_data_ptr;
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index cdf6964fbb7..df9ddfa3432 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,9 @@
+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/91985
+ * lto-lang.c (lto_type_for_mode): Handle decimal floating-point
+ types being NULL_TREE.
+
2019-11-22 Jan Hubicka <jh@suse.cz>
* lto.c (lto_wpa_write_files): Call memory_block_pool::trim.
diff --git a/gcc/lto/lto-lang.c b/gcc/lto/lto-lang.c
index 3e37c37fa46..f8278676d5d 100644
--- a/gcc/lto/lto-lang.c
+++ b/gcc/lto/lto-lang.c
@@ -1051,11 +1051,14 @@ lto_type_for_mode (machine_mode mode, int unsigned_p)
return build_vector_type_for_mode (inner_type, mode);
}
- if (mode == TYPE_MODE (dfloat32_type_node))
+ if (dfloat32_type_node != NULL_TREE
+ && mode == TYPE_MODE (dfloat32_type_node))
return dfloat32_type_node;
- if (mode == TYPE_MODE (dfloat64_type_node))
+ if (dfloat64_type_node != NULL_TREE
+ && mode == TYPE_MODE (dfloat64_type_node))
return dfloat64_type_node;
- if (mode == TYPE_MODE (dfloat128_type_node))
+ if (dfloat128_type_node != NULL_TREE
+ && mode == TYPE_MODE (dfloat128_type_node))
return dfloat128_type_node;
if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
index 2fd5b1e8f49..8dfae627782 100644
--- a/gcc/lto/lto-symtab.c
+++ b/gcc/lto/lto-symtab.c
@@ -69,6 +69,13 @@ lto_cgraph_replace_node (struct cgraph_node *node,
if (node->definition && prevailing_node->definition
&& DECL_COMDAT (node->decl) && DECL_COMDAT (prevailing_node->decl))
prevailing_node->merged_comdat = true;
+ else if ((node->definition || node->body_removed)
+ && DECL_DECLARED_INLINE_P (node->decl)
+ && DECL_EXTERNAL (node->decl)
+ && prevailing_node->definition)
+ prevailing_node->merged_extern_inline = true;
+ prevailing_node->merged_comdat |= node->merged_comdat;
+ prevailing_node->merged_extern_inline |= node->merged_extern_inline;
/* Redirect all incoming edges. */
compatible_p
diff --git a/gcc/match.pd b/gcc/match.pd
index eabd01fc115..14f6a9d5078 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -2480,18 +2480,42 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(plusminus @0 (mult:c@3 @0 @2))
(if ((!ANY_INTEGRAL_TYPE_P (type)
|| TYPE_OVERFLOW_WRAPS (type)
+ /* For @0 + @0*@2 this transformation would introduce UB
+ (where there was none before) for @0 in [-1,0] and @2 max.
+ For @0 - @0*@2 this transformation would introduce UB
+ for @0 0 and @2 in [min,min+1] or @0 -1 and @2 min+1. */
|| (INTEGRAL_TYPE_P (type)
- && tree_expr_nonzero_p (@0)
- && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
+ && ((tree_expr_nonzero_p (@0)
+ && expr_not_equal_to (@0,
+ wi::minus_one (TYPE_PRECISION (type))))
+ || (plusminus == PLUS_EXPR
+ ? expr_not_equal_to (@2,
+ wi::max_value (TYPE_PRECISION (type), SIGNED))
+ /* Let's ignore the @0 -1 and @2 min case. */
+ : (expr_not_equal_to (@2,
+ wi::min_value (TYPE_PRECISION (type), SIGNED))
+ && expr_not_equal_to (@2,
+ wi::min_value (TYPE_PRECISION (type), SIGNED)
+ + 1))))))
&& single_use (@3))
(mult (plusminus { build_one_cst (type); } @2) @0)))
(simplify
(plusminus (mult:c@3 @0 @2) @0)
(if ((!ANY_INTEGRAL_TYPE_P (type)
|| TYPE_OVERFLOW_WRAPS (type)
+ /* For @0*@2 + @0 this transformation would introduce UB
+ (where there was none before) for @0 in [-1,0] and @2 max.
+ For @0*@2 - @0 this transformation would introduce UB
+ for @0 0 and @2 min. */
|| (INTEGRAL_TYPE_P (type)
- && tree_expr_nonzero_p (@0)
- && expr_not_equal_to (@0, wi::minus_one (TYPE_PRECISION (type)))))
+ && ((tree_expr_nonzero_p (@0)
+ && (plusminus == MINUS_EXPR
+ || expr_not_equal_to (@0,
+ wi::minus_one (TYPE_PRECISION (type)))))
+ || expr_not_equal_to (@2,
+ (plusminus == PLUS_EXPR
+ ? wi::max_value (TYPE_PRECISION (type), SIGNED)
+ : wi::min_value (TYPE_PRECISION (type), SIGNED))))))
&& single_use (@3))
(mult (plusminus @2 { build_one_cst (type); }) @0))))))
diff --git a/gcc/optabs-tree.c b/gcc/optabs-tree.c
index 97cc59255e0..a04e4ffd05c 100644
--- a/gcc/optabs-tree.c
+++ b/gcc/optabs-tree.c
@@ -270,20 +270,16 @@ optab_for_tree_code (enum tree_code code, const_tree type,
Convert operations we currently support directly are FIX_TRUNC and FLOAT.
This function checks if these operations are supported
- by the target platform either directly (via vector tree-codes), or via
- target builtins.
+ by the target platform directly (via vector tree-codes).
Output:
- CODE1 is code of vector operation to be used when
- vectorizing the operation, if available.
- - DECL is decl of target builtin functions to be used
- when vectorizing the operation, if available. In this case,
- CODE1 is CALL_EXPR. */
+ vectorizing the operation, if available. */
bool
supportable_convert_operation (enum tree_code code,
tree vectype_out, tree vectype_in,
- tree *decl, enum tree_code *code1)
+ enum tree_code *code1)
{
machine_mode m1,m2;
bool truncp;
@@ -317,15 +313,6 @@ supportable_convert_operation (enum tree_code code,
return true;
}
- /* Now check for builtin. */
- if (targetm.vectorize.builtin_conversion
- && targetm.vectorize.builtin_conversion (code, vectype_out, vectype_in))
- {
- *code1 = CALL_EXPR;
- *decl = targetm.vectorize.builtin_conversion (code, vectype_out,
- vectype_in);
- return true;
- }
return false;
}
diff --git a/gcc/optabs-tree.h b/gcc/optabs-tree.h
index 5e4848997de..dac35014234 100644
--- a/gcc/optabs-tree.h
+++ b/gcc/optabs-tree.h
@@ -36,7 +36,7 @@ enum optab_subtype
the second argument. The third argument distinguishes between the types of
vector shifts and rotates. */
optab optab_for_tree_code (enum tree_code, const_tree, enum optab_subtype);
-bool supportable_convert_operation (enum tree_code, tree, tree, tree *,
+bool supportable_convert_operation (enum tree_code, tree, tree,
enum tree_code *);
bool expand_vec_cmp_expr_p (tree, tree, enum tree_code);
bool expand_vec_cond_expr_p (tree, tree, enum tree_code);
diff --git a/gcc/output.h b/gcc/output.h
index 6cccada4aeb..4ac7d507733 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -167,6 +167,7 @@ extern int decode_reg_name (const char *);
extern int decode_reg_name_and_count (const char *, int *);
extern void do_assemble_alias (tree, tree);
+extern void do_assemble_symver (tree, tree);
extern void default_assemble_visibility (tree, int);
diff --git a/gcc/params.opt b/gcc/params.opt
index 586b539ec5f..d88ae0c468b 100644
--- a/gcc/params.opt
+++ b/gcc/params.opt
@@ -198,6 +198,14 @@ Threshold ipa-cp opportunity evaluation that is still considered beneficial to c
Common Joined UInteger Var(param_ipa_cp_loop_hint_bonus) Init(64) Param
Compile-time bonus IPA-CP assigns to candidates which make loop bounds or strides known.
+-param=ipa-cp-max-recursive-depth=
+Common Joined UInteger Var(param_ipa_cp_max_recursive_depth) Init(8) Param
+Maximum depth of recursive cloning for self-recursive function.
+
+-param=ipa-cp-min-recursive-probability=
+Common Joined UInteger Var(param_ipa_cp_min_recursive_probability) Init(2) Param
+Recursive cloning only when the probability of call being executed exceeds the parameter.
+
-param=ipa-cp-recursion-penalty=
Common Joined UInteger Var(param_ipa_cp_recursion_penalty) Init(40) IntegerRange(0, 100) Param
Percentage penalty the recursive functions will receive when they are evaluated for cloning.
diff --git a/gcc/predict.c b/gcc/predict.c
index 8c66a27d8b6..67f850de17a 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -184,7 +184,7 @@ maybe_hot_count_p (struct function *fun, profile_count count)
/* Code executed at most once is not hot. */
if (count <= MAX (profile_info ? profile_info->runs : 1, 1))
return false;
- return (count.to_gcov_type () >= get_hot_bb_threshold ());
+ return (count >= get_hot_bb_threshold ());
}
/* Return true if basic block BB of function FUN can be CPU intensive
diff --git a/gcc/profile-count.c b/gcc/profile-count.c
index 49467481d47..81a969175d2 100644
--- a/gcc/profile-count.c
+++ b/gcc/profile-count.c
@@ -291,6 +291,7 @@ profile_count::to_cgraph_frequency (profile_count entry_bb_count) const
return 0;
gcc_checking_assert (entry_bb_count.initialized_p ());
uint64_t scale;
+ gcc_checking_assert (compatible_p (entry_bb_count));
if (!safe_scale_64bit (!entry_bb_count.m_val ? m_val + 1 : m_val,
CGRAPH_FREQ_BASE, MAX (1, entry_bb_count.m_val), &scale))
return CGRAPH_FREQ_MAX;
@@ -310,10 +311,25 @@ profile_count::to_sreal_scale (profile_count in, bool *known) const
}
if (known)
*known = true;
+ /* Watch for cases where one count is IPA and other is not. */
+ if (in.ipa ().initialized_p ())
+ {
+ gcc_checking_assert (ipa ().initialized_p ());
+ /* If current count is inter-procedurally 0 and IN is inter-procedurally
+ non-zero, return 0. */
+ if (in.ipa ().nonzero_p ()
+ && !ipa().nonzero_p ())
+ return 0;
+ }
+ else
+ /* We can handle correctly 0 IPA count within locally estimated
+ profile, but otherwise we are lost and this should not happen. */
+ gcc_checking_assert (!ipa ().initialized_p () || !ipa ().nonzero_p ());
if (*this == zero ())
return 0;
if (m_val == in.m_val)
return 1;
+ gcc_checking_assert (compatible_p (in));
if (!in.m_val)
{
@@ -359,6 +375,8 @@ profile_count::adjust_for_ipa_scaling (profile_count *num,
profile_count
profile_count::combine_with_ipa_count (profile_count ipa)
{
+ if (!initialized_p ())
+ return *this;
ipa = ipa.ipa ();
if (ipa.nonzero_p ())
return ipa;
@@ -369,6 +387,23 @@ profile_count::combine_with_ipa_count (profile_count ipa)
return this->global0adjusted ();
}
+/* Sae as profile_count::combine_with_ipa_count but within function with count
+ IPA2. */
+profile_count
+profile_count::combine_with_ipa_count_within (profile_count ipa,
+ profile_count ipa2)
+{
+ profile_count ret;
+ if (!initialized_p ())
+ return *this;
+ if (ipa2.ipa () == ipa2 && ipa.initialized_p ())
+ ret = ipa;
+ else
+ ret = combine_with_ipa_count (ipa);
+ gcc_checking_assert (ret.compatible_p (ipa2));
+ return ret;
+}
+
/* The profiling runtime uses gcov_type, which is usually 64bit integer.
Conversions back and forth are used to read the coverage and get it
into internal representation. */
diff --git a/gcc/profile-count.h b/gcc/profile-count.h
index 3d6e388f7fe..96145d51f2c 100644
--- a/gcc/profile-count.h
+++ b/gcc/profile-count.h
@@ -700,6 +700,7 @@ private:
uint64_t UINT64_BIT_FIELD_ALIGN m_val : n_bits;
#undef UINT64_BIT_FIELD_ALIGN
enum profile_quality m_quality : 3;
+public:
/* Return true if both values can meaningfully appear in single function
body. We have either all counters in function local or global, otherwise
@@ -711,9 +712,18 @@ private:
if (*this == zero ()
|| other == zero ())
return true;
+ /* Do not allow nonzero global profile together with local guesses
+ that are globally0. */
+ if (ipa ().nonzero_p ()
+ && !(other.ipa () == other))
+ return false;
+ if (other.ipa ().nonzero_p ()
+ && !(ipa () == *this))
+ return false;
+
return ipa_p () == other.ipa_p ();
}
-public:
+
/* Used for counters which are expected to be never executed. */
static profile_count zero ()
{
@@ -920,14 +930,14 @@ public:
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (other >= 0);
- return initialized_p () && m_val < (uint64_t) other;
+ return ipa ().initialized_p () && ipa ().m_val < (uint64_t) other;
}
bool operator> (const gcov_type other) const
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (other >= 0);
- return initialized_p () && m_val > (uint64_t) other;
+ return ipa ().initialized_p () && ipa ().m_val > (uint64_t) other;
}
bool operator<= (const profile_count &other) const
@@ -958,14 +968,14 @@ public:
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (other >= 0);
- return initialized_p () && m_val <= (uint64_t) other;
+ return ipa ().initialized_p () && ipa ().m_val <= (uint64_t) other;
}
bool operator>= (const gcov_type other) const
{
gcc_checking_assert (ipa_p ());
gcc_checking_assert (other >= 0);
- return initialized_p () && m_val >= (uint64_t) other;
+ return ipa ().initialized_p () && ipa ().m_val >= (uint64_t) other;
}
/* Return true when value is not zero and can be used for scaling.
@@ -992,6 +1002,14 @@ public:
profile_count max (profile_count other) const
{
+ profile_count val = *this;
+
+ /* Always prefer nonzero IPA counts over local counts. */
+ if (ipa ().nonzero_p () || other.ipa ().nonzero_p ())
+ {
+ val = ipa ();
+ other = other.ipa ();
+ }
if (!initialized_p ())
return other;
if (!other.initialized_p ())
@@ -1001,8 +1019,8 @@ public:
if (other == zero ())
return *this;
gcc_checking_assert (compatible_p (other));
- if (m_val < other.m_val || (m_val == other.m_val
- && m_quality < other.m_quality))
+ if (val.m_val < other.m_val || (m_val == other.m_val
+ && val.m_quality < other.m_quality))
return other;
return *this;
}
@@ -1075,8 +1093,11 @@ public:
ret.m_val = MIN (val, max_count);
ret.m_quality = MIN (MIN (MIN (m_quality, ADJUSTED),
num.m_quality), den.m_quality);
- if (num.ipa_p () && !ret.ipa_p ())
- ret.m_quality = MIN (num.m_quality, GUESSED);
+ /* Be sure that ret is not local if num is global.
+ Also ensure that ret is not global0 when num is global. */
+ if (num.ipa_p ())
+ ret.m_quality = MAX (ret.m_quality,
+ num == num.ipa () ? GUESSED : num.m_quality);
return ret;
}
@@ -1194,6 +1215,10 @@ public:
global0. */
profile_count combine_with_ipa_count (profile_count ipa);
+ /* Same as combine_with_ipa_count but inside function with count IPA2. */
+ profile_count combine_with_ipa_count_within
+ (profile_count ipa, profile_count ipa2);
+
/* The profiling runtime uses gcov_type, which is usually 64bit integer.
Conversions back and forth are used to read the coverage and get it
into internal representation. */
diff --git a/gcc/real.c b/gcc/real.c
index 90067f0087b..134240a6be9 100644
--- a/gcc/real.c
+++ b/gcc/real.c
@@ -2104,7 +2104,7 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str)
/* Nonzero value, possibly overflowing or underflowing. */
mpfr_init2 (m, SIGNIFICAND_BITS);
- inexact = mpfr_strtofr (m, str, NULL, 10, GMP_RNDZ);
+ inexact = mpfr_strtofr (m, str, NULL, 10, MPFR_RNDZ);
/* The result should never be a NaN, and because the rounding is
toward zero should never be an infinity. */
gcc_assert (!mpfr_nan_p (m) && !mpfr_inf_p (m));
@@ -2120,7 +2120,7 @@ real_from_string (REAL_VALUE_TYPE *r, const char *str)
}
else
{
- real_from_mpfr (r, m, NULL_TREE, GMP_RNDZ);
+ real_from_mpfr (r, m, NULL_TREE, MPFR_RNDZ);
/* 1 to 3 bits may have been shifted off (with a sticky bit)
because the hex digits used in real_from_mpfr did not
start with a digit 8 to f, but the exponent bounds above
@@ -2431,9 +2431,9 @@ dconst_e_ptr (void)
{
mpfr_t m;
mpfr_init2 (m, SIGNIFICAND_BITS);
- mpfr_set_ui (m, 1, GMP_RNDN);
- mpfr_exp (m, m, GMP_RNDN);
- real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN);
+ mpfr_set_ui (m, 1, MPFR_RNDN);
+ mpfr_exp (m, m, MPFR_RNDN);
+ real_from_mpfr (&value, m, NULL_TREE, MPFR_RNDN);
mpfr_clear (m);
}
@@ -2474,8 +2474,8 @@ dconst_sqrt2_ptr (void)
{
mpfr_t m;
mpfr_init2 (m, SIGNIFICAND_BITS);
- mpfr_sqrt_ui (m, 2, GMP_RNDN);
- real_from_mpfr (&value, m, NULL_TREE, GMP_RNDN);
+ mpfr_sqrt_ui (m, 2, MPFR_RNDN);
+ real_from_mpfr (&value, m, NULL_TREE, MPFR_RNDN);
mpfr_clear (m);
}
return &value;
@@ -5410,13 +5410,13 @@ build_sinatan_real (REAL_VALUE_TYPE * r, tree type)
mpfr_inits (mpfr_const1, mpfr_c, mpfr_maxval, NULL);
- mpfr_from_real (mpfr_const1, &dconst1, GMP_RNDN);
- mpfr_from_real (mpfr_maxval, &maxval, GMP_RNDN);
+ mpfr_from_real (mpfr_const1, &dconst1, MPFR_RNDN);
+ mpfr_from_real (mpfr_maxval, &maxval, MPFR_RNDN);
- mpfr_sub (mpfr_c, mpfr_maxval, mpfr_const1, GMP_RNDN);
- mpfr_sqrt (mpfr_c, mpfr_c, GMP_RNDZ);
+ mpfr_sub (mpfr_c, mpfr_maxval, mpfr_const1, MPFR_RNDN);
+ mpfr_sqrt (mpfr_c, mpfr_c, MPFR_RNDZ);
- real_from_mpfr (r, mpfr_c, fmt, GMP_RNDZ);
+ real_from_mpfr (r, mpfr_c, fmt, MPFR_RNDZ);
mpfr_clears (mpfr_const1, mpfr_c, mpfr_maxval, NULL);
}
diff --git a/gcc/realmpfr.c b/gcc/realmpfr.c
index 39f9fa1333b..a760ae124c3 100644
--- a/gcc/realmpfr.c
+++ b/gcc/realmpfr.c
@@ -28,7 +28,7 @@
for initializing and clearing the MPFR parameter. */
void
-mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mp_rnd_t rndmode)
+mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mpfr_rnd_t rndmode)
{
/* We use a string as an intermediate type. */
char buf[128];
@@ -59,11 +59,11 @@ mpfr_from_real (mpfr_ptr m, const REAL_VALUE_TYPE *r, mp_rnd_t rndmode)
void
real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, const real_format *format,
- mp_rnd_t rndmode)
+ mpfr_rnd_t rndmode)
{
/* We use a string as an intermediate type. */
char buf[128], *rstr;
- mp_exp_t exp;
+ mpfr_exp_t exp;
/* Take care of Infinity and NaN. */
if (mpfr_inf_p (m))
@@ -105,7 +105,8 @@ real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, const real_format *format,
mode RNDMODE. TYPE is only relevant if M is a NaN. */
void
-real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, tree type, mp_rnd_t rndmode)
+real_from_mpfr (REAL_VALUE_TYPE *r, mpfr_srcptr m, tree type,
+ mpfr_rnd_t rndmode)
{
real_from_mpfr (r, m, type ? REAL_MODE_FORMAT (TYPE_MODE (type)) : NULL,
rndmode);
diff --git a/gcc/realmpfr.h b/gcc/realmpfr.h
index bfea86d2bd9..ebb44fd859d 100644
--- a/gcc/realmpfr.h
+++ b/gcc/realmpfr.h
@@ -27,15 +27,9 @@
/* Convert between MPFR and REAL_VALUE_TYPE. The caller is
responsible for initializing and clearing the MPFR parameter. */
-extern void real_from_mpfr (REAL_VALUE_TYPE *, mpfr_srcptr, tree, mp_rnd_t);
+extern void real_from_mpfr (REAL_VALUE_TYPE *, mpfr_srcptr, tree, mpfr_rnd_t);
extern void real_from_mpfr (REAL_VALUE_TYPE *, mpfr_srcptr,
- const real_format *, mp_rnd_t);
-extern void mpfr_from_real (mpfr_ptr, const REAL_VALUE_TYPE *, mp_rnd_t);
-
-#if (GCC_VERSION >= 3000)
- /* For compatibility with mpfr 2.4 and earlier, we want to only use
- GMP_RND*. */
- #pragma GCC poison MPFR_RNDN MPFR_RNDZ MPFR_RNDU MPFR_RNDD
-#endif
+ const real_format *, mpfr_rnd_t);
+extern void mpfr_from_real (mpfr_ptr, const REAL_VALUE_TYPE *, mpfr_rnd_t);
#endif /* ! GCC_REALGMP_H */
diff --git a/gcc/recog.c b/gcc/recog.c
index 9e9cca7db02..1b76503323a 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -923,23 +923,6 @@ validate_simplify_insn (rtx_insn *insn)
return ((num_changes_pending () > 0) && (apply_change_group () > 0));
}
-/* Return 1 if the insn using CC0 set by INSN does not contain
- any ordered tests applied to the condition codes.
- EQ and NE tests do not count. */
-
-int
-next_insn_tests_no_inequality (rtx_insn *insn)
-{
- rtx_insn *next = next_cc0_user (insn);
-
- /* If there is no next insn, we have to take the conservative choice. */
- if (next == 0)
- return 0;
-
- return (INSN_P (next)
- && ! inequality_comparisons_p (PATTERN (next)));
-}
-
/* Return 1 if OP is a valid general operand for machine mode MODE.
This is either a register reference, a memory reference,
or a constant. In the case of a memory reference, the address
@@ -2757,10 +2740,9 @@ constrain_operands (int strict, alternative_mask alternatives)
/* Before reload, accept what reload can turn
into a mem. */
|| (strict < 0 && CONSTANT_P (op))
- /* Before reload, accept a pseudo,
+ /* Before reload, accept a pseudo or hard register,
since LRA can turn it into a mem. */
- || (strict < 0 && targetm.lra_p () && REG_P (op)
- && REGNO (op) >= FIRST_PSEUDO_REGISTER)
+ || (strict < 0 && targetm.lra_p () && REG_P (op))
/* During reload, accept a pseudo */
|| (reload_in_progress && REG_P (op)
&& REGNO (op) >= FIRST_PSEUDO_REGISTER)))
diff --git a/gcc/recog.h b/gcc/recog.h
index 71d88e3e376..69238cf16a6 100644
--- a/gcc/recog.h
+++ b/gcc/recog.h
@@ -112,7 +112,6 @@ extern void validate_replace_rtx_group (rtx, rtx, rtx_insn *);
extern void validate_replace_src_group (rtx, rtx, rtx_insn *);
extern bool validate_simplify_insn (rtx_insn *insn);
extern int num_changes_pending (void);
-extern int next_insn_tests_no_inequality (rtx_insn *);
extern bool reg_fits_class_p (const_rtx, reg_class_t, int, machine_mode);
extern int offsettable_memref_p (rtx);
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 1369e66a136..be27937f7f9 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -3514,7 +3514,6 @@ extern bool insn_nothrow_p (const_rtx);
extern bool can_nonlocal_goto (const rtx_insn *);
extern void copy_reg_eh_region_note_forward (rtx, rtx_insn *, rtx);
extern void copy_reg_eh_region_note_backward (rtx, rtx_insn *, rtx);
-extern int inequality_comparisons_p (const_rtx);
extern rtx replace_rtx (rtx, rtx, rtx, bool = false);
extern void replace_label (rtx *, rtx, rtx, bool);
extern void replace_label_in_insn (rtx_insn *, rtx_insn *, rtx_insn *, bool);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 720aa093a23..241a35b0e6c 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -3021,64 +3021,6 @@ may_trap_or_fault_p (const_rtx x)
return may_trap_p_1 (x, 1);
}
-/* Return nonzero if X contains a comparison that is not either EQ or NE,
- i.e., an inequality. */
-
-int
-inequality_comparisons_p (const_rtx x)
-{
- const char *fmt;
- int len, i;
- const enum rtx_code code = GET_CODE (x);
-
- switch (code)
- {
- case REG:
- case SCRATCH:
- case PC:
- case CC0:
- CASE_CONST_ANY:
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- return 0;
-
- case LT:
- case LTU:
- case GT:
- case GTU:
- case LE:
- case LEU:
- case GE:
- case GEU:
- return 1;
-
- default:
- break;
- }
-
- len = GET_RTX_LENGTH (code);
- fmt = GET_RTX_FORMAT (code);
-
- for (i = 0; i < len; i++)
- {
- if (fmt[i] == 'e')
- {
- if (inequality_comparisons_p (XEXP (x, i)))
- return 1;
- }
- else if (fmt[i] == 'E')
- {
- int j;
- for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (inequality_comparisons_p (XVECEXP (x, i, j)))
- return 1;
- }
- }
-
- return 0;
-}
-
/* Replace any occurrence of FROM in X with TO. The function does
not enter into CONST_DOUBLE for the replace.
diff --git a/gcc/symtab.c b/gcc/symtab.c
index 3e634e22c86..f4317d02b71 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -848,6 +848,8 @@ symtab_node::dump_base (FILE *f)
fprintf (f, " transparent_alias");
if (weakref)
fprintf (f, " weakref");
+ if (symver)
+ fprintf (f, " symver");
if (cpp_implicit_alias)
fprintf (f, " cpp_implicit_alias");
if (alias_target)
@@ -914,8 +916,10 @@ symtab_node::dump_base (FILE *f)
if (DECL_STATIC_DESTRUCTOR (decl))
fprintf (f, " destructor");
}
+ if (ifunc_resolver)
+ fprintf (f, " ifunc_resolver");
fprintf (f, "\n");
-
+
if (same_comdat_group)
fprintf (f, " Same comdat group as: %s\n",
same_comdat_group->dump_asm_name ());
@@ -1145,6 +1149,11 @@ symtab_node::verify_base (void)
error ("node is transparent_alias but not an alias");
error_found = true;
}
+ if (symver && !alias)
+ {
+ error ("node is symver but not alias");
+ error_found = true;
+ }
if (same_comdat_group)
{
symtab_node *n = same_comdat_group;
@@ -1780,7 +1789,9 @@ symtab_node::resolve_alias (symtab_node *target, bool transparent)
if (target->get_comdat_group ())
alias_alias->add_to_same_comdat_group (target);
}
- if (!alias_alias->transparent_alias || transparent)
+ if ((!alias_alias->transparent_alias
+ && !alias_alias->symver)
+ || transparent)
{
alias_alias->remove_all_references ();
alias_alias->create_reference (target, IPA_REF_ALIAS, NULL);
@@ -1861,6 +1872,13 @@ symtab_node::noninterposable_alias (void)
DECL_STATIC_CONSTRUCTOR (new_decl) = 0;
DECL_STATIC_DESTRUCTOR (new_decl) = 0;
new_node = cgraph_node::create_alias (new_decl, node->decl);
+
+ cgraph_node *new_cnode = dyn_cast <cgraph_node *> (new_node),
+ *cnode = dyn_cast <cgraph_node *> (node);
+
+ new_cnode->unit_id = cnode->unit_id;
+ new_cnode->merged_comdat = cnode->merged_comdat;
+ new_cnode->merged_extern_inline = cnode->merged_extern_inline;
}
else
{
diff --git a/gcc/target.def b/gcc/target.def
index e705c5d14d9..e0e856979a9 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1797,22 +1797,6 @@ return type of the vectorized function shall be of vector type\n\
tree, (tree fndecl, tree vec_type_out, tree vec_type_in),
default_builtin_md_vectorized_function)
-/* Returns a function declaration for a builtin that realizes the
- vector conversion, or NULL_TREE if not available. */
-DEFHOOK
-(builtin_conversion,
- "This hook should return the DECL of a function that implements conversion of the\n\
-input vector of type @var{src_type} to type @var{dest_type}.\n\
-The value of @var{code} is one of the enumerators in @code{enum tree_code} and\n\
-specifies how the conversion is to be applied\n\
-(truncation, rounding, etc.).\n\
-\n\
-If this hook is defined, the autovectorizer will use the\n\
-@code{TARGET_VECTORIZE_BUILTIN_CONVERSION} target hook when vectorizing\n\
-conversion. Otherwise, it will return @code{NULL_TREE}.",
- tree, (unsigned code, tree dest_type, tree src_type),
- default_builtin_vectorized_conversion)
-
/* Cost of different vector/scalar statements in vectorization cost
model. In case of misaligned vector loads and stores the cost depends
on the data type and misalignment value. */
@@ -5303,6 +5287,22 @@ This is currently used only by the C and C++ front ends.",
hook_tree_tree_tree_null)
DEFHOOK
+(verify_type_context,
+ "If defined, this hook returns false if there is a target-specific reason\n\
+why type @var{type} cannot be used in the source language context described\n\
+by @var{context}. When @var{silent_p} is false, the hook also reports an\n\
+error against @var{loc} for invalid uses of @var{type}.\n\
+\n\
+Calls to this hook should be made through the global function\n\
+@code{verify_type_context}, which makes the @var{silent_p} parameter\n\
+default to false and also handles @code{error_mark_node}.\n\
+\n\
+The default implementation always returns true.",
+ bool, (location_t loc, type_context_kind context, const_tree type,
+ bool silent_p),
+ NULL)
+
+DEFHOOK
(can_change_mode_class,
"This hook returns true if it is possible to bitcast values held in\n\
registers of class @var{rclass} from mode @var{from} to mode @var{to}\n\
diff --git a/gcc/target.h b/gcc/target.h
index 2c5b59be851..973d743a371 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -226,6 +226,35 @@ enum omp_device_kind_arch_isa {
will choose the first mode that works. */
const unsigned int VECT_COMPARE_COSTS = 1U << 0;
+/* The contexts in which the use of a type T can be checked by
+ TARGET_VERIFY_TYPE_CONTEXT. */
+enum type_context_kind {
+ /* Directly measuring the size of T. */
+ TCTX_SIZEOF,
+
+ /* Directly measuring the alignment of T. */
+ TCTX_ALIGNOF,
+
+ /* Creating objects of type T with static storage duration. */
+ TCTX_STATIC_STORAGE,
+
+ /* Creating objects of type T with thread-local storage duration. */
+ TCTX_THREAD_STORAGE,
+
+ /* Creating a field of type T. */
+ TCTX_FIELD,
+
+ /* Creating an array with elements of type T. */
+ TCTX_ARRAY_ELEMENT,
+
+ /* Adding to or subtracting from a pointer to T, or computing the
+ difference between two pointers when one of them is a pointer to T. */
+ TCTX_POINTER_ARITH
+};
+
+extern bool verify_type_context (location_t, type_context_kind, const_tree,
+ bool = false);
+
/* The target structure. This holds all the backend hooks. */
#define DEFHOOKPOD(NAME, DOC, TYPE, INIT) TYPE NAME;
#define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) TYPE (* NAME) PARAMS;
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index fd8e43565c3..2d3bcbf3e89 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -688,16 +688,6 @@ default_builtin_md_vectorized_function (tree, tree, tree)
return NULL_TREE;
}
-/* Vectorized conversion. */
-
-tree
-default_builtin_vectorized_conversion (unsigned int code ATTRIBUTE_UNUSED,
- tree dest_type ATTRIBUTE_UNUSED,
- tree src_type ATTRIBUTE_UNUSED)
-{
- return NULL_TREE;
-}
-
/* Default vectorizer cost model values. */
int
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index e041291347b..34987bbcdb3 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -93,8 +93,6 @@ extern const char * default_invalid_within_doloop (const rtx_insn *);
extern tree default_builtin_vectorized_function (unsigned int, tree, tree);
extern tree default_builtin_md_vectorized_function (tree, tree, tree);
-extern tree default_builtin_vectorized_conversion (unsigned int, tree, tree);
-
extern int default_builtin_vectorization_cost (enum vect_cost_for_stmt, tree, int);
extern tree default_builtin_reciprocal (tree);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 4c0553f0ce8..12abe735bbf 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,326 @@
+2019-12-02 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/92712
+ * gcc.dg/tree-ssa/pr92712-1.c: New test.
+ * gcc.dg/tree-ssa/pr92712-2.c: New test.
+ * gcc.dg/tree-ssa/pr92712-3.c: New test.
+ * gfortran.dg/loop_versioning_1.f90: Adjust expected number of
+ likely to be innermost dimension messages.
+ * gfortran.dg/loop_versioning_10.f90: Likewise.
+ * gfortran.dg/loop_versioning_6.f90: Likewise.
+
+2019-12-02 Feng Xue <fxue@os.amperecomputing.com>
+
+ PR ipa/92133
+ * gcc.dg/ipa/ipa-clone-2.c: New test.
+
+2019-12-01 Sandra Loosemore <sandra@codesourcery.com>
+
+ PR target/92499
+
+ * gcc.target/nios2/pr92499-1.c: New.
+ * gcc.target/nios2/pr92499-2.c: New.
+ * gcc.target/nios2/pr92499-3.c: New.
+
+2019-12-02 Luo Xiong Hu <luoxhu@linux.ibm.com>
+
+ testsuite/pr92398
+ * gcc.target/powerpc/pr72804.c: Split the store function to...
+ * gcc.target/powerpc/pr92398.h: ... this one. New.
+ * gcc.target/powerpc/pr92398.p9+.c: New.
+ * gcc.target/powerpc/pr92398.p9-.c: New.
+ * lib/target-supports.exp (check_effective_target_p8): New.
+ (check_effective_target_p9+): New.
+
+2019-11-30 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/acle/general-c/sizeless-1.c: New test.
+ * gcc.target/aarch64/sve/acle/general-c/sizeless-2.c: Likewise.
+
+2019-11-30 Jan Hubicka <hubicka@ucw.cz>
+
+ * g++.dg/lto/inline-crossmodule-1.h: New testcase.
+ * g++.dg/lto/inline-crossmodule-1_0.C: New testcase.
+ * g++.dg/lto/inline-crossmodule-1_1.C: New testcase.
+
+2019-11-30 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/91783
+ * gfortran.dg/dependency_56.f90: New test.
+
+2019-11-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/91003
+ * gfortran.dg/pr91003.f90: New testcase.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/92677
+ * gcc.dg/vect/pr92677.c: New test.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/92596
+ * gcc.dg/vect/bb-slp-pr92596.c: New test.
+ * gcc.dg/vect/bb-slp-43.c: Likewise.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.dg/vect/vect-bool-cmp-2.c: New test.
+ * lib/target-supports.exp (check_effective_target_vect_bool_cmp): New
+ effective target procedure.
+
+2019-11-29 Tobias Burnus <tobias@codesourcery.com>
+
+ * fortran.dg/goacc/common-block-3.f90: Check that unused common-block
+ variables do not get mapped.
+
+2019-11-29 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/92476
+ * g++.dg/lto/pr92476_[01].C: New test.
+
+2019-11-29 Richard Sandiford <richard.sandiford@arm.com>
+
+ PR tree-optimization/92710
+ * gcc.dg/vect/pr92710.c: New test.
+
+2019-11-29 Tobias Burnus <tobias@codesourcery.com>
+
+ PR ipa/84963
+ * gfortran.dg/goacc/pr84963.f90: Use dg-additional-options not
+ dg-options as otherwise -fopenacc is not used.
+
+2019-11-29 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.dg/vect/slp-reduc-3.c: Turn off epilogue-nomask.
+
+2019-11-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92715
+ * gcc.dg/torture/pr92715.c: New testcase.
+
+2019-11-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/60228
+ * g++.dg/gomp/openmp-simd-2.C: Don't expect bodies for
+ DECL_OMP_DECLARE_REDUCTION_P functions.
+
+2019-11-29 Martin Liska <mliska@suse.cz>
+
+ PR lto/91574
+ * g++.dg/lto/pr91574_0.C: New test.
+
+2019-11-29 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92704
+ * gcc.dg/torture/pr92704.c: New testcase.
+
+2019-11-29 Joseph Myers <joseph@codesourcery.com>
+
+ * objc.dg/attributes/gnu2x-attr-syntax-1.m: New test.
+
+2019-11-28 Martin Liska <mliska@suse.cz>
+
+ PR lto/92609
+ * g++.dg/lto/pr92609_0.C: New test.
+ * g++.dg/lto/pr92609_1.C: New test.
+
+2019-11-28 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.target/i386/pr32219-2.c: Adjust scan-assembler entries
+ for revised common default.
+
+2019-11-28 Jerry DeLisle <jvdelisle@gcc.ngu.org>
+
+ PR fortran/90374
+ * gfortran.dg/fmt_zero_width.f90: Update test.
+
+2019-11-28 Martin Jambor <mjambor@suse.cz>
+
+ PR ipa/92697
+ * g++.dg/ipa/pr92697.C: New.
+
+2019-11-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92645
+ * gcc.dg/tree-ssa/inline-12.c: New testcase.
+
+2019-11-28 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92645
+ * gcc.target/i386/pr92645-4.c: New testcase.
+
+2019-11-28 Christophe Lyon <christophe.lyon@linaro.org>
+
+ * gcc.target/arm/asm-flag-4.c: Use -mfloat-abi=softfp.
+
+2019-11-28 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/92691
+ * gcc.dg/tree-ssa/builtin-snprintf-10.c: New test.
+
+ PR c++/92695
+ * g++.dg/warn/inline3.C: New test.
+
+2019-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/92510
+ * gcc.dg/pr92510.c: New test.
+
+2019-11-27 Andrew Sutton <asutton@lock3software.com>
+
+ PR c++/92236
+ * g++.dg/cpp2a/concepts-iconv1.C: Update diagnostics.
+ * g++.dg/cpp2a/concepts-requires5.C: Likewise.
+ * g++.dg/cpp2a/concepts6.C: New test.
+
+2019-11-27 Andrew Sutton <asutton@lock3software.com>
+
+ PR c++/92439
+ * g++.dg/cpp2a/concepts-requires20.C: New.
+
+2019-11-27 Andrew Sutton <asutton@lock3software.com>
+
+ PR c++/88395
+ * g++.dg/cpp2a/concepts-pr88395.C: New.
+ * g++.dg/cpp2a/concepts-recursive-sat1.C: New.
+ * g++.dg/cpp2a/concepts-recursive-sat2.C: New.
+ * g++.dg/cpp2a/concepts-recursive-sat3.C: New.
+
+2019-11-27 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR rtl-optimization/90007
+ * gcc.target/i386/pr90007.c: New test.
+
+2019-11-27 Andrew Sutton <asutton@lock3software.com>
+
+ Emit hard errors for certain satisfaction errors.
+ * g++.dg/concepts/pr84330.C: Update diagnostics.
+ * g++.dg/cpp2a/concepts-requires2.C: Likewise.
+
+2019-11-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92690
+ * gcc.dg/torture/pr92690.c: New testcase.
+ * gcc.dg/tree-ssa/forwprop-35.c: Adjust.
+
+2019-11-27 Jakub Jelinek <jakub@redhat.com>
+
+ PR fortran/91944
+ * gfortran.dg/spread_size_limit_2.f90: New test.
+
+ PR c++/92524
+ * g++.dg/cpp0x/pr92524.C: New test.
+
+2019-11-27 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92645
+ * gcc.target/i386/pr92645-2.c: New testcase.
+ * gcc.target/i386/pr92645-3.c: Likewise.
+
+2019-11-26 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/cpp1z/bool-increment1.C: Test location(s) too.
+ * g++.dg/expr/bitfield3.C: Likewise.
+ * g++.dg/expr/bitfield4.C: Likewise.
+ * g++.dg/expr/bitfield5.C: Likewise.
+ * g++.dg/expr/bitfield6.C: Likewise.
+ * g++.dg/expr/bool1.C: Likewise.
+ * g++.dg/expr/bool2.C: Likewise.
+ * g++.dg/expr/bool3.C: Likewise.
+ * g++.dg/expr/bool4.C: Likewise.
+ * g++.dg/expr/lval3.C: Likewise.
+ * g++.dg/other/error18.C: Likewise.
+ * g++.dg/warn/Wpointer-arith-1.C: Likewise.
+ * g++.old-deja/g++.bugs/900212_01.C: Likewise.
+ * g++.old-deja/g++.bugs/900428_02.C: Likewise.
+ * g++.old-deja/g++.jason/rfg14.C: Likewise.
+ * g++.old-deja/g++.other/overload11.C: Likewise.
+
+2019-11-26 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/92683
+ * gcc.dg/strcmpopt_8.c: New test.
+ * gcc.dg/strcmpopt_9.c: New test.
+
+2019-11-26 Joel Hutton <Joel.Hutton@arm.com>
+
+ PR testsuite/92391
+ * lib/target-supports.exp (check_effective_target_vect_char_add):
+ Use a separate cache entry from vect_int.
+
+2019-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/92648
+ * g++.dg/cpp0x/gen-attrs-71.C: New test.
+
+ PR c++/61414
+ * g++.dg/cpp0x/enum23.C: Remove xfail.
+ * g++.dg/cpp0x/enum28.C: New test.
+
+ PR tree-optimization/92644
+ * g++.dg/opt/pr92644.C: New test.
+
+2019-11-26 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/92645
+ * gcc.target/i386/pr92645.c: New testcase.
+
+2019-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ * gfortran.dg/dec-comparison.f90: Change dg-do from run to compile.
+
+2019-11-25 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/92629
+ * gfortran.dg/pr92629.f90: New testcase.
+
+2019-11-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * g++.dg/diagnostic/base-operand-non-pointer-1.C: New.
+ * g++.dg/pr53055.C: Check location too.
+ * g++.old-deja/g++.bugs/900213_02.C: Likewise.
+ * g++.old-deja/g++.bugs/900215_02.C: Likewise.
+ * g++.old-deja/g++.other/badarrow.C: Likewise.
+ * g++.old-deja/g++.other/deref1.C: Likewise.
+
+ * g++.dg/warn/Wenum-compare.C: Check location too.
+
+ * g++.dg/cpp0x/initlist26.C: Check location too.
+ * g++.dg/cpp0x/initlist28.C: Likewise.
+ * g++.dg/cpp0x/initlist29.C: Likewise.
+ * g++.dg/cpp0x/initlist33.C: Likewise.
+ * g++.dg/expr/string-2.C: Likewise.
+ * g++.dg/other/ptrmem5.C: Likewise.
+ * g++.old-deja/g++.benjamin/14664-1.C: Likewise.
+ * g++.old-deja/g++.benjamin/14664-2.C: Likewise.
+ * g++.old-deja/g++.brendan/init12.C: Likewise.
+ * g++.old-deja/g++.bugs/900324_04.C: Likewise.
+ * g++.old-deja/g++.ext/array1.C: Likewise.
+ * g++.old-deja/g++.jason/rfg17.C: Likewise.
+
+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ PR c/91985
+ * gcc.dg/c2x-no-dfp-1.c, gcc.dg/gnu2x-builtins-no-dfp-1.c: New
+ tests.
+ * gcc.dg/fltconst-pedantic-dfp.c: Expect errors when decimal
+ floating-point not supported.
+
+2019-11-25 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/gnu2x-attrs-1.c: Do not expect message about attributes
+ appertaining to types.
+ * gcc.dg/gnu2x-attrs-2.c: New test.
+ * g++.dg/cpp0x/gen-attrs-1.C, g++.dg/cpp0x/gen-attrs-22.C,
+ g++.dg/cpp0x/gen-attrs-4.C, g++.dg/cpp0x/lambda/lambda-attr1.C:
+ Update expected diagnostics.
+
+2019-11-25 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.dg/torture/fp-int-convert-timode-1.c: Always run if int128.
+
2019-11-25 Eric Botcazou <ebotcazou@adacore.com>
* gnat.dg/addr14.adb: New test.
@@ -24,6 +347,11 @@
PR ipa/91956
* g++.dg/ipa/pr91956.C: New test.
+2019-11-24 Jerry DeLisle <jvdelisle@gcc.ngu.org>
+
+ PR fortran/92100
+ gfortran.dg/streamio_18.f90: New test.
+
2019-11-23 Thomas Koenig <tkoenig@gcc.gnu.org>
Harald Anlauf <anlauf@gmx.de>
@@ -86,9 +414,9 @@
2019-11-22 Jakub Jelinek <jakub@redhat.com>
- Implement P1920R1, Missing feature-test macros 2017-2019.
+ Implement P1902R1, Missing feature-test macros 2017-2019.
* g++.dg/cpp1z/feat-cxx1z.C: Only compile with -std=c++17.
- * g++.dg/cpp2a/feat-cxx2a.C: Adjust for P1920R1 changes.
+ * g++.dg/cpp2a/feat-cxx2a.C: Adjust for P1902R1 changes.
* g++.dg/cpp2a/desig15.C: New test.
* g++.dg/cpp2a/lambda-pack-init3.C: New test.
* g++.dg/cpp2a/lambda-generic6.C: New test.
diff --git a/gcc/testsuite/g++.dg/concepts/pr67595.C b/gcc/testsuite/g++.dg/concepts/pr67595.C
index 7199e0517d4..029ec7a1186 100644
--- a/gcc/testsuite/g++.dg/concepts/pr67595.C
+++ b/gcc/testsuite/g++.dg/concepts/pr67595.C
@@ -9,6 +9,6 @@ template <class X> bool input_iterator{weak_input_iterator<X>}; // { dg-warning
template <class X> bool forward_iterator{input_iterator<X>};
template <class X> bool bidirectional_iterator{forward_iterator<X>};
template <class X>
-concept bool random_access_iterator{bidirectional_iterator<X>};
+concept bool random_access_iterator{bidirectional_iterator<X>}; // { dg-error "constant" }
void fn1(random_access_iterator);
int main() { fn1(0); } // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/concepts/pr84330.C b/gcc/testsuite/g++.dg/concepts/pr84330.C
index 0c2f45602d1..ba035d02555 100644
--- a/gcc/testsuite/g++.dg/concepts/pr84330.C
+++ b/gcc/testsuite/g++.dg/concepts/pr84330.C
@@ -5,7 +5,7 @@
struct A
{
template<typename T>
- requires (sizeof(T) >> 0)
+ requires (sizeof(T) >> 0) // { dg-error "constraint does not have type 'bool'" }
void foo(T);
void bar()
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-4.C b/gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-4.C
new file mode 100644
index 00000000000..4c86d4567ce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-pr92206-4.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+
+template <typename T> struct A { };
+template <typename T, int = sizeof(typename T::type)> using AA = A<T>; // { dg-error "char" }
+template <typename T> using AAA = AA<T>;
+
+template <class T> struct C { };
+template <class T> struct B {
+ C<AAA<T>> a;
+};
+B<char> b; // { dg-message "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum23.C b/gcc/testsuite/g++.dg/cpp0x/enum23.C
index b2378e1b366..53ad990bf93 100644
--- a/gcc/testsuite/g++.dg/cpp0x/enum23.C
+++ b/gcc/testsuite/g++.dg/cpp0x/enum23.C
@@ -5,5 +5,5 @@ enum class MyEnum { A = 1 };
struct MyClass
{
- MyEnum Field1 : 3; // { dg-bogus "warning: 'MyClass::Field1' is too small" "" { xfail *-*-* } }
+ MyEnum Field1 : 3; // { dg-bogus "warning: 'MyClass::Field1' is too small" }
};
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum38.C b/gcc/testsuite/g++.dg/cpp0x/enum38.C
new file mode 100644
index 00000000000..f0dd8a1fc6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum38.C
@@ -0,0 +1,25 @@
+// PR c++/61414
+// { dg-do compile { target c++11 } }
+
+enum C { C0 = -4, C1 = 3 };
+enum D { D0 = 0, D1 = 15 };
+enum class E { E0 = -4, E1 = 3 };
+enum F : unsigned { F0 = 0, F1 = 15 };
+enum __attribute__((__mode__ (__QI__))) G { G0 = -4, G1 = 3 };
+enum __attribute__((__mode__ (__HI__))) H { H0 = 0, H1 = 15 };
+
+struct S
+{
+ C a : 2; // { dg-warning "'S::a' is too small to hold all values of 'enum C'" }
+ C b : 3; // { dg-bogus "'S::b' is too small to hold all values of 'enum C'" }
+ D c : 3; // { dg-warning "'S::c' is too small to hold all values of 'enum D'" }
+ D d : 4; // { dg-bogus "'S::d' is too small to hold all values of 'enum D'" }
+ E e : 2; // { dg-warning "'S::e' is too small to hold all values of 'enum class E'" }
+ E f : 3; // { dg-bogus "'S::f' is too small to hold all values of 'enum class E'" }
+ F g : 3; // { dg-warning "'S::g' is too small to hold all values of 'enum F'" }
+ F h : 4; // { dg-bogus "'S::h' is too small to hold all values of 'enum F'" }
+ G i : 2; // { dg-warning "'S::i' is too small to hold all values of 'enum G'" }
+ G j : 3; // { dg-bogus "'S::j' is too small to hold all values of 'enum G'" }
+ H k : 3; // { dg-warning "'S::k' is too small to hold all values of 'enum H'" }
+ H l : 4; // { dg-bogus "'S::l' is too small to hold all values of 'enum H'" }
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C
index a55698c9383..c2cf912047e 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-1.C
@@ -1,3 +1,3 @@
// { dg-do compile { target c++11 } }
-int **** [[gnu::format(printf, 1, 2)]] foo(const char *, ...); // { dg-warning "ignored" }
+int **** [[gnu::format(printf, 1, 2)]] foo(const char *, ...); // { dg-warning "only applies to function types" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C
index 4c07df995c7..e060c523fe3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-22.C
@@ -3,5 +3,5 @@
void f()
{
- static_cast<float *[[gnu::unused]]>(0); // { dg-warning "ignored" }
+ static_cast<float *[[gnu::unused]]>(0);
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
index 023d8396777..b401c6908e3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-4.C
@@ -21,7 +21,7 @@ void two [[gnu::unused]] (void) {}
[[gnu::unused]]
int
five(void)
-[[noreturn]] // { dg-warning "ignored" }
+[[noreturn]] // { dg-warning "does not apply to types" }
{ return 0; }
[[noreturn]]
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-71.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-71.C
new file mode 100644
index 00000000000..7876a2fba30
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-71.C
@@ -0,0 +1,7 @@
+// PR c++/92648
+// { dg-do compile { target c++11 } }
+
+int a [[gnu::no_such_attribute(![!(!)!]!,;;)]]; // { dg-warning "ignored" }
+int b [[no_such_namespace::nonexisting_attribute(linear(c, d : 2), reduction(*:e), linear(uval (f)))]]; // { dg-warning "ignored" }
+int c [[gnu::nonexisting_attribute()]]; // { dg-warning "ignored" }
+int d [[gnu::another_nonexistent_attr(1,"abcd",g+6)]]; // { dg-warning "ignored" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist26.C b/gcc/testsuite/g++.dg/cpp0x/initlist26.C
index 8fd267f4409..045147c4882 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist26.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist26.C
@@ -6,5 +6,5 @@ void
foo (int i)
{
int a[i];
- a = { }; // { dg-error "assign" }
+ a = { }; // { dg-error "5:assigning to an array from an initializer list" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist28.C b/gcc/testsuite/g++.dg/cpp0x/initlist28.C
index 3bf995ad236..decd36eea7b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist28.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist28.C
@@ -4,5 +4,5 @@
void foo()
{
int a[1];
- throw a = {}; // { dg-error "assign" }
+ throw a = {}; // { dg-error "11:assigning to an array from an initializer list" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist29.C b/gcc/testsuite/g++.dg/cpp0x/initlist29.C
index 9174164aa48..494d6951581 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist29.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist29.C
@@ -5,7 +5,7 @@ class Mesh
{
public:
Mesh(const char*)
- { typele={0}; } // { dg-error "" }
+ { typele={0}; } // { dg-error "11:assigning to an array from an initializer list" }
private:
int typele[7][2];
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist33.C b/gcc/testsuite/g++.dg/cpp0x/initlist33.C
index 9ab4b55d31e..ae7f130ebf0 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist33.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist33.C
@@ -9,5 +9,5 @@ struct base
int main()
{
base ptr_array[1];
- ptr_array = { base() }; // { dg-error "assign" }
+ ptr_array = { base() }; // { dg-error "12:assigning to an array from an initializer list" }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-attr1.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-attr1.C
index 9aa6506d5ed..27321f25554 100644
--- a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-attr1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-attr1.C
@@ -1,3 +1,3 @@
// { dg-do compile { target c++11 } }
-auto l = []() [[noreturn]] {}; // { dg-warning "ignored" }
+auto l = []() [[noreturn]] {}; // { dg-warning "does not apply to types" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr92524.C b/gcc/testsuite/g++.dg/cpp0x/pr92524.C
new file mode 100644
index 00000000000..ffbcd8f9f3a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr92524.C
@@ -0,0 +1,12 @@
+// PR c++/92524
+// { dg-do compile { target c++11 } }
+
+struct A { char a = '*'; };
+struct B { A b[64]; };
+
+void
+foo ()
+{
+ A a;
+ B{a};
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ64.C b/gcc/testsuite/g++.dg/cpp1y/var-templ64.C
new file mode 100644
index 00000000000..4e2b43b1d07
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ64.C
@@ -0,0 +1,14 @@
+// { dg-do compile { target c++14 } }
+
+template <class T> T var = T();
+
+template <class T>
+void f()
+{
+ constexpr T i = var<T>; // { dg-error "19:var" }
+}
+
+int main()
+{
+ f<int>();
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/bool-increment1.C b/gcc/testsuite/g++.dg/cpp1z/bool-increment1.C
index 0355dc879a6..3ef713595f1 100644
--- a/gcc/testsuite/g++.dg/cpp1z/bool-increment1.C
+++ b/gcc/testsuite/g++.dg/cpp1z/bool-increment1.C
@@ -5,10 +5,10 @@ fn (bool b)
{
int r = 0;
- r += b++; // { dg-error "use of an operand of type .bool. in .operator\\+\\+. is forbidden in" }
- r += ++b; // { dg-error "use of an operand of type .bool. in .operator\\+\\+. is forbidden in" }
- r += b--; // { dg-error "use of an operand of type .bool. in .operator--. is forbidden" }
- r += --b; // { dg-error "use of an operand of type .bool. in .operator--. is forbidden" }
+ r += b++; // { dg-error "8:use of an operand of type .bool. in .operator\\+\\+. is forbidden in" }
+ r += ++b; // { dg-error "10:use of an operand of type .bool. in .operator\\+\\+. is forbidden in" }
+ r += b--; // { dg-error "8:use of an operand of type .bool. in .operator--. is forbidden" }
+ r += --b; // { dg-error "10:use of an operand of type .bool. in .operator--. is forbidden" }
return r;
}
diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction46.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction46.C
index 513e16057af..e98573729f3 100644
--- a/gcc/testsuite/g++.dg/cpp1z/class-deduction46.C
+++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction46.C
@@ -3,4 +3,4 @@
template<class S> struct C;
template<> struct C<int> { C(int, int) {} };
-auto k = C{0, 0}; // { dg-error "cannot deduce" }
+auto k = C{0, 0}; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias1.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias1.C
new file mode 100644
index 00000000000..ed47eb38f1b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias1.C
@@ -0,0 +1,27 @@
+// Testcase from P1814R0
+// { dg-do compile { target c++2a } }
+
+template <class T> struct identity { using type = T; };
+template <class T> using identity_t = typename identity<T>::type;
+template <class T> concept Int = __is_same_as (T, int);
+
+template <class T, class U> struct C {
+ C(T, U); // #1 { dg-message "constraint" }
+};
+template<class T, class U>
+C(T, U) -> C<T, identity_t<U>>; // #2 { dg-message "constraint" }
+
+template<class V>
+using A = C<V *, V *>;
+
+template<Int W>
+using B = A<W>;
+
+int i{};
+double d{};
+A a1(&i, &i); // { dg-bogus "" "Deduces A<int>" }
+A a2(i, i); // { dg-error "" "cannot deduce V * from i" }
+A a3(&i, &d); // { dg-error "" } #1: Cannot deduce (V*, V*) from (int *, double *)
+ // #2: Cannot deduce A<V> from C<int *, double *>
+B b1(&i, &i); // { dg-bogus "" "Deduces B<int>" }
+B b2(&d, &d); // { dg-error "" "cannot deduce B<W> from C<double *, double *>" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias2.C b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias2.C
new file mode 100644
index 00000000000..d855f7d11ce
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/class-deduction-alias2.C
@@ -0,0 +1,22 @@
+// Test that a non-template deduction guide that doesn't match the alias is
+// ignored.
+// { dg-do compile { target c++2a } }
+
+template <class T> struct identity { using type = T; };
+template <class T> using identity_t = typename identity<T>::type;
+
+template <class T, class U> struct C {
+ C(T, U); // #1
+};
+
+C(char*, char*) -> C<int,int>; // #3
+
+template<class V>
+using A = C<V *, V *>;
+
+char c;
+A a4 (&c, &c); // ignores #3 because C<int,int> is not an A<V>
+
+static_assert (__is_same_as(decltype(a4),A<char>));
+
+C c2 (&c, &c); // { dg-error "conversion" } deduces with #3
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-alias.C b/gcc/testsuite/g++.dg/cpp2a/concepts-alias.C
index 6b2ab0d8046..862879169fb 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-alias.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-alias.C
@@ -7,12 +7,8 @@ template<typename T>
requires Class<T>
using X = T*;
-// BUG: Alias templates are expanded at the point of use, regardless
-// of whether or not they are dependent. This causes T* to be substituted
-// without acutally checking the constraints. See the declaration of y1
-// below.
template<typename T>
-using Y = X<T>;
+using Y = X<T>; // { dg-error "constraint" }
template<Class T> using Z = T*;
@@ -20,6 +16,5 @@ struct S { };
X<S> x1; // OK
X<int> x2; // { dg-error "template constraint failure" }
-Y<int> y1; // { dg-error "" "" { xfail *-*-* } }
+Y<int> y1; // { dg-message "" }
Z<S> z1; // ok
-
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-alias3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-alias3.C
new file mode 100644
index 00000000000..02e960ad40a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-alias3.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++2a } }
+
+template <typename T> struct A { };
+template <typename T> concept int_type = __is_same_as (T, int);
+template <int_type T> using intA = A<T>;
+
+template <template <typename T> class TT> struct B {
+ TT<char> tt; // { dg-error "" }
+};
+B<intA> b;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-alias4.C b/gcc/testsuite/g++.dg/cpp2a/concepts-alias4.C
new file mode 100644
index 00000000000..d37ce6a51e8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-alias4.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++2a } }
+
+template <typename T> struct A { };
+template <typename T> concept int_type = __is_same_as (T, int);
+template <int_type T> using intA = A<T>;
+
+template <class T> struct B {
+ intA<T> a; // { dg-error "" }
+};
+B<char> b;
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C
index cc2ce7e321d..4d521c30748 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-iconv1.C
@@ -7,16 +7,16 @@ int foo(int x)
{
return x;
}
-
+
template <typename T>
concept C1 = requires (T x) {
- {foo(x)} -> Same<int&>;
+ {foo(x)} -> Same<int&>; // { dg-error "placeholder constraints" }
};
template <typename T>
concept C2 = requires (T x) {
- {foo(x)} -> Same<void>;
+ {foo(x)} -> Same<void>; // { dg-error "placeholder constraints" }
};
-
+
static_assert( C1<int> ); // { dg-error "assert" }
static_assert( C2<int> ); // { dg-error "assert" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C
new file mode 100644
index 00000000000..ad24da9cb47
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr88395.C
@@ -0,0 +1,23 @@
+// { dg-do compile { target c++2a } }
+
+template <class T, class U>
+concept Concept2 = requires (T t, U u)
+{
+ t += u; // { dg-error "template instantiation depth" }
+};
+
+template <class T>
+concept Concept = Concept2 <T, T>;
+
+struct S
+{
+ template <Concept T>
+ constexpr S& operator += (T o);
+};
+
+constexpr S operator * (S a, S b)
+{
+ return a += b;
+}
+
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C
new file mode 100644
index 00000000000..ee83d560cf6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C
@@ -0,0 +1,18 @@
+// { dg-do compile { target c++2a } }
+
+template<int N, typename T>
+concept Foo = requires(T t) { foo<N + 1>(t); }; // { dg-error "template instantiation depth" }
+
+template<int N = 1, typename T = int>
+ requires Foo<N, T>
+int foo(T t)
+{
+ return foo<N + 1>(t);
+}
+
+int main(int, char**)
+{
+ return foo<1>(1);
+}
+
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
new file mode 100644
index 00000000000..d76f12eb209
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat2.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++2a } }
+
+template<typename T>
+concept Fooable = requires(T t) { foo(t); }; // { dg-error "template instantiation depth" }
+
+template<Fooable T>
+void foo(T t) { }
+
+void test()
+{
+ struct S {} s;
+ foo(s);
+}
+
+// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat3.C
new file mode 100644
index 00000000000..b8ca9164792
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat3.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++2a } }
+
+template<typename T>
+concept Fooable = requires(T t) { foo(t); };
+
+template<Fooable T>
+void foo(T t) { }
+
+void test()
+{
+ foo(0); // { dg-error "unsatisfied constraints" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires2.C
index 73cee220567..8643f46a16d 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires2.C
@@ -12,7 +12,7 @@ template<typename T> constexpr fool p1() { return {}; }
template<typename T> constexpr fool p2() { return {}; }
template<typename T>
-concept Bad = p1<T>() && p2<T>();
+concept Bad = p1<T>() && p2<T>(); // { dg-error "does not have type 'bool'" }
template<typename T> requires Bad<T> void bad(T x) { }
@@ -26,14 +26,14 @@ struct X { };
int operator==(X, X) { return 0; }
template<typename T>
-concept C1 = (X());
+concept C1 = (X()); // { dg-error "does not have type 'bool'" }
template<typename T>
-concept C2 = (X() == X());
+concept C2 = (X() == X()); // { dg-error "does not have type 'bool'" }
template<typename T>
requires C1<T>
-void h1(T) { }
+void h1(T) { }
template<typename T>
requires C2<T>
@@ -42,12 +42,12 @@ void h2(T);
void driver_3()
{
h1(0); // { dg-error "" }
- h2(0); // { dg-error "" }
+ h2(0); // { dg-error "" }
}
// req7.C
template<bool B>
-struct boolean_constant
+struct boolean_constant
{
constexpr operator bool() const { return B; }
};
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires20.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires20.C
new file mode 100644
index 00000000000..089db2ba013
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires20.C
@@ -0,0 +1,65 @@
+// { dg-do compile { target c++2a } }
+
+template<typename ...>
+constexpr bool r () { return true; }
+
+template<typename ... Ts>
+ requires r<Ts...>() // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires ++N // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires N++ // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires N == 0 // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires N ? true : false // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires N = 0 // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires N + 1 // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires N - 1 // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires N.x // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires N->x && true // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires N && N
+void f() { }
+
+template<typename T, T N>
+ requires N || N
+void f() { }
+
+template<typename T, T N>
+ requires N || !N // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires N[0] // { dg-error "enclose" }
+void f() { }
+
+template<typename T, T N>
+ requires static_cast<bool>(N) // { dg-error "enclose" }
+void f() { }
+
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C b/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C
index fe37ed48e79..133d29e45a4 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-requires5.C
@@ -33,13 +33,13 @@ int driver_1()
// Test implicit conversion requirements
template<typename T, typename U>
-concept ConvertibleTo = requires(T& t) { {t} -> U&; };
+concept ConvertibleTo = requires(T& t) { {t} -> U&; }; // { dg-error "inaccessible" }
struct B { };
class D : /*private*/ B { };
void driver_2()
{
- static_assert(ConvertibleTo<D, B>()); // { dg-error "cannot be used as a function" }
+ static_assert(ConvertibleTo<D, B>()); // { dg-error "cannot call" }
static_assert(ConvertibleTo<D, B>); // { dg-error "static assertion failed" }
}
diff --git a/gcc/testsuite/g++.dg/cpp2a/explicit11.C b/gcc/testsuite/g++.dg/cpp2a/explicit11.C
index ad1bed5b3f0..2df42cdfec5 100644
--- a/gcc/testsuite/g++.dg/cpp2a/explicit11.C
+++ b/gcc/testsuite/g++.dg/cpp2a/explicit11.C
@@ -9,7 +9,7 @@ struct A {
};
int i;
-A a1 = { i, i }; // { dg-error "deduction|cannot" }
+A a1 = { i, i }; // { dg-error "deduction|cannot|no match" }
A a2{ i, i };
A a3{ 0, i };
A a4 = { 0, i };
diff --git a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
index 753a6ecd0a8..9b6e2f59d2c 100644
--- a/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
+++ b/gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C
@@ -358,8 +358,8 @@
#ifndef __cpp_deduction_guides
# error "__cpp_deduction_guides"
-#elif __cpp_deduction_guides != 201703
-# error "__cpp_deduction_guides != 201703"
+#elif __cpp_deduction_guides != 201907
+# error "__cpp_deduction_guides != 201907"
#endif
#ifndef __cpp_if_constexpr
diff --git a/gcc/testsuite/g++.dg/diagnostic/base-operand-non-pointer-1.C b/gcc/testsuite/g++.dg/diagnostic/base-operand-non-pointer-1.C
new file mode 100644
index 00000000000..26188d1b0ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/diagnostic/base-operand-non-pointer-1.C
@@ -0,0 +1,2 @@
+class C { public: C f(); int get(); };
+int f(C* p) { return p->f()->get(); } // { dg-error "28:base operand of .->. has non-pointer type .C." }
diff --git a/gcc/testsuite/g++.dg/expr/bitfield3.C b/gcc/testsuite/g++.dg/expr/bitfield3.C
index 3f30337c2db..ba4c5fac81d 100644
--- a/gcc/testsuite/g++.dg/expr/bitfield3.C
+++ b/gcc/testsuite/g++.dg/expr/bitfield3.C
@@ -7,6 +7,6 @@ struct S {
S s;
void f() {
- s.x--; // { dg-error "use of an operand of type .bool." }
- --s.x; // { dg-error "use of an operand of type .bool." }
+ s.x--; // { dg-error "5:use of an operand of type .bool." }
+ --s.x; // { dg-error "7:use of an operand of type .bool." }
}
diff --git a/gcc/testsuite/g++.dg/expr/bitfield4.C b/gcc/testsuite/g++.dg/expr/bitfield4.C
index 2b1d1fee945..7b27b724785 100644
--- a/gcc/testsuite/g++.dg/expr/bitfield4.C
+++ b/gcc/testsuite/g++.dg/expr/bitfield4.C
@@ -14,8 +14,8 @@ template <>
void f(bool) {}
int main() {
- f(s.x++); // { dg-warning "deprecated" "" { target { ! c++17 } } }
+ f(s.x++); // { dg-warning "7:use of an operand of type .bool. in .operator\\+\\+. is deprecated" "" { target { ! c++17 } } }
// { dg-error "forbidden" "" { target c++17 } .-1 }
- f(++s.x); // { dg-warning "deprecated" "" { target { ! c++17 } } }
+ f(++s.x); // { dg-warning "9:use of an operand of type .bool. in .operator\\+\\+. is deprecated" "" { target { ! c++17 } } }
// { dg-error "forbidden" "" { target c++17 } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/expr/bitfield5.C b/gcc/testsuite/g++.dg/expr/bitfield5.C
index 1921b193d21..fe7a0770078 100644
--- a/gcc/testsuite/g++.dg/expr/bitfield5.C
+++ b/gcc/testsuite/g++.dg/expr/bitfield5.C
@@ -9,11 +9,11 @@ struct S {
S s;
int main() {
- s.x++; // { dg-warning "deprecated" "" { target { ! c++17 } } }
+ s.x++; // { dg-warning "5:use of an operand of type .bool. in .operator\\+\\+. is deprecated" "" { target { ! c++17 } } }
// { dg-error "forbidden" "" { target c++17 } .-1 }
if (s.x != 1)
return 1;
- ++s.x; // { dg-warning "deprecated" "" { target { ! c++17 } } }
+ ++s.x; // { dg-warning "7:use of an operand of type .bool. in .operator\\+\\+. is deprecated" "" { target { ! c++17 } } }
// { dg-error "forbidden" "" { target c++17 } .-1 }
if (s.x != 1)
return 2;
diff --git a/gcc/testsuite/g++.dg/expr/bitfield6.C b/gcc/testsuite/g++.dg/expr/bitfield6.C
index b417310e2cf..5a778f94983 100644
--- a/gcc/testsuite/g++.dg/expr/bitfield6.C
+++ b/gcc/testsuite/g++.dg/expr/bitfield6.C
@@ -7,6 +7,6 @@ struct S {
S s;
void f() {
- ++s.x = false; // { dg-warning "deprecated" "" { target { ! c++17 } } }
+ ++s.x = false; // { dg-warning "7:use of an operand of type .bool. in .operator\\+\\+. is deprecated" "" { target { ! c++17 } } }
// { dg-error "forbidden" "" { target c++17 } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/expr/bool1.C b/gcc/testsuite/g++.dg/expr/bool1.C
index 7b120e17739..91a7cd8127b 100644
--- a/gcc/testsuite/g++.dg/expr/bool1.C
+++ b/gcc/testsuite/g++.dg/expr/bool1.C
@@ -11,10 +11,10 @@ int main()
my_bool b = false;
int i;
- b++; // { dg-warning "deprecated" "" { target { ! c++17 } } }
- // { dg-error "forbidden" "" { target c++17 } .-1 }
- b++; // { dg-warning "deprecated" "" { target { ! c++17 } } }
- // { dg-error "forbidden" "" { target c++17 } .-1 }
+ b++; // { dg-warning "3:use of an operand of type .bool. in .operator\\+\\+. is deprecated" "" { target { ! c++17 } } }
+ // { dg-error "3:use of an operand of type .bool. in .operator\\+\\+. is forbidden" "" { target c++17 } .-1 }
+ b++; // { dg-warning "3:use of an operand of type .bool. in .operator\\+\\+. is deprecated" "" { target { ! c++17 } } }
+ // { dg-error "3:use of an operand of type .bool. in .operator\\+\\+. is forbidden" "" { target c++17 } .-1 }
i = b;
if (i != 1)
abort ();
diff --git a/gcc/testsuite/g++.dg/expr/bool2.C b/gcc/testsuite/g++.dg/expr/bool2.C
index 39d93c0af9d..662c495d8ce 100644
--- a/gcc/testsuite/g++.dg/expr/bool2.C
+++ b/gcc/testsuite/g++.dg/expr/bool2.C
@@ -7,7 +7,7 @@ typedef bool my_bool;
int main()
{
my_bool b = false;
- b--; // { dg-error "" }
+ b--; // { dg-error "3:use of an operand of type .bool. in .operator\\-\\-. is forbidden" }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/expr/bool3.C b/gcc/testsuite/g++.dg/expr/bool3.C
index f27399cfc8a..311b2f5512d 100644
--- a/gcc/testsuite/g++.dg/expr/bool3.C
+++ b/gcc/testsuite/g++.dg/expr/bool3.C
@@ -11,11 +11,11 @@ int main()
my_bool b = false;
int i;
- b++; // { dg-warning "deprecated" "" { target { ! c++17 } } }
- // { dg-error "forbidden" "" { target c++17 } .-1 }
+ b++; // { dg-warning "3:use of an operand of type .bool. in .operator\\+\\+. is deprecated" "" { target { ! c++17 } } }
+ // { dg-error "3:use of an operand of type .bool. in .operator\\+\\+. is forbidden" "" { target c++17 } .-1 }
// { dg-warning ".volatile.-qualified type is deprecated" "" { target c++2a } .-2 }
- b++; // { dg-warning "deprecated" "" { target { ! c++17 } } }
- // { dg-error "forbidden" "" { target c++17 } .-1 }
+ b++; // { dg-warning "3:use of an operand of type .bool. in .operator\\+\\+. is deprecated" "" { target { ! c++17 } } }
+ // { dg-error "3:use of an operand of type .bool. in .operator\\+\\+. is forbidden" "" { target c++17 } .-1 }
// { dg-warning ".volatile.-qualified type is deprecated" "" { target c++2a } .-2 }
i = b;
if (i != 1)
diff --git a/gcc/testsuite/g++.dg/expr/bool4.C b/gcc/testsuite/g++.dg/expr/bool4.C
index 5891bc311bd..1c43acf61be 100644
--- a/gcc/testsuite/g++.dg/expr/bool4.C
+++ b/gcc/testsuite/g++.dg/expr/bool4.C
@@ -7,7 +7,7 @@ typedef volatile bool my_bool;
int main()
{
my_bool b = false;
- b--; // { dg-error "" }
+ b--; // { dg-error "3:use of an operand of type .bool. in .operator\\-\\-. is forbidden" }
// { dg-warning ".volatile.-qualified type is deprecated" "" { target c++2a } .-1 }
return 0;
}
diff --git a/gcc/testsuite/g++.dg/expr/lval3.C b/gcc/testsuite/g++.dg/expr/lval3.C
index fd79c8c8a39..b4a9e6d7e73 100644
--- a/gcc/testsuite/g++.dg/expr/lval3.C
+++ b/gcc/testsuite/g++.dg/expr/lval3.C
@@ -4,5 +4,5 @@ f()
{
bool i = 0;
i++ = 3; // { dg-error "" }
- // { dg-warning "deprecated" "" { target { ! c++17 } } .-1 }
+ // { dg-warning "3:use of an operand of type .bool. in .operator\\+\\+. is deprecated" "" { target { ! c++17 } } .-1 }
}
diff --git a/gcc/testsuite/g++.dg/expr/string-2.C b/gcc/testsuite/g++.dg/expr/string-2.C
index 224fd61e086..07357db7683 100644
--- a/gcc/testsuite/g++.dg/expr/string-2.C
+++ b/gcc/testsuite/g++.dg/expr/string-2.C
@@ -3,7 +3,7 @@
char a[1];
-int foo(a = "") // { dg-error "invalid array assignment" }
+int foo(a = "") // { dg-error "11:invalid array assignment" }
{
return 0;
}
diff --git a/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C b/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C
index e31c1ebecf9..e66806845b7 100644
--- a/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C
+++ b/gcc/testsuite/g++.dg/gomp/openmp-simd-2.C
@@ -36,8 +36,6 @@ void bar(int n, float *a, float *b)
a[i] = b[i];
}
-/* { dg-final { scan-tree-dump-times "Function void omp declare reduction operator\\+" 1 "original" } } */
-/* { dg-final { scan-tree-dump-times "Function void omp declare reduction foo" 2 "original" } } */
/* { dg-final { scan-tree-dump-times "pragma omp simd reduction\\(u\\) reduction\\(t\\) reduction\\(\\+:s\\) aligned\\(a:32\\)" 1 "original" } } */
/* { dg-final { scan-tree-dump-times "pragma omp simd safelen\\(64\\)" 1 "original" } } */
/* { dg-final { scan-tree-dump-not "omp parallel" "original" } } */
diff --git a/gcc/testsuite/g++.dg/ipa/pr92697.C b/gcc/testsuite/g++.dg/ipa/pr92697.C
new file mode 100644
index 00000000000..8958bd0dcf2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr92697.C
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-require-ifunc "" } */
+/* { dg-options "-O2 -fdump-ipa-sra" } */
+
+extern int have_avx2;
+extern int have_ssse3;
+
+namespace NTL
+{
+
+ static void randomstream_impl_init_base ()
+ {
+ __builtin_printf ("Frob1\n");
+ }
+
+ static void // __attribute__ ((target ("ssse3")))
+ randomstream_impl_init_ssse3 ()
+ {
+ __builtin_printf ("Frob2\n");
+ }
+
+ static void
+ //__attribute__ ((target ("avx2,fma,avx,pclmul,ssse3")))
+ randomstream_impl_init_avx2 ()
+ {
+ __builtin_printf ("Frob3\n");
+ }
+
+ extern "C"
+ {
+ static void (*resolve_randomstream_impl_init (void)) ()
+ {
+ if (have_avx2)
+ return &randomstream_impl_init_avx2;
+ if (have_ssse3)
+ return &randomstream_impl_init_ssse3;
+ return &randomstream_impl_init_base;
+ }
+ }
+ static void
+ __attribute__ ((ifunc ("resolve_" "randomstream_impl_init")))
+ randomstream_impl_init ();
+ void foo ()
+ {
+ randomstream_impl_init ();
+ }
+
+}
+
+
+/* { dg-final { scan-ipa-dump-not "Created new node" "sra" } } */
diff --git a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1.h b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1.h
new file mode 100644
index 00000000000..ce345532a68
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1.h
@@ -0,0 +1,15 @@
+struct a
+{
+ int ret1 ()
+ {
+ return 1;
+ }
+ int key ();
+};
+struct b
+{
+ int ret2 ()
+ {
+ return 2;
+ }
+};
diff --git a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C
new file mode 100644
index 00000000000..a1712187010
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_0.C
@@ -0,0 +1,11 @@
+// { dg-lto-do link }
+/* { dg-lto-options { "-O2 -fno-early-inlining -flto -fdump-ipa-inline" } } */
+#include "inline-crossmodule-1.h"
+int a::key ()
+{
+ return 0;
+}
+/* { dg-final { scan-wpa-ipa-times "Inlined ret1" 1 "inlined" } } */
+/* { dg-final { scan-wpa-ipa-times "Inlined ret2" 1 "inlined" } } */
+/* { dg-final { scan-wpa-ipa-times "Inlined key\[^\\n\]*(cross module)" 1 "inlined" } } */
+/* { dg-final { scan-wpa-ipa-times "(cross module)" 1 "inlined" } } */
diff --git a/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_1.C b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_1.C
new file mode 100644
index 00000000000..72e4b9beedd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/inline-crossmodule-1_1.C
@@ -0,0 +1,8 @@
+#include "inline-crossmodule-1.h"
+int
+main()
+{
+ struct a a;
+ struct b b;
+ return a.key () + a.ret1 () + b.ret2() - 3;
+}
diff --git a/gcc/testsuite/g++.dg/lto/pr91574_0.C b/gcc/testsuite/g++.dg/lto/pr91574_0.C
new file mode 100644
index 00000000000..346a8015c98
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr91574_0.C
@@ -0,0 +1,23 @@
+// PR lto/91574
+// { dg-lto-do link }
+// { dg-lto-options { { -fPIC -flto -O2 } } }
+// { dg-require-effective-target shared }
+// { dg-require-effective-target fpic }
+// { dg-extra-ld-options "-shared" }
+
+class A
+{
+public:
+ virtual ~A ();
+ A (A &);
+ virtual unsigned m_fn1 () const;
+};
+class B : A
+{
+ unsigned m_fn1 () const;
+};
+void
+fn1 (B p1)
+{
+ B a[]{p1, p1};
+}
diff --git a/gcc/testsuite/g++.dg/lto/pr92476_0.C b/gcc/testsuite/g++.dg/lto/pr92476_0.C
new file mode 100644
index 00000000000..5bbc9236f4d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr92476_0.C
@@ -0,0 +1,20 @@
+// { dg-lto-do link }
+// { dg-lto-options { { -O0 -flto -shared -fPIC -fvisibility=hidden } } }
+// { dg-require-effective-target fpic }
+// { dg-require-effective-target shared }
+// { dg-extra-ld-options "-shared" }
+
+namespace Passenger {
+namespace Json {
+class Value {};
+} // namespace Json
+namespace ConfigKit {
+class Translator {};
+} // namespace ConfigKit
+namespace LoggingKit {
+void initialize(const Json::Value & = Json::Value(),
+ const ConfigKit::Translator & = ConfigKit::Translator());
+void init_module() { initialize(); }
+} // namespace LoggingKit
+} // namespace Passenger
+
diff --git a/gcc/testsuite/g++.dg/lto/pr92476_1.C b/gcc/testsuite/g++.dg/lto/pr92476_1.C
new file mode 100644
index 00000000000..cd29613b808
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr92476_1.C
@@ -0,0 +1,13 @@
+// { dg-options { -O2 -flto -shared -fPIC -fvisibility=hidden } }
+
+namespace Passenger {
+namespace Json {
+class Value;
+}
+namespace ConfigKit {
+class Translator;
+}
+namespace LoggingKit {
+void initialize(const Json::Value &, const ConfigKit::Translator &) {}
+} // namespace LoggingKit
+} // namespace Passenger
diff --git a/gcc/testsuite/g++.dg/lto/pr92609_0.C b/gcc/testsuite/g++.dg/lto/pr92609_0.C
new file mode 100644
index 00000000000..3cce1811d1e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr92609_0.C
@@ -0,0 +1,88 @@
+// PR lto/92609
+// { dg-lto-do link }
+// { dg-lto-options { { -fPIC -flto } } }
+// { dg-require-effective-target shared }
+// { dg-require-effective-target fpic }
+// { dg-extra-ld-options "-shared" }
+
+namespace std {
+inline namespace __cxx11 {}
+template < typename _Default > struct __detector { using type = _Default; };
+template < typename _Default, template < typename > class >
+using __detected_or = __detector< _Default >;
+template < typename _Default, template < typename > class _Op >
+using __detected_or_t = typename __detected_or< _Default, _Op >::type;
+template < typename > class allocator;
+template < class > struct char_traits;
+namespace __cxx11 {
+template < typename _CharT, typename = char_traits< _CharT >,
+ typename = allocator< _CharT > >
+class basic_string;
+}
+struct __allocator_traits_base {
+ template < typename _Tp > using __pointer = typename _Tp::pointer;
+};
+struct allocator_traits : __allocator_traits_base {
+ using pointer = __detected_or_t< char *, __pointer >;
+};
+} // std
+struct rebind {
+ typedef std::allocator_traits other;
+};
+namespace std {
+namespace __cxx11 {
+template < typename, typename, typename > class basic_string {
+ struct _Alloc_hider {
+ rebind::other::pointer _M_p;
+ } _M_dataplus;
+ unsigned long _M_string_length;
+ enum { _S_local_capacity = 15 };
+ union {
+ char _M_local_buf[_S_local_capacity + 1];
+ unsigned long _M_allocated_capacity;
+ };
+};
+} // __cxx11
+template < typename _Tp > class __uniq_ptr_impl {
+ template < typename _Up > struct _Ptr { using type = _Up *; };
+
+public:
+ using pointer = typename _Ptr< _Tp >::type;
+};
+template < typename _Tp > class unique_ptr {
+public:
+ using pointer = typename __uniq_ptr_impl< _Tp >::pointer;
+ unique_ptr(pointer);
+};
+} // std
+class wxRefCounter;
+class wxObject {
+ virtual wxRefCounter CreateRefData();
+ wxRefCounter *m_refData;
+};
+class wxGDIObject : wxObject {};
+class wxFontBase : wxGDIObject {};
+class wxFont : wxFontBase {};
+class VisualTool {
+protected:
+ VisualTool(int *, int *);
+};
+class OpenGLText;
+class VisualToolCross : VisualTool {
+ std::unique_ptr< OpenGLText > gl_text;
+ VisualToolCross();
+};
+class OpenGLText { // { dg-lto-warning "7: type 'struct OpenGLText' violates the C\\+\\+ One Definition Rule" }
+ float r, g, b, a;
+ int fontSize;
+ bool fontBold;
+ bool fontItalics;
+ std::basic_string< char > fontFace;
+ wxFont font;
+ int glyphs;
+};
+int VisualToolCross_parent;
+int VisualToolCross_context;
+VisualToolCross::VisualToolCross()
+ : VisualTool(&VisualToolCross_parent, &VisualToolCross_context),
+ gl_text(0) {}
diff --git a/gcc/testsuite/g++.dg/lto/pr92609_1.C b/gcc/testsuite/g++.dg/lto/pr92609_1.C
new file mode 100644
index 00000000000..4c65a6a4600
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr92609_1.C
@@ -0,0 +1,58 @@
+namespace std {
+inline namespace __cxx11 {}
+template < typename _Default > struct __detector { using type = _Default; };
+template < typename _Default, template < typename > class >
+using __detected_or = __detector< _Default >;
+template < typename _Default, template < typename > class _Op >
+using __detected_or_t = typename __detected_or< _Default, _Op >::type;
+template < typename > class allocator;
+template < class > struct char_traits;
+namespace __cxx11 {
+template < typename _CharT, typename = char_traits< _CharT >,
+ typename = allocator< _CharT > >
+class basic_string;
+}
+struct __allocator_traits_base {
+ template < typename _Tp > using __pointer = typename _Tp::pointer;
+};
+struct allocator_traits : __allocator_traits_base {
+ using pointer = __detected_or_t< char *, __pointer >;
+};
+namespace __cxx11 {
+template < typename, typename, typename > class basic_string {
+ struct _Alloc_hider {
+ allocator_traits::pointer _M_p;
+ } _M_dataplus;
+ unsigned long _M_string_length;
+ enum { _S_local_capacity = 15 };
+ union {
+ char _M_local_buf[_S_local_capacity + 1];
+ unsigned long _M_allocated_capacity;
+ };
+};
+} // __cxx11
+} // std
+class wxRefCounter;
+class wxObject {
+ virtual int GetClassInfo();
+ wxRefCounter *m_refData;
+};
+class wxGDIObject : wxObject {};
+class wxFontBase : wxGDIObject {};
+class wxFont : wxFontBase {};
+template < class > class map {};
+namespace {
+struct OpenGLTextGlyph;
+}
+typedef map< OpenGLTextGlyph > glyphMap;
+class OpenGLText {
+ float r, g, b, a;
+ int fontSize;
+ bool fontBold;
+ bool fontItalics;
+ std::basic_string< char > fontFace;
+ wxFont font;
+ glyphMap glyphs;
+ OpenGLText();
+};
+OpenGLText::OpenGLText() {}
diff --git a/gcc/testsuite/g++.dg/opt/pr92644.C b/gcc/testsuite/g++.dg/opt/pr92644.C
new file mode 100644
index 00000000000..2f8a86f1fdb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr92644.C
@@ -0,0 +1,6 @@
+// PR tree-optimization/92644
+// { dg-do compile { target c++14 } }
+// { dg-options "-O2 -fno-early-inlining" }
+
+inline auto foo () { return nullptr; }
+int bar () { return foo () ? 1 : 0; }
diff --git a/gcc/testsuite/g++.dg/other/error18.C b/gcc/testsuite/g++.dg/other/error18.C
index 05ddf116675..c613e9afd0d 100644
--- a/gcc/testsuite/g++.dg/other/error18.C
+++ b/gcc/testsuite/g++.dg/other/error18.C
@@ -7,5 +7,5 @@ struct A
void f(A a)
{
- a.b--; // { dg-error "use of an operand of type .bool." }
+ a.b--; // { dg-error "5:use of an operand of type .bool." }
}
diff --git a/gcc/testsuite/g++.dg/other/ptrmem5.C b/gcc/testsuite/g++.dg/other/ptrmem5.C
index 75a78b2f17b..2faf6cd2b7e 100644
--- a/gcc/testsuite/g++.dg/other/ptrmem5.C
+++ b/gcc/testsuite/g++.dg/other/ptrmem5.C
@@ -8,5 +8,5 @@ struct a
int main()
{
int a::*n[8];
- n = &a::x; // { dg-error "int \\(a::\\*\\)" }
+ n = &a::x; // { dg-error "5:incompatible types in assignment of .int \\(a::\\*\\)" }
}
diff --git a/gcc/testsuite/g++.dg/pr53055.C b/gcc/testsuite/g++.dg/pr53055.C
index 787af9d156f..dbe90a3be58 100644
--- a/gcc/testsuite/g++.dg/pr53055.C
+++ b/gcc/testsuite/g++.dg/pr53055.C
@@ -2,4 +2,4 @@
// { dg-do compile }
struct A A :: * p ;
-int i = p ->* p ; // { dg-error "" }
+int i = p ->* p ; // { dg-error "11:left hand operand" }
diff --git a/gcc/testsuite/g++.dg/warn/Wenum-compare.C b/gcc/testsuite/g++.dg/warn/Wenum-compare.C
index f60080039fb..af7c483a238 100644
--- a/gcc/testsuite/g++.dg/warn/Wenum-compare.C
+++ b/gcc/testsuite/g++.dg/warn/Wenum-compare.C
@@ -6,5 +6,5 @@ enum E2 { b };
int foo (E1 e1, E2 e2)
{
- return e1 == e2; /* { dg-warning "comparison between" } */
+ return e1 == e2; /* { dg-warning "13:comparison between" } */
}
diff --git a/gcc/testsuite/g++.dg/warn/Wpointer-arith-1.C b/gcc/testsuite/g++.dg/warn/Wpointer-arith-1.C
index a4aa6960897..1e031f9d732 100644
--- a/gcc/testsuite/g++.dg/warn/Wpointer-arith-1.C
+++ b/gcc/testsuite/g++.dg/warn/Wpointer-arith-1.C
@@ -4,10 +4,10 @@
int main()
{
void *pv = 0;
- pv++; // { dg-warning "forbids incrementing a pointer" }
+ pv++; // { dg-warning "3:ISO C\\+\\+ forbids incrementing a pointer" }
typedef void (*pft) ();
pft pf = 0;
- pf++; // { dg-warning "forbids incrementing a pointer" }
+ pf++; // { dg-warning "3:ISO C\\+\\+ forbids incrementing a pointer" }
}
diff --git a/gcc/testsuite/g++.dg/warn/inline3.C b/gcc/testsuite/g++.dg/warn/inline3.C
new file mode 100644
index 00000000000..0d4dc8ff268
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/inline3.C
@@ -0,0 +1,20 @@
+struct S {
+ inline virtual void foo () = 0; // { dg-bogus "used but never defined" }
+#if __cplusplus > 201703L
+ constexpr virtual void bar () = 0; // { dg-bogus "used but never defined" "" { target c++2a } }
+#else
+ inline virtual void bar () = 0; // { dg-bogus "used but never defined" "" { target c++17_down } }
+#endif
+ S () {}
+};
+struct T : public S {
+ inline virtual void foo () {}
+#if __cplusplus > 201703L
+ constexpr virtual void bar () {}
+#else
+ inline virtual void bar () {}
+#endif
+ T () {}
+};
+T t;
+void foo (S *s) { s->foo (); s->bar (); }
diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/14664-1.C b/gcc/testsuite/g++.old-deja/g++.benjamin/14664-1.C
index 9a6e644433c..966507c4b86 100644
--- a/gcc/testsuite/g++.old-deja/g++.benjamin/14664-1.C
+++ b/gcc/testsuite/g++.old-deja/g++.benjamin/14664-1.C
@@ -8,7 +8,7 @@ void bar()
{
//-g++: incompatible types in assignment of 'const char[]' to 'char[]'
//-edg: expression must be a modifiable lvalue
- foo = "0123456789012345678901234"; // { dg-error "" } // ERROR -
+ foo = "0123456789012345678901234"; // { dg-error "7:invalid array assignment" } // ERROR -
}
diff --git a/gcc/testsuite/g++.old-deja/g++.benjamin/14664-2.C b/gcc/testsuite/g++.old-deja/g++.benjamin/14664-2.C
index 364f30c4b27..3c9591f7733 100644
--- a/gcc/testsuite/g++.old-deja/g++.benjamin/14664-2.C
+++ b/gcc/testsuite/g++.old-deja/g++.benjamin/14664-2.C
@@ -7,7 +7,7 @@ char foo[26];
void bar()
{
- foo = "0123456789012345678901234"; // { dg-error "array" }
+ foo = "0123456789012345678901234"; // { dg-error "7:invalid array assignment" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/init12.C b/gcc/testsuite/g++.old-deja/g++.brendan/init12.C
index 2e3578b1a04..d8889c0abfe 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/init12.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/init12.C
@@ -5,5 +5,5 @@ char * bob();
int main()
{
char a[1][2];
- a[0] = bob();// { dg-error "" } .*
+ a[0] = bob();// { dg-error "10:incompatible types in assignment" } .*
}
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900212_01.C b/gcc/testsuite/g++.old-deja/g++.bugs/900212_01.C
index 8c3349f9424..9e61c1fdfcd 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900212_01.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900212_01.C
@@ -23,17 +23,17 @@ void global_function_0 ()
{
p0 = p1 + 3; // { dg-error "" }
p0 = p1 - 3; // { dg-error "" }
- p1++; /* { dg-error "" } caught by g++ */
- ++p1; /* { dg-error "" } caught by g++ */
- p1--; /* { dg-error "" } caught by g++ */
- --p1; /* { dg-error "" } caught by g++ */
+ p1++; /* { dg-error "3:no post-increment" } caught by g++ */
+ ++p1; /* { dg-error "5:no pre-increment" } caught by g++ */
+ p1--; /* { dg-error "3:no post-decrement" } caught by g++ */
+ --p1; /* { dg-error "5:no pre-decrement" } caught by g++ */
fp0 = fp1 + 3; // { dg-error "" }
fp0 = fp1 - 3; // { dg-error "" }
- fp1++; /* { dg-error "" } */
- ++fp1; /* { dg-error "" } */
- fp1--; /* { dg-error "" } */
- --fp1; /* { dg-error "" } */
+ fp1++; /* { dg-error "3:no post-increment" } */
+ ++fp1; /* { dg-error "5:no pre-increment" } */
+ fp1--; /* { dg-error "3:no post-decrement" } */
+ --fp1; /* { dg-error "5:no pre-decrement" } */
}
int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900213_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900213_02.C
index 9b9ae994de9..63ba605dbdd 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900213_02.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900213_02.C
@@ -16,7 +16,7 @@ int struct0::*dmp;
void global_function_0 ()
{
- i = *dmp; // { dg-error "invalid use of unary '\\\*' on pointer to member" } causes abort
+ i = *dmp; // { dg-error "7:invalid use of unary '\\\*' on pointer to member" } causes abort
}
int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900215_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900215_02.C
index 3309c886384..89bada320da 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900215_02.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900215_02.C
@@ -41,8 +41,8 @@ void struct0::function_member ()
i = (this->*fmp) (); // perfectly legal - for both cfront and g++
i = this->*dmp; // perfectly legal - for both cfront and g++
- i = (*fmp) (); // { dg-error "invalid use of unary '\\\*' on pointer to member" }
- i = *dmp; // { dg-error "invalid use of unary '\\\*' on pointer to member" }
+ i = (*fmp) (); // { dg-error "8:invalid use of unary '\\\*' on pointer to member" }
+ i = *dmp; // { dg-error "7:invalid use of unary '\\\*' on pointer to member" }
}
int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900324_04.C b/gcc/testsuite/g++.old-deja/g++.bugs/900324_04.C
index 1d671d156e5..70c2fbe232a 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900324_04.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900324_04.C
@@ -20,7 +20,7 @@ int_array ia2;
void function_0 ()
{
- ia1 = ia2; // { dg-error "" } gnu extension
+ ia1 = ia2; // { dg-error "7:invalid array assignment" } gnu extension
}
int main () { return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.bugs/900428_02.C b/gcc/testsuite/g++.old-deja/g++.bugs/900428_02.C
index 4846a8113cc..be4e43a2826 100644
--- a/gcc/testsuite/g++.old-deja/g++.bugs/900428_02.C
+++ b/gcc/testsuite/g++.old-deja/g++.bugs/900428_02.C
@@ -15,13 +15,13 @@ void (*fp) ();
void test ()
{
- vp++; /* { dg-error "" } */
- ++vp; /* { dg-error "" } */
- vp--; /* { dg-error "" } */
- --vp; /* { dg-error "" } */
+ vp++; /* { dg-error "3:ISO C\\+\\+ forbids incrementing" } */
+ ++vp; /* { dg-error "5:ISO C\\+\\+ forbids incrementing" } */
+ vp--; /* { dg-error "3:ISO C\\+\\+ forbids decrementing" } */
+ --vp; /* { dg-error "5:ISO C\\+\\+ forbids decrementing" } */
- fp++; /* { dg-error "" } */
- ++fp; /* { dg-error "" } */
- fp--; /* { dg-error "" } */
- --fp; /* { dg-error "" } */
+ fp++; /* { dg-error "3:ISO C\\+\\+ forbids incrementing" } */
+ ++fp; /* { dg-error "5:ISO C\\+\\+ forbids incrementing" } */
+ fp--; /* { dg-error "3:ISO C\\+\\+ forbids decrementing" } */
+ --fp; /* { dg-error "5:ISO C\\+\\+ forbids decrementing" } */
}
diff --git a/gcc/testsuite/g++.old-deja/g++.ext/array1.C b/gcc/testsuite/g++.old-deja/g++.ext/array1.C
index a297c73b8b8..8dfeed62875 100644
--- a/gcc/testsuite/g++.old-deja/g++.ext/array1.C
+++ b/gcc/testsuite/g++.old-deja/g++.ext/array1.C
@@ -19,5 +19,5 @@ void
ccBgaInspection::reinspect (unsigned long diag_flags)
{
ct2d_rigid physTdev;
- _dev2phys = physTdev; // { dg-error "" }
+ _dev2phys = physTdev; // { dg-error "13:incompatible types in assignment" }
}
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/rfg14.C b/gcc/testsuite/g++.old-deja/g++.jason/rfg14.C
index 85a346afecc..4bc0990f33d 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/rfg14.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/rfg14.C
@@ -8,9 +8,9 @@ int (*fp)();
void
test ()
{
- vp++; /* { dg-error "" } incrementing void * */
- ap++; /* { dg-error "" } incrementing ptr to incomplete type */
- sp++; /* { dg-error "" } incrementing ptr to incomplete type */
- up++; /* { dg-error "" } incrementing ptr to incomplete type */
- fp++; /* { dg-error "" } incrementing ptr to function */
+ vp++; /* { dg-error "5:ISO C\\+\\+ forbids incrementing" } incrementing void * */
+ ap++; /* { dg-error "5:cannot increment" } incrementing ptr to incomplete type */
+ sp++; /* { dg-error "5:cannot increment" } incrementing ptr to incomplete type */
+ up++; /* { dg-error "5:cannot increment" } incrementing ptr to incomplete type */
+ fp++; /* { dg-error "5:ISO C\\+\\+ forbids incrementing" } incrementing ptr to function */
}
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/rfg17.C b/gcc/testsuite/g++.old-deja/g++.jason/rfg17.C
index a138f9ad908..415141bf8a7 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/rfg17.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/rfg17.C
@@ -12,5 +12,5 @@ void
test ()
{
b1 = b2; /* OK */
- a1 = a2; /* { dg-error "" } array assignment */
+ a1 = a2; /* { dg-error "6:invalid array assignment" } array assignment */
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/badarrow.C b/gcc/testsuite/g++.old-deja/g++.other/badarrow.C
index 6e7578d1db9..2bcc3eb1394 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/badarrow.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/badarrow.C
@@ -6,5 +6,5 @@ struct S {
void f()
{
- s->i = 3; // { dg-error "" } base operand
+ s->i = 3; // { dg-error "4:base operand of .->. has non-pointer type .S." } base operand
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/deref1.C b/gcc/testsuite/g++.old-deja/g++.other/deref1.C
index 1b32c8c5695..88c640326c0 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/deref1.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/deref1.C
@@ -7,8 +7,8 @@
void fn (void *vp, volatile void *vvp)
{
- *vp; // { dg-error "" } not a pointer to object
- *vvp; // { dg-error "" } not a pointer to object
- &*vp; // { dg-error "" } not a pointer to object
- &*vvp; // { dg-error "" } not a pointer to object
+ *vp; // { dg-error "3:.void\\*. is not a pointer-to-object type" } not a pointer to object
+ *vvp; // { dg-error "3:.volatile void\\*. is not a pointer-to-object type" } not a pointer to object
+ &*vp; // { dg-error "4:.void\\*. is not a pointer-to-object type" } not a pointer to object
+ &*vvp; // { dg-error "4:.volatile void\\*. is not a pointer-to-object type" } not a pointer to object
}
diff --git a/gcc/testsuite/g++.old-deja/g++.other/overload11.C b/gcc/testsuite/g++.old-deja/g++.other/overload11.C
index 9b5b44bd32d..c191b339f31 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/overload11.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/overload11.C
@@ -38,8 +38,8 @@ int main (int argc, char **argv)
// 13.3.1.1 indicates that the following are errors -- the primary expression
// is not the name of a function.
- (0, ovl) (1); // { dg-error "" } not suitable for overload resolution
- (0, &ovl) (1); // { dg-error "" } not suitable for overload resolution
+ (0, ovl) (1); // { dg-error "7:no context" } not suitable for overload resolution
+ (0, &ovl) (1); // { dg-error "7:no context" } not suitable for overload resolution
(argc ? ovl : ovl) (1); // { dg-error "" } not suitable for overload resolution
(argc ? &ovl : &ovl) (1); // { dg-error "" } not suitable for overload resolution
@@ -52,15 +52,15 @@ int main (int argc, char **argv)
ptr = (ovl); // ok
ptr = (&ovl); // ok
- ptr = (0, ovl); // ok { dg-error "no context" }
- ptr = (0, &ovl); // ok { dg-error "no context" }
+ ptr = (0, ovl); // ok { dg-error "13:no context" }
+ ptr = (0, &ovl); // ok { dg-error "13:no context" }
ptr = (argc ? ovl : ovl); // ok { dg-error "no context" }
ptr = (argc ? &ovl : &ovl);// ok { dg-error "no context" }
vptr = (ovl); // { dg-error "" } no matching candidates
vptr = (&ovl); // { dg-error "" } no matching candidates
- vptr = (0, ovl); // { dg-error "" } no matching candidates
- vptr = (0, &ovl); // { dg-error "" } no matching candidates
+ vptr = (0, ovl); // { dg-error "14:no context" } no matching candidates
+ vptr = (0, &ovl); // { dg-error "14:no context" } no matching candidates
vptr = (argc ? ovl : ovl); // { dg-error "" } no matching candidates
vptr = (argc ? &ovl : &ovl);// { dg-error "" } no matching candidates
@@ -81,11 +81,11 @@ int main (int argc, char **argv)
static_cast<void>(ovl); // { dg-error "" } not suitable for overload
static_cast<void>(&ovl); // { dg-error "" } not suitable for overload
((void)1, f); // { dg-warning "" "" { xfail *-*-* } } not a call
- ((void)1, ovl); // { dg-error "" } not suitable for overload
- ((void)1, &ovl); // { dg-error "" } not suitable for overload
+ ((void)1, ovl); // { dg-error "13:no context" } not suitable for overload
+ ((void)1, &ovl); // { dg-error "13:no context" } not suitable for overload
(void)((void)1, f); // ok
- (void)((void)1, ovl); // { dg-error "" } not suitable for overload
- (void)((void)1, &ovl); // { dg-error "" } not suitable for overload
+ (void)((void)1, ovl); // { dg-error "19:no context" } not suitable for overload
+ (void)((void)1, &ovl); // { dg-error "19:no context" } not suitable for overload
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/c2x-no-dfp-1.c b/gcc/testsuite/gcc.dg/c2x-no-dfp-1.c
new file mode 100644
index 00000000000..2cfbb6cad26
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c2x-no-dfp-1.c
@@ -0,0 +1,12 @@
+/* Test DFP types and constants rejected if no DFP support. Bug
+ 91985. */
+/* { dg-do compile { target { ! dfp } } } */
+/* { dg-options "-std=c2x" } */
+
+_Decimal32 d32a; /* { dg-error "not supported" } */
+_Decimal64 d64a; /* { dg-error "not supported" } */
+_Decimal128 d128a; /* { dg-error "not supported" } */
+
+_Bool d32b = 1.0DF; /* { dg-error "not supported" } */
+_Bool d64b = 1.0DD; /* { dg-error "not supported" } */
+_Bool d128b = 1.0DL; /* { dg-error "not supported" } */
diff --git a/gcc/testsuite/gcc.dg/fltconst-pedantic-dfp.c b/gcc/testsuite/gcc.dg/fltconst-pedantic-dfp.c
index d0d1c4c52fc..6ff3091ce6a 100644
--- a/gcc/testsuite/gcc.dg/fltconst-pedantic-dfp.c
+++ b/gcc/testsuite/gcc.dg/fltconst-pedantic-dfp.c
@@ -2,5 +2,8 @@
/* { dg-options "-pedantic" } */
double a = 1.dl; /* { dg-warning "decimal float" } */
+/* { dg-error "not supported for this target" "not supported" { target { ! dfp } } .-1 } */
double b = 1.df; /* { dg-warning "decimal float" } */
+/* { dg-error "not supported for this target" "not supported" { target { ! dfp } } .-1 } */
double c = 1.dd; /* { dg-warning "decimal float" } */
+/* { dg-error "not supported for this target" "not supported" { target { ! dfp } } .-1 } */
diff --git a/gcc/testsuite/gcc.dg/gnu2x-attrs-1.c b/gcc/testsuite/gcc.dg/gnu2x-attrs-1.c
index bc00371f466..87bdaec0807 100644
--- a/gcc/testsuite/gcc.dg/gnu2x-attrs-1.c
+++ b/gcc/testsuite/gcc.dg/gnu2x-attrs-1.c
@@ -7,8 +7,7 @@ void f (void) {};
[[gnu::alias("f")]] void g (void); /* { dg-error "only weak" "" { target *-*-darwin* } } */
-void [[gnu::alias("f")]] h (void); /* { dg-warning "ignored" } */
-/* { dg-message "that appertains to a type-specifier" "appertains" { target *-*-* } .-1 } */
+void [[gnu::alias("f")]] h (void); /* { dg-warning "does not apply to types" } */
struct [[gnu::packed]] s { int a; char b; };
_Static_assert (sizeof (struct s) == (sizeof (int) + sizeof (char)));
diff --git a/gcc/testsuite/gcc.dg/gnu2x-attrs-2.c b/gcc/testsuite/gcc.dg/gnu2x-attrs-2.c
new file mode 100644
index 00000000000..d512b2a2aca
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu2x-attrs-2.c
@@ -0,0 +1,33 @@
+/* Test C2x attribute syntax. Test GNU attributes appertain to
+ appropriate constructs. Attributes on types not being defined at
+ the time. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x -Wformat" } */
+
+typedef void va_type (const char *, ...);
+typedef va_type [[gnu::format (printf, 1, 2)]] printf_like_1;
+typedef void printf_like_2 (const char *, ...) [[gnu::format (printf, 1, 2)]];
+typedef __typeof__ (void (const char *, ...) [[gnu::format (printf, 1, 2)]])
+ printf_like_3;
+
+va_type func1;
+printf_like_1 func2;
+printf_like_2 func3;
+printf_like_3 func4;
+va_type [[gnu::format (printf, 1, 2)]] *func5 (void);
+
+void
+func_test (void)
+{
+ func1 ("%s", 1);
+ func2 ("%s", 1); /* { dg-warning "expects argument" } */
+ func3 ("%s", 1); /* { dg-warning "expects argument" } */
+ func4 ("%s", 1); /* { dg-warning "expects argument" } */
+ func5 () ("%s", 1); /* { dg-warning "expects argument" } */
+}
+
+typedef int A[2];
+
+__typeof__ (int [[gnu::deprecated]]) var1; /* { dg-warning "deprecated" } */
+__typeof__ (A [[gnu::deprecated]]) var2; /* { dg-warning "deprecated" } */
+__typeof__ (int [3] [[gnu::deprecated]]) var3; /* { dg-warning "deprecated" } */
diff --git a/gcc/testsuite/gcc.dg/gnu2x-builtins-no-dfp-1.c b/gcc/testsuite/gcc.dg/gnu2x-builtins-no-dfp-1.c
new file mode 100644
index 00000000000..853a56e9a85
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/gnu2x-builtins-no-dfp-1.c
@@ -0,0 +1,18 @@
+/* Test C2x built-in functions: test DFP built-in functions are not
+ available when no DFP support. Bug 91985. */
+/* { dg-do compile { target { ! dfp } } } */
+/* { dg-options "-std=gnu2x" } */
+
+int fabsd32 (void);
+int fabsd64 (void);
+int fabsd128 (void);
+int nand32 (void);
+int nand64 (void);
+int nand128 (void);
+
+__typeof__ (__builtin_fabsd32 (0)) d32; /* { dg-warning "implicit" } */
+__typeof__ (__builtin_fabsd64 (0)) d64; /* { dg-warning "implicit" } */
+__typeof__ (__builtin_fabsd128 (0)) d128; /* { dg-warning "implicit" } */
+__typeof__ (__builtin_nand32 (0)) d32n; /* { dg-warning "implicit" } */
+__typeof__ (__builtin_nand64 (0)) d64n; /* { dg-warning "implicit" } */
+__typeof__ (__builtin_nand128 (0)) d128n; /* { dg-warning "implicit" } */
diff --git a/gcc/testsuite/gcc.dg/ipa/ipa-clone-2.c b/gcc/testsuite/gcc.dg/ipa/ipa-clone-2.c
new file mode 100644
index 00000000000..d513020ee8b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/ipa-clone-2.c
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-ipa-cp-details -fno-early-inlining --param ipa-cp-max-recursive-depth=8" } */
+
+int fn();
+
+int data[100];
+
+int recur_fn (int i)
+{
+ int j;
+
+ if (i == 6)
+ {
+ fn();
+ fn();
+ fn();
+ fn();
+ fn();
+ fn();
+ fn();
+ fn();
+ fn();
+ fn();
+ fn();
+ fn();
+ return 10;
+ }
+
+ data[i] = i;
+
+ for (j = 0; j < 100; j++)
+ recur_fn (i + 1);
+
+ return i;
+}
+
+int main ()
+{
+ int i;
+
+ for (i = 0; i < 100; i++)
+ recur_fn (1) + recur_fn (-5);
+
+ return 1;
+}
+
+/* { dg-final { scan-ipa-dump-times "Creating a specialized node of recur_fn/\[0-9\]*\\." 12 "cp" } } */
diff --git a/gcc/testsuite/gcc.dg/pr92510.c b/gcc/testsuite/gcc.dg/pr92510.c
new file mode 100644
index 00000000000..d468586c0f8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr92510.c
@@ -0,0 +1,16 @@
+/* PR rtl-optimization/92510 */
+/* { dg-do compile } */
+/* { dg-options "-O1 -ftree-loop-vectorize -fno-forward-propagate -fno-tree-scev-cprop" } */
+
+int v;
+
+long int
+foo (long int x)
+{
+ signed char i;
+
+ for (i = 0; i < 8; ++i)
+ x |= !!v;
+
+ return x + i;
+}
diff --git a/gcc/testsuite/gcc.dg/strcmpopt_8.c b/gcc/testsuite/gcc.dg/strcmpopt_8.c
new file mode 100644
index 00000000000..a90c0d371b4
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strcmpopt_8.c
@@ -0,0 +1,177 @@
+/* PR tree-optimization/92683 - strncmp incorrect result with equal substrings
+ and nonconst bound
+ { dg-do compile }
+ { dg-options "-O1 -Wall -fdump-tree-forwprop1" } */
+
+#define SIZE_MAX __SIZE_MAX__
+
+#define S123 "123"
+#define S1234 "1234"
+
+typedef __SIZE_TYPE__ size_t;
+
+#ifndef ident
+# define ident(n) n
+#endif
+
+extern void failure_on_line (int);
+
+/* Verify that the test in 'if (EQL strncmp (S, T, N))' is folded. */
+#define T(eql, s, t, n) do { \
+ max = ident (n); \
+ if (!(eql __builtin_strncmp (s, t, max))) \
+ failure_on_line (__LINE__); \
+ } while (0)
+
+void test_literal (void)
+{
+ size_t max;
+
+ T (0 ==, S123, S1234, 0);
+ T (0 ==, S123, S1234, 1);
+ T (0 ==, S123, S1234, 2);
+ T (0 ==, S123, S1234, 3);
+ T (0 >, S123, S1234, 4);
+ T (0 >, S123, S1234, 5);
+ T (0 >, S123, S1234, SIZE_MAX - 2);
+ T (0 >, S123, S1234, SIZE_MAX - 1);
+ T (0 >, S123, S1234, SIZE_MAX);
+
+ T (0 ==, S123 + 1, S1234, 0);
+ T (0 <, S123 + 1, S1234, 1);
+ T (0 <, S123 + 1, S1234, 2);
+ T (0 <, S123 + 1, S1234, 3);
+ T (0 <, S123 + 1, S1234, 4);
+ T (0 <, S123 + 1, S1234, SIZE_MAX - 2);
+ T (0 <, S123 + 1, S1234, SIZE_MAX - 1);
+ T (0 <, S123 + 1, S1234, SIZE_MAX);
+
+ T (0 ==, S123 + 1, S1234 + 1, 0);
+ T (0 ==, S123 + 1, S1234 + 1, 1);
+ T (0 ==, S123 + 1, S1234 + 1, 2);
+ T (0 >, S123 + 1, S1234 + 1, 3);
+ T (0 >, S123 + 1, S1234 + 1, SIZE_MAX - 1);
+ T (0 >, S123 + 1, S1234 + 1, SIZE_MAX);
+
+ T (0 ==, S123 + 3, S1234 + 1, 0);
+ T (0 >, S123 + 3, S1234 + 1, 1);
+ T (0 >, S123 + 3, S1234 + 1, 2);
+ T (0 >, S123 + 3, S1234 + 1, 3);
+ T (0 >, S123 + 3, S1234 + 1, SIZE_MAX - 1);
+ T (0 >, S123 + 3, S1234 + 1, SIZE_MAX);
+
+ int zero = 0;
+
+ T (zero ==, S123, S1234, 0);
+ T (zero ==, S123, S1234, 1);
+ T (zero ==, S123, S1234, 2);
+ T (zero ==, S123, S1234, 3);
+ T (zero >, S123, S1234, 4);
+ T (zero >, S123, S1234, 5);
+ T (zero >, S123, S1234, SIZE_MAX - 2);
+ T (zero >, S123, S1234, SIZE_MAX - 1);
+ T (zero >, S123, S1234, SIZE_MAX);
+
+ T (zero ==, S123 + 1, S1234, 0);
+ T (zero <, S123 + 1, S1234, 1);
+ T (zero <, S123 + 1, S1234, 2);
+ T (zero <, S123 + 1, S1234, 3);
+ T (zero <, S123 + 1, S1234, 4);
+ T (zero <, S123 + 1, S1234, SIZE_MAX - 2);
+ T (zero <, S123 + 1, S1234, SIZE_MAX - 1);
+ T (zero <, S123 + 1, S1234, SIZE_MAX);
+
+ T (zero ==, S123 + 1, S1234 + 1, 0);
+ T (zero ==, S123 + 1, S1234 + 1, 1);
+ T (zero ==, S123 + 1, S1234 + 1, 2);
+ T (zero >, S123 + 1, S1234 + 1, 3);
+ T (zero >, S123 + 1, S1234 + 1, SIZE_MAX - 1);
+ T (zero >, S123 + 1, S1234 + 1, SIZE_MAX);
+
+ T (zero ==, S123 + 3, S1234 + 1, 0);
+ T (zero >, S123 + 3, S1234 + 1, 1);
+ T (zero >, S123 + 3, S1234 + 1, 2);
+ T (zero >, S123 + 3, S1234 + 1, 3);
+ T (zero >, S123 + 3, S1234 + 1, SIZE_MAX - 1);
+ T (zero >, S123 + 3, S1234 + 1, SIZE_MAX);
+}
+
+const char s123[] = S123;
+const char s1234[] = S1234;
+
+void test_cst_array (void)
+{
+ size_t max;
+
+ T (0 ==, s123, s1234, 0);
+ T (0 ==, s123, s1234, 1);
+ T (0 ==, s123, s1234, 2);
+ T (0 ==, s123, s1234, 3);
+ T (0 >, s123, s1234, 4);
+ T (0 >, s123, s1234, 5);
+ T (0 >, s123, s1234, SIZE_MAX - 2);
+ T (0 >, s123, s1234, SIZE_MAX - 1);
+ T (0 >, s123, s1234, SIZE_MAX);
+
+ T (0 ==, s123 + 1, s1234, 0);
+ T (0 <, s123 + 1, s1234, 1);
+ T (0 <, s123 + 1, s1234, 2);
+ T (0 <, s123 + 1, s1234, 3);
+ T (0 <, s123 + 1, s1234, 4);
+ T (0 <, s123 + 1, s1234, SIZE_MAX - 2);
+ T (0 <, s123 + 1, s1234, SIZE_MAX - 1);
+ T (0 <, s123 + 1, s1234, SIZE_MAX);
+
+ T (0 ==, s123 + 1, s1234 + 1, 0);
+ T (0 ==, s123 + 1, s1234 + 1, 1);
+ T (0 ==, s123 + 1, s1234 + 1, 2);
+ T (0 >, s123 + 1, s1234 + 1, 3);
+ T (0 >, s123 + 1, s1234 + 1, SIZE_MAX - 1);
+ T (0 >, s123 + 1, s1234 + 1, SIZE_MAX);
+
+ T (0 ==, s123 + 3, s1234 + 1, 0);
+ T (0 >, s123 + 3, s1234 + 1, 1);
+ T (0 >, s123 + 3, s1234 + 1, 2);
+ T (0 >, s123 + 3, s1234 + 1, 3);
+ T (0 >, s123 + 3, s1234 + 1, SIZE_MAX - 1);
+ T (0 >, s123 + 3, s1234 + 1, SIZE_MAX);
+
+ int zero = 0;
+
+ T (zero ==, s123, s1234, 0);
+ T (zero ==, s123, s1234, 1);
+ T (zero ==, s123, s1234, 2);
+ T (zero ==, s123, s1234, 3);
+ T (zero >, s123, s1234, 4);
+ T (zero >, s123, s1234, 5);
+ T (zero >, s123, s1234, SIZE_MAX - 2);
+ T (zero >, s123, s1234, SIZE_MAX - 1);
+ T (zero >, s123, s1234, SIZE_MAX);
+
+ T (zero ==, s123 + 1, s1234, 0);
+ T (zero <, s123 + 1, s1234, 1);
+ T (zero <, s123 + 1, s1234, 2);
+ T (zero <, s123 + 1, s1234, 3);
+ T (zero <, s123 + 1, s1234, 4);
+ T (zero <, s123 + 1, s1234, SIZE_MAX - 2);
+ T (zero <, s123 + 1, s1234, SIZE_MAX - 1);
+ T (zero <, s123 + 1, s1234, SIZE_MAX);
+
+ T (zero ==, s123 + 1, s1234 + 1, 0);
+ T (zero ==, s123 + 1, s1234 + 1, 1);
+ T (zero ==, s123 + 1, s1234 + 1, 2);
+ T (zero >, s123 + 1, s1234 + 1, 3);
+ T (zero >, s123 + 1, s1234 + 1, SIZE_MAX - 1);
+ T (zero >, s123 + 1, s1234 + 1, SIZE_MAX);
+
+ T (zero ==, s123 + 3, s1234 + 1, 0);
+ T (zero >, s123 + 3, s1234 + 1, 1);
+ T (zero >, s123 + 3, s1234 + 1, 2);
+ T (zero >, s123 + 3, s1234 + 1, 3);
+ T (zero >, s123 + 3, s1234 + 1, SIZE_MAX - 1);
+ T (zero >, s123 + 3, s1234 + 1, SIZE_MAX);
+}
+
+/* { dg-final { scan-tree-dump-not "strcmp" "forwprop1" } }
+ { dg-final { scan-tree-dump-not "strncmp" "forwprop1" } }
+ { dg-final { scan-tree-dump-not "failure_on_line_" "forwprop1" } } */
diff --git a/gcc/testsuite/gcc.dg/strcmpopt_9.c b/gcc/testsuite/gcc.dg/strcmpopt_9.c
new file mode 100644
index 00000000000..15f6b63d191
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/strcmpopt_9.c
@@ -0,0 +1,34 @@
+/* PR tree-optimization/92683 - strncmp incorrect result with equal substrings
+ and nonconst bound
+ { dg-do run }
+ { dg-options "-O2 -Wall" } */
+
+#include "strlenopt.h"
+
+#define ident(n) ident (n)
+
+__attribute__ ((noclone, noinline, noipa)) size_t
+ident (size_t x)
+{
+ return x;
+}
+
+int nfails;
+
+__attribute__ ((noclone, noinline, noipa)) void
+failure_on_line (int line)
+{
+ __builtin_printf ("failure on line %i\n", line);
+ ++nfails;
+}
+
+#include "strcmpopt_8.c"
+
+int main (void)
+{
+ test_literal ();
+ test_cst_array ();
+
+ if (nfails)
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-1.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-1.c
index bf7f3cedb29..971a5985357 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-1.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-1.c
@@ -2,27 +2,22 @@
float. */
/* { dg-do run } */
/* { dg-require-effective-target int128 } */
-/* { dg-require-effective-target fenv } */
/* { dg-options "-frounding-math" } */
-#include <fenv.h>
#include <stdlib.h>
int
main (void)
{
-#ifdef FE_TONEAREST
volatile unsigned long long h = 0x8000000000000000LL;
volatile unsigned long long l = 0xdLL;
volatile unsigned __int128 u128 = (((unsigned __int128) h) << 64) | l;
volatile __int128 s128 = u128;
- fesetround (FE_TONEAREST);
float fs = s128;
if (fs != -0x1p+127)
abort ();
double ds = s128;
if (ds != -0x1p+127)
abort ();
-#endif
exit (0);
}
diff --git a/gcc/testsuite/gcc.dg/torture/pr92690.c b/gcc/testsuite/gcc.dg/torture/pr92690.c
new file mode 100644
index 00000000000..b49f184fc09
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr92690.c
@@ -0,0 +1,38 @@
+/* { dg-do run { target *-*-*gnu* } } */
+/* { dg-additional-options "-D_GNU_SOURCE" } */
+/* { dg-require-effective-target fenv_exceptions } */
+
+#include <fenv.h>
+
+typedef int v4si __attribute__((vector_size(16)));
+typedef float v4sf __attribute__((vector_size(16)));
+
+void __attribute__((noipa))
+foo (v4si *dstp, v4sf *srcp)
+{
+ v4sf src = *srcp;
+ *dstp = (v4si) { src[0], src[1], 3, 4 };
+}
+
+void __attribute__((noipa))
+bar (v4sf *dstp, v4si *srcp)
+{
+ v4si src = *srcp;
+ *dstp = (v4sf) { src[0], src[1], 3.5, 4.5 };
+}
+
+int
+main()
+{
+ feenableexcept (FE_INVALID|FE_INEXACT);
+ v4sf x = (v4sf) { 1, 2, __builtin_nanf (""), 3.5 };
+ v4si y;
+ foo (&y, &x);
+ if (y[0] != 1 || y[1] != 2 || y[2] != 3 || y[3] != 4)
+ __builtin_abort ();
+ y = (v4si) { 0, 1, __INT_MAX__, -__INT_MAX__ };
+ bar (&x, &y);
+ if (x[0] != 0 || x[1] != 1 || x[2] != 3.5 || x[3] != 4.5)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr92704.c b/gcc/testsuite/gcc.dg/torture/pr92704.c
new file mode 100644
index 00000000000..79994a39b54
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr92704.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fexceptions -fnon-call-exceptions -fno-tree-dce -ftree-loop-if-convert" } */
+int zr, yx;
+
+void __attribute__ ((simd))
+oj (int rd, int q7)
+{
+ int wo = (__UINTPTR_TYPE__)&rd;
+
+ while (q7 < 1)
+ {
+ int kv;
+ short int v3;
+
+ for (v3 = 0; v3 < 82; v3 += 3)
+ {
+ }
+
+ kv = zr ? 0 : v3;
+ yx = kv < rd;
+ zr = zr && yx;
+ ++q7;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr92715.c b/gcc/testsuite/gcc.dg/torture/pr92715.c
new file mode 100644
index 00000000000..170179c2032
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr92715.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-mavx2" { target x86_64-*-* i?86-*-* } } */
+
+typedef double v4si __attribute__((vector_size(32)));
+typedef double v2si __attribute__((vector_size(16)));
+
+void foo (v4si *dstp, v2si *srcp)
+{
+ v2si src = *srcp;
+ *dstp = (v4si) { src[0], src[1], src[0], src[1] };
+}
+
+void bar (v4si *dstp, v2si *srcp)
+{
+ v2si src = *srcp;
+ *dstp = (v4si) { src[0], src[0], src[0], src[0] };
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-10.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-10.c
new file mode 100644
index 00000000000..07ee4e587a2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-snprintf-10.c
@@ -0,0 +1,10 @@
+/* PR tree-optimization/92691 */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+void
+foo (int x, char *y)
+{
+ if (x != 0)
+ __builtin_snprintf (y, 0, "foo");
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c
index d55197bceb9..24e63386960 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-35.c
@@ -16,4 +16,5 @@ v4sf vec_cast_perm(v4si f)
}
/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 1 "cddce1" { target { i?86-*-* x86_64-*-* } } } } */
-/* { dg-final { scan-tree-dump-times "\\\(v4sf\\\) " 2 "cddce1" { target { i?86-*-* x86_64-*-* } } } } */
+/* Catch (v4sf) and (vector(4) float). */
+/* { dg-final { scan-tree-dump-times " = \\\(v" 2 "cddce1" { target { i?86-*-* x86_64-*-* } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-12.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-12.c
new file mode 100644
index 00000000000..250d77eb04d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-12.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-einline" } */
+
+void *foo (void *, int);
+static inline void *mcp (void *src, int i)
+{
+ return foo (src, i);
+}
+void bar()
+{
+ int i;
+ mcp (&i, 0);
+}
+
+/* There should be exactly two assignments, one for both
+ the original foo call and the inlined copy (plus a clobber
+ that doesn't match here). In particular bar should look like
+ <bb 2> :
+ _4 = foo (&i, 0);
+ i ={v} {CLOBBER};
+ return; */
+/* { dg-final { scan-tree-dump-times " = " 2 "einline" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr92712-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr92712-1.c
new file mode 100644
index 00000000000..c19ff5cf29c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr92712-1.c
@@ -0,0 +1,21 @@
+/* PR tree-optimization/92712 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump " = \[tv]_\[0-9]*\\\(D\\\) \\* \[tv]_\[0-9]*\\\(D\\\);" "optimized" } } */
+
+static int
+foo (int t, int v)
+{
+ int i, x = 0;
+ for (int i = 0; i < t; ++i)
+ x += v;
+ return x;
+}
+
+int
+bar (int t, int v)
+{
+ if (t < 0)
+ __builtin_unreachable ();
+ return foo (t, v);
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr92712-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr92712-2.c
new file mode 100644
index 00000000000..2710ff36cc1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr92712-2.c
@@ -0,0 +1,66 @@
+/* PR tree-optimization/92712 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-times " = \[tv]_\[0-9]*\\\(D\\\) \\* \[tv]_\[0-9]*\\\(D\\\);" 7 "optimized" } } */
+
+int
+f1 (int t, int v)
+{
+ int a = t - 1;
+ int b = a * v;
+ return b + v;
+}
+
+int
+f2 (int t, int v)
+{
+ int a = t - 1;
+ int b = a * v;
+ return v + b;
+}
+
+int
+f3 (int t, int v)
+{
+ int a = t + 1;
+ int b = a * v;
+ return b - v;
+}
+
+int
+f4 (int t, int v)
+{
+ int a = 1 - t;
+ int b = a * v;
+ return v - b;
+}
+
+int
+f5 (int t, int v)
+{
+ if (v == 0 || v == -1)
+ __builtin_unreachable ();
+ int a = t - 1U;
+ int b = a * v;
+ return b + v;
+}
+
+int
+f6 (int t, int v)
+{
+ if (v == 0 || v == -1)
+ __builtin_unreachable ();
+ int a = t - 1U;
+ int b = a * v;
+ return v + b;
+}
+
+int
+f7 (int t, int v)
+{
+ if (v == 0)
+ __builtin_unreachable ();
+ int a = t + 1U;
+ int b = a * v;
+ return b - v;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr92712-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr92712-3.c
new file mode 100644
index 00000000000..27749a125a7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr92712-3.c
@@ -0,0 +1,36 @@
+/* PR tree-optimization/92712 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-ipa-icf -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not " = \[tv]_\[0-9]*\\\(D\\\) \\* \[tv]_\[0-9]*\\\(D\\\);" "optimized" } } */
+
+int
+f1 (int t, int v)
+{
+ int a = t - 1U;
+ int b = a * v;
+ return b + v;
+}
+
+int
+f2 (int t, int v)
+{
+ int a = t - 1U;
+ int b = a * v;
+ return v + b;
+}
+
+int
+f3 (int t, int v)
+{
+ int a = t + 1U;
+ int b = a * v;
+ return b - v;
+}
+
+int
+f4 (int t, int v)
+{
+ int a = 1U - t;
+ int b = a * v;
+ return v - b;
+}
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-43.c b/gcc/testsuite/gcc.dg/vect/bb-slp-43.c
new file mode 100644
index 00000000000..a65d9513c4d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-43.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+
+void
+f (int *restrict x, short *restrict y)
+{
+ x[0] = x[0] == 1 & y[0] == 2;
+ x[1] = x[1] == 1 & y[1] == 2;
+ x[2] = x[2] == 1 & y[2] == 2;
+ x[3] = x[3] == 1 & y[3] == 2;
+ x[4] = x[4] == 1 & y[4] == 2;
+ x[5] = x[5] == 1 & y[5] == 2;
+ x[6] = x[6] == 1 & y[6] == 2;
+ x[7] = x[7] == 1 & y[7] == 2;
+}
+
+/* { dg-final { scan-tree-dump-not "mixed mask and nonmask" "slp2" } } */
+/* { dg-final { scan-tree-dump-not "vector operands from scalars" "slp2" { target { { vect_int && vect_bool_cmp } && { vect_unpack && vect_hw_misalign } } xfail vect_variable_length } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr92596.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr92596.c
new file mode 100644
index 00000000000..f3dd08d9878
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr92596.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+
+typedef struct {
+ long n[5];
+} secp256k1_fe;
+
+secp256k1_fe a;
+
+void fn1(int p1) { a.n[0] = a.n[1] = a.n[2] = p1; }
+void fn2() {
+ int b;
+ fn1(!b);
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr92677.c b/gcc/testsuite/gcc.dg/vect/pr92677.c
new file mode 100644
index 00000000000..3f85b295249
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr92677.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O3" } */
+
+int a, c;
+int *b;
+long d;
+double *e;
+
+void fn1() {
+ long f;
+ double g, h;
+ while (c) {
+ if (d) {
+ g = *e;
+ *(b + 4) = g;
+ }
+ if (f) {
+ h = *(e + 2);
+ *(b + 6) = h;
+ }
+ e += a;
+ b += 8;
+ c--;
+ d += 2;
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/vect/pr92710.c b/gcc/testsuite/gcc.dg/vect/pr92710.c
new file mode 100644
index 00000000000..2986d4ce06a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr92710.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-fopenmp-simd" } */
+
+#pragma omp declare simd
+_Bool foo (_Bool) __attribute__((const));
+
+void
+f (_Bool *restrict x, char *restrict y, char *restrict z)
+{
+ for (int i = 0; i < 128; ++i)
+ x[i] = foo (y[i] == z[i]);
+}
diff --git a/gcc/testsuite/gcc.dg/vect/slp-reduc-3.c b/gcc/testsuite/gcc.dg/vect/slp-reduc-3.c
index 9c8124c9b5f..7358275c3cb 100644
--- a/gcc/testsuite/gcc.dg/vect/slp-reduc-3.c
+++ b/gcc/testsuite/gcc.dg/vect/slp-reduc-3.c
@@ -1,4 +1,5 @@
/* { dg-require-effective-target vect_int } */
+/* { dg-additional-options "--param=vect-epilogues-nomask=0" } */
#include <stdarg.h>
#include "tree-vect.h"
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bool-cmp-2.c b/gcc/testsuite/gcc.dg/vect/vect-bool-cmp-2.c
new file mode 100644
index 00000000000..1fb57ff945e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/vect-bool-cmp-2.c
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+
+void
+f (_Bool *restrict x, _Bool *restrict y)
+{
+ for (int i = 0; i < 128; ++i)
+ x[i] = x[i] == y[i];
+}
+
+/* { dg-final { scan-tree-dump "loop vectorized" "vect" { target vect_bool_cmp } } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c
new file mode 100644
index 00000000000..ec892a3fc83
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c
@@ -0,0 +1,217 @@
+/* { dg-options "-std=gnu99" } */
+
+#include <arm_sve.h>
+
+typedef signed char int8x32_t __attribute__((__vector_size__ (32)));
+
+/* Sizeless objects with global scope. */
+
+svint8_t global_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+static svint8_t local_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+extern svint8_t extern_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+__thread svint8_t tls_sve_sc; /* { dg-error {variables of type 'svint8_t' cannot have thread-local storage duration} } */
+_Atomic svint8_t atomic_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+
+/* Sizeless arrays. */
+
+typedef svint8_t array_type[2]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+extern svint8_t extern_array[]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+
+/* Sizeless fields. */
+
+struct struct1 {
+ svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */
+};
+
+union union1 {
+ svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */
+};
+
+/* Pointers to sizeless types. */
+
+svint8_t *global_sve_sc_ptr;
+svint8_t *invalid_sve_sc_ptr = &(svint8_t) { *global_sve_sc_ptr }; /* { dg-error {initializer element is not constant} } */
+ /* { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target *-*-* } .-1 } */
+
+/* Sizeless arguments and return values. */
+
+void ext_consume_sve_sc (svint8_t);
+void ext_consume_varargs (int, ...);
+svint8_t ext_produce_sve_sc ();
+
+/* Main tests for statements and expressions. */
+
+void
+statements (int n)
+{
+ /* Local declarations. */
+
+ unsigned char va __attribute__((__vector_size__(2)));
+ svint8_t sve_sc1, sve_sc2;
+ _Atomic svint8_t atomic_sve_sc;
+ int8x32_t gnu_sc1;
+ svint16_t sve_sh1;
+ static svint8_t local_static_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+
+ /* Layout queries. */
+
+ sizeof (svint8_t); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+ sizeof (sve_sc1); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+ sizeof (ext_produce_sve_sc ()); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+ _Alignof (svint8_t); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */
+ _Alignof (sve_sc1); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */
+ _Alignof (ext_produce_sve_sc ()); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */
+
+ /* Initialization. */
+
+ svint8_t init_sve_sc1 = sve_sc1;
+ svint8_t init_sve_sc2 = sve_sh1; /* { dg-error {incompatible types when initializing type 'svint8_t' using type 'svint16_t'} } */
+ svint8_t init_sve_sc3 = {}; /* { dg-error {empty scalar initializer} } */
+
+ int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+ int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+
+ /* Compound literals. */
+
+ (svint8_t) {}; /* { dg-error {empty scalar initializer} } */
+ (svint8_t) { sve_sc1 };
+
+ (int) { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+
+ /* Arrays. */
+
+ svint8_t array[2]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+ svint8_t zero_length_array[0]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+ svint8_t empty_init_array[] = {}; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+ /* { dg-error {empty scalar initializer} "" { target *-*-* } .-1 } */
+ typedef svint8_t vla_type[n]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+
+ /* Assignment. */
+
+ n = sve_sc1; /* { dg-error {incompatible types when assigning to type 'int' from type 'svint8_t'} } */
+
+ sve_sc1 = 0; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'int'} } */
+ sve_sc1 = sve_sc2;
+ sve_sc1 = sve_sh1; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'svint16_t'} } */
+
+ /* Casting. */
+
+ (void) sve_sc1;
+ (svint8_t) sve_sc1;
+
+ /* Addressing and dereferencing. */
+
+ svint8_t *sve_sc_ptr = &sve_sc1;
+ int8x32_t *gnu_sc_ptr = &gnu_sc1;
+ sve_sc1 = *sve_sc_ptr;
+
+ /* Pointer assignment. */
+
+ gnu_sc_ptr = sve_sc_ptr; /* { dg-warning {assignment to [^\n]* from incompatible pointer type} } */
+ sve_sc_ptr = gnu_sc_ptr; /* { dg-warning {assignment to [^\n]* from incompatible pointer type} } */
+
+ /* Pointer arithmetic. */
+
+ ++sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ --sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr++; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr--; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr += 0; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr += 1; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr -= 0; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr -= 1; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr - sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ gnu_sc_ptr - sve_sc_ptr; /* { dg-error {invalid operands to binary -} } */
+ sve_sc_ptr - gnu_sc_ptr; /* { dg-error {invalid operands to binary -} } */
+ sve_sc1 = sve_sc_ptr[0]; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc1 = sve_sc_ptr[1]; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+
+ /* Pointer comparison. */
+
+ sve_sc_ptr == &sve_sc1;
+ sve_sc_ptr != &sve_sc1;
+ sve_sc_ptr < &sve_sc1;
+ sve_sc_ptr <= &sve_sc1;
+ sve_sc_ptr > &sve_sc1;
+ sve_sc_ptr >= &sve_sc1;
+ gnu_sc_ptr == sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ gnu_sc_ptr != sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ gnu_sc_ptr < sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ gnu_sc_ptr <= sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ gnu_sc_ptr > sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ gnu_sc_ptr >= sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ sve_sc_ptr == gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ sve_sc_ptr != gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ sve_sc_ptr < gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ sve_sc_ptr <= gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ sve_sc_ptr > gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+ sve_sc_ptr >= gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */
+
+ /* Conditional expressions. */
+
+ 0 ? sve_sc1 : sve_sc1;
+ 0 ? sve_sc1 : sve_sh1; /* { dg-error {type mismatch in conditional expression} } */
+ 0 ? sve_sc1 : 0; /* { dg-error {type mismatch in conditional expression} } */
+ 0 ? 0 : sve_sc1; /* { dg-error {type mismatch in conditional expression} } */
+ 0 ?: sve_sc1; /* { dg-error {type mismatch in conditional expression} } */
+ 0 ? sve_sc_ptr : sve_sc_ptr;
+ 0 ? sve_sc_ptr : gnu_sc_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */
+ 0 ? gnu_sc_ptr : sve_sc_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */
+
+ /* Generic associations. */
+
+ _Generic (sve_sc1, default: 100);
+ _Generic (1, svint8_t: 10, default: 20);
+
+ /* Function arguments. */
+
+ ext_consume_sve_sc (sve_sc1);
+ ext_consume_sve_sc (sve_sh1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_sve_sc'} } */
+ ext_consume_varargs (sve_sc1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_varargs'} } */
+ ext_consume_varargs (1, sve_sc1);
+
+ /* Function returns. */
+
+ ext_produce_sve_sc ();
+ sve_sc1 = ext_produce_sve_sc ();
+ sve_sh1 = ext_produce_sve_sc (); /* { dg-error {incompatible types when assigning to type 'svint16_t' from type 'svint8_t'} } */
+
+ /* Varargs processing. */
+
+ __builtin_va_list valist;
+ __builtin_va_arg (valist, svint8_t);
+
+ /* Statement expressions. */
+
+ ({ sve_sc1; });
+ ({ svint8_t another_sve_sc = *sve_sc_ptr; another_sve_sc; });
+}
+
+/* Function parameters in definitions. */
+
+void
+old_style (input_sve_sc) /* { dg-error {SVE type 'svint8_t' cannot be passed to an unprototyped function} } */
+ svint8_t input_sve_sc;
+{
+ svint8_t sve_sc1 = input_sve_sc;
+}
+
+void
+new_style_param (svint8_t input_sve_sc)
+{
+ svint8_t sve_sc1 = input_sve_sc;
+}
+
+/* Function return values in definitions. */
+
+svint8_t
+good_return_sve_sc (svint8_t param)
+{
+ return param;
+}
+
+svint8_t
+bad_return_sve_sc (svint16_t param)
+{
+ return param; /* { dg-error {incompatible types when returning type 'svint16_t' but 'svint8_t' was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c
new file mode 100644
index 00000000000..71743930098
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c
@@ -0,0 +1,217 @@
+/* { dg-options "-std=gnu99 -msve-vector-bits=256" } */
+
+#include <arm_sve.h>
+
+typedef signed char int8x32_t __attribute__((__vector_size__ (32)));
+
+/* Sizeless objects with global scope. */
+
+svint8_t global_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+static svint8_t local_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+extern svint8_t extern_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+__thread svint8_t tls_sve_sc; /* { dg-error {variables of type 'svint8_t' cannot have thread-local storage duration} } */
+_Atomic svint8_t atomic_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+
+/* Sizeless arrays. */
+
+typedef svint8_t array_type[2]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+extern svint8_t extern_array[]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+
+/* Sizeless fields. */
+
+struct struct1 {
+ svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */
+};
+
+union union1 {
+ svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */
+};
+
+/* Pointers to sizeless types. */
+
+svint8_t *global_sve_sc_ptr;
+svint8_t *invalid_sve_sc_ptr = &(svint8_t) { *global_sve_sc_ptr }; /* { dg-error {initializer element is not constant} } */
+ /* { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target *-*-* } .-1 } */
+
+/* Sizeless arguments and return values. */
+
+void ext_consume_sve_sc (svint8_t);
+void ext_consume_varargs (int, ...);
+svint8_t ext_produce_sve_sc ();
+
+/* Main tests for statements and expressions. */
+
+void
+statements (int n)
+{
+ /* Local declarations. */
+
+ unsigned char va __attribute__((__vector_size__(2)));
+ svint8_t sve_sc1, sve_sc2;
+ _Atomic svint8_t atomic_sve_sc;
+ int8x32_t gnu_sc1;
+ svint16_t sve_sh1;
+ static svint8_t local_static_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+
+ /* Layout queries. */
+
+ sizeof (svint8_t); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+ sizeof (sve_sc1); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+ sizeof (ext_produce_sve_sc ()); /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */
+ _Alignof (svint8_t); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */
+ _Alignof (sve_sc1); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */
+ _Alignof (ext_produce_sve_sc ()); /* { dg-error {SVE type 'svint8_t' does not have a defined alignment} } */
+
+ /* Initialization. */
+
+ svint8_t init_sve_sc1 = sve_sc1;
+ svint8_t init_sve_sc2 = sve_sh1; /* { dg-error {incompatible types when initializing type 'svint8_t' using type 'svint16_t'} } */
+ svint8_t init_sve_sc3 = {}; /* { dg-error {empty scalar initializer} } */
+
+ int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+ int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+
+ /* Compound literals. */
+
+ (svint8_t) {}; /* { dg-error {empty scalar initializer} } */
+ (svint8_t) { sve_sc1 };
+
+ (int) { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */
+
+ /* Arrays. */
+
+ svint8_t array[2]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+ svint8_t zero_length_array[0]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+ svint8_t empty_init_array[] = {}; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+ /* { dg-error {empty scalar initializer} "" { target *-*-* } .-1 } */
+ typedef svint8_t vla_type[n]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */
+
+ /* Assignment. */
+
+ n = sve_sc1; /* { dg-error {incompatible types when assigning to type 'int' from type 'svint8_t'} } */
+
+ sve_sc1 = 0; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'int'} } */
+ sve_sc1 = sve_sc2;
+ sve_sc1 = sve_sh1; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'svint16_t'} } */
+
+ /* Casting. */
+
+ (void) sve_sc1;
+ (svint8_t) sve_sc1;
+
+ /* Addressing and dereferencing. */
+
+ svint8_t *sve_sc_ptr = &sve_sc1;
+ int8x32_t *gnu_sc_ptr = &gnu_sc1;
+ sve_sc1 = *sve_sc_ptr;
+
+ /* Pointer assignment. */
+
+ gnu_sc_ptr = sve_sc_ptr;
+ sve_sc_ptr = gnu_sc_ptr;
+
+ /* Pointer arithmetic. */
+
+ ++sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ --sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr++; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr--; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr += 0; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr += 1; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr -= 0; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr -= 1; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr - sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ gnu_sc_ptr - sve_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc_ptr - gnu_sc_ptr; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc1 = sve_sc_ptr[0]; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+ sve_sc1 = sve_sc_ptr[1]; /* { dg-error {arithmetic on pointer to SVE type 'svint8_t'} } */
+
+ /* Pointer comparison. */
+
+ sve_sc_ptr == &sve_sc1;
+ sve_sc_ptr != &sve_sc1;
+ sve_sc_ptr < &sve_sc1;
+ sve_sc_ptr <= &sve_sc1;
+ sve_sc_ptr > &sve_sc1;
+ sve_sc_ptr >= &sve_sc1;
+ gnu_sc_ptr == sve_sc_ptr;
+ gnu_sc_ptr != sve_sc_ptr;
+ gnu_sc_ptr < sve_sc_ptr;
+ gnu_sc_ptr <= sve_sc_ptr;
+ gnu_sc_ptr > sve_sc_ptr;
+ gnu_sc_ptr >= sve_sc_ptr;
+ sve_sc_ptr == gnu_sc_ptr;
+ sve_sc_ptr != gnu_sc_ptr;
+ sve_sc_ptr < gnu_sc_ptr;
+ sve_sc_ptr <= gnu_sc_ptr;
+ sve_sc_ptr > gnu_sc_ptr;
+ sve_sc_ptr >= gnu_sc_ptr;
+
+ /* Conditional expressions. */
+
+ 0 ? sve_sc1 : sve_sc1;
+ 0 ? sve_sc1 : sve_sh1; /* { dg-error {type mismatch in conditional expression} } */
+ 0 ? sve_sc1 : 0; /* { dg-error {type mismatch in conditional expression} } */
+ 0 ? 0 : sve_sc1; /* { dg-error {type mismatch in conditional expression} } */
+ 0 ?: sve_sc1; /* { dg-error {type mismatch in conditional expression} } */
+ 0 ? sve_sc_ptr : sve_sc_ptr;
+ 0 ? sve_sc_ptr : gnu_sc_ptr;
+ 0 ? gnu_sc_ptr : sve_sc_ptr;
+
+ /* Generic associations. */
+
+ _Generic (sve_sc1, default: 100);
+ _Generic (1, svint8_t: 10, default: 20);
+
+ /* Function arguments. */
+
+ ext_consume_sve_sc (sve_sc1);
+ ext_consume_sve_sc (sve_sh1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_sve_sc'} } */
+ ext_consume_varargs (sve_sc1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_varargs'} } */
+ ext_consume_varargs (1, sve_sc1);
+
+ /* Function returns. */
+
+ ext_produce_sve_sc ();
+ sve_sc1 = ext_produce_sve_sc ();
+ sve_sh1 = ext_produce_sve_sc (); /* { dg-error {incompatible types when assigning to type 'svint16_t' from type 'svint8_t'} } */
+
+ /* Varargs processing. */
+
+ __builtin_va_list valist;
+ __builtin_va_arg (valist, svint8_t);
+
+ /* Statement expressions. */
+
+ ({ sve_sc1; });
+ ({ svint8_t another_sve_sc = *sve_sc_ptr; another_sve_sc; });
+}
+
+/* Function parameters in definitions. */
+
+void
+old_style (input_sve_sc) /* { dg-error {SVE type 'svint8_t' cannot be passed to an unprototyped function} } */
+ svint8_t input_sve_sc;
+{
+ svint8_t sve_sc1 = input_sve_sc;
+}
+
+void
+new_style_param (svint8_t input_sve_sc)
+{
+ svint8_t sve_sc1 = input_sve_sc;
+}
+
+/* Function return values in definitions. */
+
+svint8_t
+good_return_sve_sc (svint8_t param)
+{
+ return param;
+}
+
+svint8_t
+bad_return_sve_sc (svint16_t param)
+{
+ return param; /* { dg-error {incompatible types when returning type 'svint16_t' but 'svint8_t' was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/arm/asm-flag-4.c b/gcc/testsuite/gcc.target/arm/asm-flag-4.c
index 8b3eac1320b..75378cc89b0 100644
--- a/gcc/testsuite/gcc.target/arm/asm-flag-4.c
+++ b/gcc/testsuite/gcc.target/arm/asm-flag-4.c
@@ -1,6 +1,8 @@
/* Test that we do not ice in thumb1 mode */
/* { dg-do compile } */
-/* { dg-options "-march=armv4t" } */
+/* { dg-require-effective-target arm_arch_v4t_thumb_ok } */
+/* { dg-skip-if "do not override -mfloat-abi" { *-*-* } { "-mfloat-abi=*" } { "-mfloat-abi=softfp" } } */
+/* { dg-options "-march=armv4t -mfloat-abi=softfp" } */
void __attribute__((target("arm"))) f(char *out)
{
diff --git a/gcc/testsuite/gcc.target/i386/pr32219-2.c b/gcc/testsuite/gcc.target/i386/pr32219-2.c
index b6212f7dd4c..a9c18ba1995 100644
--- a/gcc/testsuite/gcc.target/i386/pr32219-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr32219-2.c
@@ -12,13 +12,12 @@ foo ()
}
/* { dg-final { scan-assembler-not "movl\[ \t\]xxx\\(%rip\\), %" { target { ! ia32 } } } } */
-/* For Darwin m64 we are always PIC, but common symbols are indirected, which happens to
- match the general "ELF" case. */
-/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { ! ia32 } } } } */
+/* For Darwin m64 PIC we make a direct access to this symbol. */
+/* { dg-final { scan-assembler "xxx@GOTPCREL" { target { { ! ia32 } && { ! *-*-darwin* } } } } } */
/* { dg-final { scan-assembler-not "movl\[ \t\]xxx@GOTOFF\\(%\[^,\]*\\), %" { target { ia32 && { ! *-*-darwin* } } } } } */
/* { dg-final { scan-assembler "movl\[ \t\]xxx@GOT\\(%\[^,\]*\\), %" { target { ia32 && { ! *-*-darwin* } } } } } */
-/* Darwin m32 defaults to PIC but common symbols need to be indirected. */
-/* { dg-final { scan-assembler {movl[ \t][Ll]_xxx\$non_lazy_ptr-L1\$pb\(%eax\),[ \t]%eax} { target { ia32 && *-*-darwin* } } } } */
+/* Darwin m32 PIC requires the picbase adjustment. */
+/* { dg-final { scan-assembler {movl[ \t]_xxx-L1\$pb\(%eax\),[ \t]%eax} { target { ia32 && *-*-darwin* } } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr90007.c b/gcc/testsuite/gcc.target/i386/pr90007.c
new file mode 100644
index 00000000000..a16eec308fb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr90007.c
@@ -0,0 +1,15 @@
+/* PR rtl-optimization/90007 */
+/* { dg-do compile { target x86_64-*-* } } */
+/* { dg-options "-march=bdver1 -mfpmath=387 -O1 -fschedule-insns -fselective-scheduling" } */
+
+void
+qj (int b9, int r9, int k4, int k0, int e7)
+{
+ (void) b9;
+ (void) r9;
+ (void) k4;
+
+ while (!!k0 == e7 * 1.1)
+ {
+ }
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr92645-2.c b/gcc/testsuite/gcc.target/i386/pr92645-2.c
new file mode 100644
index 00000000000..d34ed3aa8e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr92645-2.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -msse2 -fdump-tree-cddce1" } */
+
+typedef int v4si __attribute__((vector_size(16)));
+typedef int v2si __attribute__((vector_size(8)));
+
+void low (v2si *dst, v4si *srcp)
+{
+ v4si src = *srcp;
+ *dst = (v2si) { src[0], src[1] };
+}
+
+void high (v2si *dst, v4si *srcp)
+{
+ v4si src = *srcp;
+ *dst = (v2si) { src[2], src[3] };
+}
+
+void even (v2si *dst, v4si *srcp)
+{
+ v4si src = *srcp;
+ *dst = (v2si) { src[0], src[2] };
+}
+
+void odd (v2si *dst, v4si *srcp)
+{
+ v4si src = *srcp;
+ *dst = (v2si) { src[1], src[3] };
+}
+
+/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 4 "cddce1" } } */
+/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 3 "cddce1" } } */
+/* Ideally highpart extraction would elide the permutation as well. */
+/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 2 "cddce1" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr92645-3.c b/gcc/testsuite/gcc.target/i386/pr92645-3.c
new file mode 100644
index 00000000000..9c08c9fb632
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr92645-3.c
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx2 -fdump-tree-cddce1" } */
+
+typedef int v8si __attribute__((vector_size(32)));
+typedef float v4sf __attribute__((vector_size(16)));
+
+void low (v4sf *dst, v8si *srcp)
+{
+ v8si src = *srcp;
+ *dst = (v4sf) { src[0], src[1], src[2], src[3] };
+}
+
+void high (v4sf *dst, v8si *srcp)
+{
+ v8si src = *srcp;
+ *dst = (v4sf) { src[4], src[5], src[6], src[7] };
+}
+
+void even (v4sf *dst, v8si *srcp)
+{
+ v8si src = *srcp;
+ *dst = (v4sf) { src[0], src[2], src[4], src[6] };
+}
+
+void odd (v4sf *dst, v8si *srcp)
+{
+ v8si src = *srcp;
+ *dst = (v4sf) { src[1], src[3], src[5], src[7] };
+}
+
+/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 4 "cddce1" } } */
+/* Four conversions, on the smaller vector type, to not convert excess
+ elements. */
+/* { dg-final { scan-tree-dump-times " = \\\(vector\\\(4\\\) float\\\)" 4 "cddce1" } } */
+/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 3 "cddce1" } } */
+/* Ideally highpart extraction would elide the VEC_PERM_EXPR as well. */
+/* { dg-final { scan-tree-dump-times "VEC_PERM_EXPR" 2 "cddce1" { xfail *-*-* } } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr92645-4.c b/gcc/testsuite/gcc.target/i386/pr92645-4.c
new file mode 100644
index 00000000000..788a97ed117
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr92645-4.c
@@ -0,0 +1,56 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mavx2 -fdump-tree-optimized -Wno-psabi" } */
+
+typedef unsigned int u32v4 __attribute__((vector_size(16)));
+typedef unsigned short u16v16 __attribute__((vector_size(32)));
+typedef unsigned char u8v16 __attribute__((vector_size(16)));
+
+union vec128 {
+ u8v16 u8;
+ u32v4 u32;
+};
+
+#define memcpy __builtin_memcpy
+
+static u16v16 zxt(u8v16 x)
+{
+ return (u16v16) {
+ x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]
+ };
+}
+
+static u8v16 narrow(u16v16 x)
+{
+ return (u8v16) {
+ x[0], x[1], x[2], x[3], x[4], x[5], x[6], x[7],
+ x[8], x[9], x[10], x[11], x[12], x[13], x[14], x[15]
+ };
+}
+
+void f(char *dst, char *src, unsigned long n, unsigned c)
+{
+ unsigned ia = 255 - (c >> 24);
+ ia += ia >> 7;
+
+ union vec128 c4 = {0}, ia16 = {0};
+ c4.u32 += c;
+ ia16.u8 += (unsigned char)ia;
+
+ u16v16 c16 = (zxt(c4.u8) << 8) + 128;
+
+ for (; n; src += 16, dst += 16, n -= 4) {
+ union vec128 s;
+ memcpy(&s, src, sizeof s);
+ s.u8 = narrow((zxt(s.u8)*zxt(ia16.u8) + c16) >> 8);
+ memcpy(dst, &s, sizeof s);
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "vec_unpack_lo" 3 "optimized" } } */
+/* We're missing an opportunity to, after later optimizations, combine
+ a uniform CTOR with a vec_unpack_lo_expr to a CTOR on a converted
+ element. */
+/* { dg-final { scan-tree-dump-times "vec_unpack_lo" 2 "optimized" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "VEC_PACK_TRUNC" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr92645.c b/gcc/testsuite/gcc.target/i386/pr92645.c
new file mode 100644
index 00000000000..467ed536b94
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr92645.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -fdump-tree-optimized -msse2 -Wno-psabi" } */
+
+typedef unsigned short v8hi __attribute__((vector_size(16)));
+typedef unsigned int v4si __attribute__((vector_size(16)));
+
+void bar (v4si *dst, v8hi * __restrict src)
+{
+ unsigned int tem[8];
+ tem[0] = (*src)[0];
+ tem[1] = (*src)[1];
+ tem[2] = (*src)[2];
+ tem[3] = (*src)[3];
+ tem[4] = (*src)[4];
+ tem[5] = (*src)[5];
+ tem[6] = (*src)[6];
+ tem[7] = (*src)[7];
+ dst[0] = *(v4si *)tem;
+ dst[1] = *(v4si *)&tem[4];
+}
+void foo (v4si *dst, v8hi src)
+{
+ unsigned int tem[8];
+ tem[0] = src[0];
+ tem[1] = src[1];
+ tem[2] = src[2];
+ tem[3] = src[3];
+ tem[4] = src[4];
+ tem[5] = src[5];
+ tem[6] = src[6];
+ tem[7] = src[7];
+ dst[0] = *(v4si *)tem;
+ dst[1] = *(v4si *)&tem[4];
+}
+
+/* { dg-final { scan-tree-dump-times "vec_unpack_" 4 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/nios2/pr92499-1.c b/gcc/testsuite/gcc.target/nios2/pr92499-1.c
new file mode 100644
index 00000000000..3985917a10c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nios2/pr92499-1.c
@@ -0,0 +1,48 @@
+/* PR target/92499 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mgpopt=global -G8" } */
+
+/* Check placement and addressing of flexibly-sized objects with internal
+ linkage. */
+
+enum { size = 100 };
+
+struct flexible
+{
+ int length;
+ int data[];
+};
+
+static struct flexible local_flexible =
+ {
+ .data = { [size - 1] = 0, }
+ };
+
+static struct flexible local_flexible_nonzero =
+ {
+ .length = size,
+ .data = { [size - 1] = 0, }
+ };
+
+struct flexible *
+get_local_flexible (void)
+{
+ return &local_flexible;
+}
+
+struct flexible *
+get_local_flexible_nonzero (void)
+{
+ return &local_flexible_nonzero;
+}
+
+/* We should not place the flexibly-sized objects in small data
+ sections, or generate gp-relative addresses for them. */
+
+/* { dg-final { scan-assembler-not "\\.sdata" } } */
+/* { dg-final { scan-assembler-not "\\.sbss" } } */
+/* { dg-final { scan-assembler-not "%gprel\(.*flexible.*\)" } } */
+
+
+
+
diff --git a/gcc/testsuite/gcc.target/nios2/pr92499-2.c b/gcc/testsuite/gcc.target/nios2/pr92499-2.c
new file mode 100644
index 00000000000..e253d0a056a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nios2/pr92499-2.c
@@ -0,0 +1,45 @@
+/* PR target/92499 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mgpopt=global -G8" } */
+
+/* Check placement and addressing of flexibly-sized objects with external
+ linkage. */
+
+enum { size = 100 };
+
+struct flexible
+{
+ int length;
+ int data[];
+};
+
+extern struct flexible global_flexible;
+struct flexible global_flexible =
+ {
+ .data = { [size - 1] = 0, }
+ };
+
+extern struct flexible global_flexible_nonzero;
+struct flexible global_flexible_nonzero =
+ {
+ .length = size,
+ .data = { [size - 1] = 0, }
+ };
+
+struct flexible *
+get_global_flexible (void)
+{
+ return &global_flexible;
+}
+
+struct flexible *
+get_global_flexible_nonzero (void)
+{
+ return &global_flexible_nonzero;
+}
+
+/* To preserve ABI compatibility we place the flexibly-sized objects in
+ small data sections. */
+
+/* { dg-final { scan-assembler-times "\\.sdata" 1 } } */
+/* { dg-final { scan-assembler-times "\\.sbss" 1 } } */
diff --git a/gcc/testsuite/gcc.target/nios2/pr92499-3.c b/gcc/testsuite/gcc.target/nios2/pr92499-3.c
new file mode 100644
index 00000000000..faeef050acf
--- /dev/null
+++ b/gcc/testsuite/gcc.target/nios2/pr92499-3.c
@@ -0,0 +1,23 @@
+/* PR target/92499 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mgpopt=global -G8" } */
+
+/* Check addressing of extern flexibly-sized objects. */
+
+struct flexible
+{
+ int length;
+ int data[];
+};
+
+extern struct flexible extern_flexible;
+
+struct flexible *
+get_extern_flexible (void)
+{
+ return &extern_flexible;
+}
+
+/* We should not generate GP-relative addresses for external objects of
+ unknown size. */
+/* { dg-final { scan-assembler-not "%gprel\(.*flexible.*\)" } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/pr72804.c b/gcc/testsuite/gcc.target/powerpc/pr72804.c
index 56a2452885e..d424bccd5c3 100644
--- a/gcc/testsuite/gcc.target/powerpc/pr72804.c
+++ b/gcc/testsuite/gcc.target/powerpc/pr72804.c
@@ -1,7 +1,6 @@
/* { dg-do compile { target { lp64 } } } */
-/* { dg-skip-if "" { powerpc*-*-darwin* } } */
/* { dg-require-effective-target powerpc_vsx_ok } */
-/* { dg-options "-O2 -mvsx -fno-inline-functions --param max-inline-insns-single=200" } */
+/* { dg-options "-O2 -mvsx"} */
__int128_t
foo (__int128_t *src)
@@ -9,17 +8,7 @@ foo (__int128_t *src)
return ~*src;
}
-void
-bar (__int128_t *dst, __int128_t src)
-{
- *dst = ~src;
-}
-/* { dg-final { scan-assembler-times "not " 4 } } */
-/* { dg-final { scan-assembler-times "std " 2 } } */
-/* { dg-final { scan-assembler-times "ld " 2 } } */
-/* { dg-final { scan-assembler-not "lxvd2x" } } */
-/* { dg-final { scan-assembler-not "stxvd2x" } } */
-/* { dg-final { scan-assembler-not "xxpermdi" } } */
-/* { dg-final { scan-assembler-not "mfvsrd" } } */
-/* { dg-final { scan-assembler-not "mfvsrd" } } */
+/* { dg-final { scan-assembler-times {\mld\M} 2 } } */
+/* { dg-final { scan-assembler-times {\mnot\M} 2 } } */
+/* { dg-final { scan-assembler-not {\mlxvd2x\M} } }*/
diff --git a/gcc/testsuite/gcc.target/powerpc/pr92398.h b/gcc/testsuite/gcc.target/powerpc/pr92398.h
new file mode 100644
index 00000000000..5a4a8bcab80
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr92398.h
@@ -0,0 +1,17 @@
+/* This test code is included into pr92398.p9-.c and pr92398.p9+.c.
+ The two files have the tests for the number of instructions generated for
+ P9- versus P9+.
+
+ store generates difference instructions as below:
+ P9+: mtvsrdd;xxlnot;stxv.
+ P8/P7/P6 LE: not;not;std;std.
+ P8 BE: mtvsrd;mtvsrd;xxpermdi;xxlnor;stxvd2x.
+ P7/P6 BE: std;std;addi;lxvd2x;xxlnor;stxvd2x.
+ P9+ and P9- LE are expected, P6/P7/P8 BE are unexpected. */
+
+void
+bar (__int128_t *dst, __int128_t src)
+{
+ *dst = ~src;
+}
+
diff --git a/gcc/testsuite/gcc.target/powerpc/pr92398.p9+.c b/gcc/testsuite/gcc.target/powerpc/pr92398.p9+.c
new file mode 100644
index 00000000000..a819c3f16af
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr92398.p9+.c
@@ -0,0 +1,12 @@
+/* { dg-do compile { target { lp64 && p9+ } } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mvsx" } */
+
+/* { dg-final { scan-assembler-times {\mmtvsrdd\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mxxlnor\M} 1 } } */
+/* { dg-final { scan-assembler-times {\mstxv\M} 1 } } */
+/* { dg-final { scan-assembler-not {\mld\M} } } */
+/* { dg-final { scan-assembler-not {\mnot\M} } } */
+
+/* Source code for the test in pr92398.h */
+#include "pr92398.h"
diff --git a/gcc/testsuite/gcc.target/powerpc/pr92398.p9-.c b/gcc/testsuite/gcc.target/powerpc/pr92398.p9-.c
new file mode 100644
index 00000000000..065ae73f267
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr92398.p9-.c
@@ -0,0 +1,10 @@
+/* { dg-do compile { target { lp64 && {! p9+} } } } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-O2 -mvsx" } */
+
+/* { dg-final { scan-assembler-times {\mnot\M} 2 { xfail be } } } */
+/* { dg-final { scan-assembler-times {\mstd\M} 2 { xfail { p8 && be } } } } */
+
+/* Source code for the test in pr92398.h */
+#include "pr92398.h"
+
diff --git a/gcc/testsuite/gfortran.dg/dec-comparison.f90 b/gcc/testsuite/gfortran.dg/dec-comparison.f90
index b0b28e55111..dee1e39ef9c 100644
--- a/gcc/testsuite/gfortran.dg/dec-comparison.f90
+++ b/gcc/testsuite/gfortran.dg/dec-comparison.f90
@@ -1,4 +1,4 @@
-! { dg-do run }
+! { dg-do compile }
! { dg-options "-fdec" }
!
! Test case contributed by Mark Eggleston <mark.eggleston@codethink.com>
@@ -38,4 +38,3 @@ program convert
if (a.ne.d) stop 17 ! { dg-error "Operands of comparison" }
if (d.eq.a) stop 18 ! { dg-error "Operands of comparison" }
end program
-
diff --git a/gcc/testsuite/gfortran.dg/dependency_56.f90 b/gcc/testsuite/gfortran.dg/dependency_56.f90
new file mode 100644
index 00000000000..97c0c814aed
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dependency_56.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+! PR 91783 - used to cause an ICE in dependency checking.
+! Test case by Gerhard Steinmetz.
+program p
+ class(*), allocatable :: a(:)
+ a = [1, 2, 3]
+ a = f(a)
+contains
+ function f(x) result(y)
+ class(*), allocatable, intent(in) :: x(:)
+ class(*), allocatable :: y(:)
+ y = x
+ end
+end
diff --git a/gcc/testsuite/gfortran.dg/fmt_zero_width.f90 b/gcc/testsuite/gfortran.dg/fmt_zero_width.f90
index 093c0a44c34..640b6735c65 100644
--- a/gcc/testsuite/gfortran.dg/fmt_zero_width.f90
+++ b/gcc/testsuite/gfortran.dg/fmt_zero_width.f90
@@ -1,11 +1,11 @@
! { dg-do run }
! PR90374 "5.5 d0.d, e0.d, es0.d, en0.d, g0.d and ew.d edit descriptors
program pr90374
+ implicit none
real(4) :: rn
character(32) :: afmt, aresult
- real(8) :: one = 1.0D0, zero = 0.0D0, nan, pinf, minf
+ real(8) :: one = 1.0D0, zero = 0.0D0, pinf, minf
- nan = zero/zero
rn = 0.00314_4
afmt = "(D0.3)"
write (aresult,fmt=afmt) rn
@@ -22,15 +22,19 @@ program pr90374
afmt = "(G0.10)"
write (aresult,fmt=afmt) rn
if (aresult /= "0.3139999928E-02") stop 24
+ afmt = "(E0.10e0)"
+ write (aresult,fmt=afmt) rn
+ if (aresult /= "0.3139999928E-02") stop 27
write (aresult,fmt="(D0.3)") rn
- if (aresult /= "0.314D-02") stop 26
+ if (aresult /= "0.314D-02") stop 29
write (aresult,fmt="(E0.10)") rn
- if (aresult /= "0.3139999928E-02") stop 28
+ if (aresult /= "0.3139999928E-02") stop 31
write (aresult,fmt="(ES0.10)") rn
- if (aresult /= "3.1399999280E-03") stop 30
+ if (aresult /= "3.1399999280E-03") stop 33
write (aresult,fmt="(EN0.10)") rn
- if (aresult /= "3.1399999280E-03") stop 32
+ if (aresult /= "3.1399999280E-03") stop 35
write (aresult,fmt="(G0.10)") rn
- if (aresult /= "0.3139999928E-02") stop 34
-
+ if (aresult /= "0.3139999928E-02") stop 37
+ write (aresult,fmt="(E0.10e0)") rn
+ if (aresult /= "0.3139999928E-02") stop 39
end
diff --git a/gcc/testsuite/gfortran.dg/goacc/common-block-3.f90 b/gcc/testsuite/gfortran.dg/goacc/common-block-3.f90
index 9032d9331f0..5defe2ea85d 100644
--- a/gcc/testsuite/gfortran.dg/goacc/common-block-3.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/common-block-3.f90
@@ -9,7 +9,7 @@ program main
implicit none
integer :: i, j
- real :: a(n) = 0, b(n) = 0, c, d
+ real :: a(n) = 0, b(n) = 0, c, d, e(n)
real :: x(n) = 0, y(n), z
common /BLOCK/ a, b, c, j, d
common /KERNELS_BLOCK/ x, y, z
@@ -35,5 +35,10 @@ end program main
! { dg-final { scan-tree-dump-times "omp target oacc_kernels .*map\\(tofrom:y \\\[len: 400\\\]\\\)" 1 "omplower" } }
! { dg-final { scan-tree-dump-times "omp target oacc_kernels .*map\\(force_tofrom:c \\\[len: 4\\\]\\)" 1 "omplower" } }
-! { dg-final { scan-tree-dump-not "map\\(.*:block\\)" "omplower" } }
-! { dg-final { scan-tree-dump-not "map\\(.*:kernels_block\\)" "omplower" } }
+! Expecting no mapping of un-referenced common-blocks variables
+
+! { dg-final { scan-tree-dump-not "map\\(.*:block" "omplower" } }
+! { dg-final { scan-tree-dump-not "map\\(.*:kernels_block" "omplower" } }
+! { dg-final { scan-tree-dump-not "map\\(.*:d " "omplower" } }
+! { dg-final { scan-tree-dump-not "map\\(.*:e " "omplower" } }
+! { dg-final { scan-tree-dump-not "map\\(.*:z " "omplower" } }
diff --git a/gcc/testsuite/gfortran.dg/goacc/pr84963.f90 b/gcc/testsuite/gfortran.dg/goacc/pr84963.f90
index 4548082bee3..481f20711f5 100644
--- a/gcc/testsuite/gfortran.dg/goacc/pr84963.f90
+++ b/gcc/testsuite/gfortran.dg/goacc/pr84963.f90
@@ -1,5 +1,5 @@
! PR ipa/84963
-! { dg-options "-O2" }
+! { dg-additional-options "-O2" }
program p
print *, sin([1.0, 2.0])
diff --git a/gcc/testsuite/gfortran.dg/loop_versioning_1.f90 b/gcc/testsuite/gfortran.dg/loop_versioning_1.f90
index 144a193d708..e80f8920d00 100644
--- a/gcc/testsuite/gfortran.dg/loop_versioning_1.f90
+++ b/gcc/testsuite/gfortran.dg/loop_versioning_1.f90
@@ -23,6 +23,6 @@ subroutine f3(x, limit, step)
end do
end subroutine f3
-! { dg-final { scan-tree-dump-times {likely to be the innermost dimension} 2 "lversion" } }
+! { dg-final { scan-tree-dump-times {likely to be the innermost dimension} 1 "lversion" } }
! { dg-final { scan-tree-dump-times {want to version containing loop} 3 "lversion" } }
! { dg-final { scan-tree-dump-times {versioned this loop} 3 "lversion" } }
diff --git a/gcc/testsuite/gfortran.dg/loop_versioning_10.f90 b/gcc/testsuite/gfortran.dg/loop_versioning_10.f90
index 5803527bb3c..3d921d6c993 100644
--- a/gcc/testsuite/gfortran.dg/loop_versioning_10.f90
+++ b/gcc/testsuite/gfortran.dg/loop_versioning_10.f90
@@ -26,6 +26,6 @@ subroutine f4(x, i)
end do
end subroutine f4
-! { dg-final { scan-tree-dump-times {likely to be the innermost dimension} 6 "lversion" } }
+! { dg-final { scan-tree-dump-times {likely to be the innermost dimension} 4 "lversion" } }
! { dg-final { scan-tree-dump-times {want to version} 4 "lversion" } }
! { dg-final { scan-tree-dump-times {versioned} 4 "lversion" } }
diff --git a/gcc/testsuite/gfortran.dg/loop_versioning_6.f90 b/gcc/testsuite/gfortran.dg/loop_versioning_6.f90
index 450a79c1fdf..163d225cb49 100644
--- a/gcc/testsuite/gfortran.dg/loop_versioning_6.f90
+++ b/gcc/testsuite/gfortran.dg/loop_versioning_6.f90
@@ -89,5 +89,7 @@ subroutine f9(x, limit, step)
end do
end subroutine f9
-! { dg-final { scan-tree-dump-times {want to version containing loop} 9 "lversion" } }
-! { dg-final { scan-tree-dump-times {versioned this loop} 9 "lversion" } }
+! { dg-final { scan-tree-dump-times {want to version containing loop} 9 "lversion" { target lp64 } } }
+! { dg-final { scan-tree-dump-times {versioned this loop} 9 "lversion" { target lp64 } } }
+! { dg-final { scan-tree-dump-times {want to version containing loop} 8 "lversion" { target { ! lp64 } } } }
+! { dg-final { scan-tree-dump-times {versioned this loop} 8 "lversion" { target { ! lp64 } } } }
diff --git a/gcc/testsuite/gfortran.dg/pr91003.f90 b/gcc/testsuite/gfortran.dg/pr91003.f90
new file mode 100644
index 00000000000..ed5063d6365
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr91003.f90
@@ -0,0 +1,33 @@
+! { dg-do compile }
+! { dg-options "-Ofast" }
+ SUBROUTINE FOO(N, A, B, C, D, E, F, G)
+ COMPLEX A(*)
+ LOGICAL H
+ INTEGER G
+ REAL I, C, J, F, F1, F2, K, E, L, M, B, D
+ DO JC = 1, N
+ K = F*REAL(A(JC))
+ Z = F*AIMAG(A(JC))
+ H = .FALSE.
+ L = G
+ IF(ABS(Z).LT.D .AND. I.GE. MAX(D, B*C, B*J)) THEN
+ H = .TRUE.
+ L = (D / F1) / MAX(D, F2*I)
+ END IF
+ IF(ABS(K).LT.D .AND. C.GE. MAX(D, B*I, B*J)) THEN
+ L = MAX(L, (D / F1) / MAX(D, F2*C))
+ END IF
+ IF(ABS(E).LT.D .AND. J.GE. MAX(D, B*C, B*I)) THEN
+ H = .TRUE.
+ L = MAX(L, (D / BNRM1) / MAX(D, BNRM2*J))
+ END IF
+ IF(H) THEN
+ M = (L*D)*MAX(ABS(K), ABS(Z), ABS(E))
+ END IF
+ IF(H) THEN
+ K = (L*REAL(A(JC)))*F
+ Z = (L*AIMAG(A(JC)))*F
+ END IF
+ A(JC) = CMPLX(K, Z)
+ END DO
+ END
diff --git a/gcc/testsuite/gfortran.dg/pr92629.f90 b/gcc/testsuite/gfortran.dg/pr92629.f90
new file mode 100644
index 00000000000..5c2267ca6f1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr92629.f90
@@ -0,0 +1,11 @@
+! { dg-do run }
+! { dg-options "-fno-range-check" }
+!
+! Test the fix for PR92629.
+program bge_tests
+ if (bge (huge (1_1), 128_1)) stop 1
+ if (bge ( 128_1 , 255_1)) stop 2
+ if (bge (huge (1_2), 32768_2)) stop 3
+ if (bge (huge (1_4), 2147483648_4)) stop 4
+ if (bge (huge (1_8), 9223372036854775808_8)) stop 5
+end program
diff --git a/gcc/testsuite/gfortran.dg/spread_size_limit_2.f90 b/gcc/testsuite/gfortran.dg/spread_size_limit_2.f90
new file mode 100644
index 00000000000..3ea064e267f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/spread_size_limit_2.f90
@@ -0,0 +1,11 @@
+! PR fortran/91944
+! { dg-do compile }
+! { dg-options "-fmax-array-constructor=65535" }
+
+program pr91944
+ integer, parameter :: n = 10
+ integer, parameter :: m = 65536
+ integer :: i
+ integer :: x(n,m) = spread([(i,i=1,n)], dim=2, ncopies=m) ! { dg-error "requires an increase of the allowed 65535 upper limit" }
+ print *, x(n,m)
+end
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 5fe1e83492c..5b4cc02f921 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -2585,6 +2585,26 @@ proc check_effective_target_le { } {
}]
}
+# Return 1 if we're generating code for only power8 platforms.
+
+proc check_effective_target_p8 { } {
+ return [check_no_compiler_messages_nocache p8 assembly {
+ #if !(!defined(_ARCH_PWR9) && defined(_ARCH_PWR8))
+ #error NO
+ #endif
+ } ""]
+}
+
+# Return 1 if we're generating code for power9 and future platforms.
+
+proc check_effective_target_p9+ { } {
+ return [check_no_compiler_messages_nocache p9+ assembly {
+ #if !(defined(_ARCH_PWR9))
+ #error NO
+ #endif
+ } ""]
+}
+
# Return 1 if we're generating 32-bit code using default options, 0
# otherwise.
@@ -5749,11 +5769,21 @@ proc check_effective_target_vect_bswap { } {
|| [istarget amdgcn-*-*] }}]
}
+# Return 1 if the target supports comparison of bool vectors for at
+# least one vector length.
+
+proc check_effective_target_vect_bool_cmp { } {
+ return [check_cached_effective_target_indexed vect_bool_cmp {
+ expr { [istarget i?86-*-*] || [istarget x86_64-*-*]
+ || [istarget aarch64*-*-*]
+ || [is-effective-target arm_neon] }}]
+}
+
# Return 1 if the target supports addition of char vectors for at least
# one vector length.
proc check_effective_target_vect_char_add { } {
- return [check_cached_effective_target_indexed vect_int {
+ return [check_cached_effective_target_indexed vect_char_add {
expr {
[istarget i?86-*-*] || [istarget x86_64-*-*]
|| ([istarget powerpc*-*-*]
diff --git a/gcc/testsuite/objc.dg/attributes/gnu2x-attr-syntax-1.m b/gcc/testsuite/objc.dg/attributes/gnu2x-attr-syntax-1.m
new file mode 100644
index 00000000000..7c727343075
--- /dev/null
+++ b/gcc/testsuite/objc.dg/attributes/gnu2x-attr-syntax-1.m
@@ -0,0 +1,5 @@
+/* Test C2x attribute syntax. Test empty attributes accepted. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu2x" } */
+
+#include "../../gcc.dg/c2x-attr-syntax-1.c"
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index eb268e32b2d..8e5179e6291 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -9551,6 +9551,7 @@ execute_fixup_cfg (void)
gimple_stmt_iterator gsi;
int todo = 0;
cgraph_node *node = cgraph_node::get (current_function_decl);
+ /* Same scaling is also done by ipa_merge_profiles. */
profile_count num = node->count;
profile_count den = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
bool scale = num.initialized_p () && !(num == den);
@@ -9664,7 +9665,10 @@ execute_fixup_cfg (void)
}
}
if (scale)
- compute_function_frequency ();
+ {
+ update_max_bb_count ();
+ compute_function_frequency ();
+ }
if (current_loops
&& (todo & TODO_cleanup_cfg))
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 12e078882da..f76f68d835d 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -695,9 +695,6 @@ enum tree_index {
TI_DFLOAT32_TYPE,
TI_DFLOAT64_TYPE,
TI_DFLOAT128_TYPE,
- TI_DFLOAT32_PTR_TYPE,
- TI_DFLOAT64_PTR_TYPE,
- TI_DFLOAT128_PTR_TYPE,
TI_VOID_LIST_NODE,
diff --git a/gcc/tree-if-conv.c b/gcc/tree-if-conv.c
index 33d6cddb460..d2e40d43373 100644
--- a/gcc/tree-if-conv.c
+++ b/gcc/tree-if-conv.c
@@ -2624,6 +2624,11 @@ combine_blocks (class loop *loop)
vphi = get_virtual_phi (bb);
if (vphi)
{
+ /* When there's just loads inside the loop a stray virtual
+ PHI merging the uses can appear, update last_vdef from
+ it. */
+ if (!last_vdef)
+ last_vdef = gimple_phi_arg_def (vphi, 0);
imm_use_iterator iter;
use_operand_p use_p;
gimple *use_stmt;
@@ -2655,6 +2660,10 @@ combine_blocks (class loop *loop)
if (gimple_vdef (stmt))
last_vdef = gimple_vdef (stmt);
}
+ else
+ /* If this is the first load we arrive at update last_vdef
+ so we handle stray PHIs correctly. */
+ last_vdef = gimple_vuse (stmt);
if (predicated[i])
{
ssa_op_iter i;
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index bdc332dcc23..720f50eefec 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1541,9 +1541,12 @@ remap_gimple_stmt (gimple *stmt, copy_body_data *id)
assignment to the equivalent of the original RESULT_DECL.
If RETVAL is just the result decl, the result decl has
already been set (e.g. a recent "foo (&result_decl, ...)");
- just toss the entire GIMPLE_RETURN. */
+ just toss the entire GIMPLE_RETURN. Likewise for when the
+ call doesn't want the return value. */
if (retval
&& (TREE_CODE (retval) != RESULT_DECL
+ && (!id->call_stmt
+ || gimple_call_lhs (id->call_stmt) != NULL_TREE)
&& (TREE_CODE (retval) != SSA_NAME
|| ! SSA_NAME_VAR (retval)
|| TREE_CODE (SSA_NAME_VAR (retval)) != RESULT_DECL)))
@@ -4623,7 +4626,8 @@ reset_debug_bindings (copy_body_data *id, gimple_stmt_iterator gsi)
/* If STMT is a GIMPLE_CALL, replace it with its inline expansion. */
static bool
-expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
+expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id,
+ bitmap to_purge)
{
tree use_retvar;
tree fn;
@@ -4768,7 +4772,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
gimple_call_set_fndecl (stmt, edge->callee->decl);
update_stmt (stmt);
id->src_node->remove ();
- expand_call_inline (bb, stmt, id);
+ expand_call_inline (bb, stmt, id, to_purge);
maybe_remove_unused_call_args (cfun, stmt);
return true;
}
@@ -5156,10 +5160,7 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
}
if (purge_dead_abnormal_edges)
- {
- gimple_purge_dead_eh_edges (return_block);
- gimple_purge_dead_abnormal_call_edges (return_block);
- }
+ bitmap_set_bit (to_purge, return_block->index);
/* If the value of the new expression is ignored, that's OK. We
don't warn about this for CALL_EXPRs, so we shouldn't warn about
@@ -5197,7 +5198,8 @@ expand_call_inline (basic_block bb, gimple *stmt, copy_body_data *id)
in a MODIFY_EXPR. */
static bool
-gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
+gimple_expand_calls_inline (basic_block bb, copy_body_data *id,
+ bitmap to_purge)
{
gimple_stmt_iterator gsi;
bool inlined = false;
@@ -5209,7 +5211,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
if (is_gimple_call (stmt)
&& !gimple_call_internal_p (stmt))
- inlined |= expand_call_inline (bb, stmt, id);
+ inlined |= expand_call_inline (bb, stmt, id, to_purge);
}
return inlined;
@@ -5222,6 +5224,7 @@ gimple_expand_calls_inline (basic_block bb, copy_body_data *id)
static void
fold_marked_statements (int first, hash_set<gimple *> *statements)
{
+ auto_bitmap to_purge;
for (; first < last_basic_block_for_fn (cfun); first++)
if (BASIC_BLOCK_FOR_FN (cfun, first))
{
@@ -5233,7 +5236,8 @@ fold_marked_statements (int first, hash_set<gimple *> *statements)
if (statements->contains (gsi_stmt (gsi)))
{
gimple *old_stmt = gsi_stmt (gsi);
- tree old_decl = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
+ tree old_decl
+ = is_gimple_call (old_stmt) ? gimple_call_fndecl (old_stmt) : 0;
if (old_decl && fndecl_built_in_p (old_decl))
{
@@ -5277,8 +5281,7 @@ fold_marked_statements (int first, hash_set<gimple *> *statements)
is mood anyway. */
if (maybe_clean_or_replace_eh_stmt (old_stmt,
new_stmt))
- gimple_purge_dead_eh_edges (
- BASIC_BLOCK_FOR_FN (cfun, first));
+ bitmap_set_bit (to_purge, first);
break;
}
gsi_next (&i2);
@@ -5298,11 +5301,11 @@ fold_marked_statements (int first, hash_set<gimple *> *statements)
new_stmt);
if (maybe_clean_or_replace_eh_stmt (old_stmt, new_stmt))
- gimple_purge_dead_eh_edges (BASIC_BLOCK_FOR_FN (cfun,
- first));
+ bitmap_set_bit (to_purge, first);
}
}
}
+ gimple_purge_all_dead_eh_edges (to_purge);
}
/* Expand calls to inline functions in the body of FN. */
@@ -5348,8 +5351,9 @@ optimize_inline_calls (tree fn)
will split id->current_basic_block, and the new blocks will
follow it; we'll trudge through them, processing their CALL_EXPRs
along the way. */
+ auto_bitmap to_purge;
FOR_EACH_BB_FN (bb, cfun)
- inlined_p |= gimple_expand_calls_inline (bb, &id);
+ inlined_p |= gimple_expand_calls_inline (bb, &id, to_purge);
pop_gimplify_context (NULL);
@@ -5369,6 +5373,21 @@ optimize_inline_calls (tree fn)
fold_marked_statements (last, id.statements_to_fold);
delete id.statements_to_fold;
+ /* Finally purge EH and abnormal edges from the call stmts we inlined.
+ We need to do this after fold_marked_statements since that may walk
+ the SSA use-def chain. */
+ unsigned i;
+ bitmap_iterator bi;
+ EXECUTE_IF_SET_IN_BITMAP (to_purge, 0, i, bi)
+ {
+ basic_block bb = BASIC_BLOCK_FOR_FN (cfun, i);
+ if (bb)
+ {
+ gimple_purge_dead_eh_edges (bb);
+ gimple_purge_dead_abnormal_call_edges (bb);
+ }
+ }
+
gcc_assert (!id.debug_stmts.exists ());
/* If we didn't inline into the function there is nothing to do. */
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 386406fbb38..36e6267cf55 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -2004,16 +2004,12 @@ get_bit_field_ref_def (tree val, enum tree_code &conv_code)
return NULL_TREE;
enum tree_code code = gimple_assign_rhs_code (def_stmt);
if (code == FLOAT_EXPR
- || code == FIX_TRUNC_EXPR)
+ || code == FIX_TRUNC_EXPR
+ || CONVERT_EXPR_CODE_P (code))
{
tree op1 = gimple_assign_rhs1 (def_stmt);
if (conv_code == ERROR_MARK)
- {
- if (maybe_ne (GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (val))),
- GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (op1)))))
- return NULL_TREE;
- conv_code = code;
- }
+ conv_code = code;
else if (conv_code != code)
return NULL_TREE;
if (TREE_CODE (op1) != SSA_NAME)
@@ -2034,25 +2030,25 @@ static bool
simplify_vector_constructor (gimple_stmt_iterator *gsi)
{
gimple *stmt = gsi_stmt (*gsi);
- tree op, op2, orig[2], type, elem_type;
+ tree op, orig[2], type, elem_type;
unsigned elem_size, i;
unsigned HOST_WIDE_INT nelts;
+ unsigned HOST_WIDE_INT refnelts;
enum tree_code conv_code;
constructor_elt *elt;
bool maybe_ident;
- gcc_checking_assert (gimple_assign_rhs_code (stmt) == CONSTRUCTOR);
-
op = gimple_assign_rhs1 (stmt);
type = TREE_TYPE (op);
- gcc_checking_assert (TREE_CODE (type) == VECTOR_TYPE);
+ gcc_checking_assert (TREE_CODE (op) == CONSTRUCTOR
+ && TREE_CODE (type) == VECTOR_TYPE);
- if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts))
+ if (!TYPE_VECTOR_SUBPARTS (type).is_constant (&nelts)
+ || uniform_vector_p (op))
return false;
elem_type = TREE_TYPE (type);
elem_size = TREE_INT_CST_LOW (TYPE_SIZE (elem_type));
- vec_perm_builder sel (nelts, nelts, 1);
orig[0] = NULL;
orig[1] = NULL;
conv_code = ERROR_MARK;
@@ -2061,6 +2057,7 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
tree one_nonconstant = NULL_TREE;
auto_vec<tree> constants;
constants.safe_grow_cleared (nelts);
+ auto_vec<std::pair<unsigned, unsigned>, 64> elts;
FOR_EACH_VEC_SAFE_ELT (CONSTRUCTOR_ELTS (op), i, elt)
{
tree ref, op1;
@@ -2077,9 +2074,9 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
&& VECTOR_TYPE_P (TREE_TYPE (ref))
&& useless_type_conversion_p (TREE_TYPE (op1),
TREE_TYPE (TREE_TYPE (ref)))
- && known_eq (bit_field_size (op1), elem_size)
&& constant_multiple_p (bit_field_offset (op1),
- elem_size, &elem))
+ bit_field_size (op1), &elem)
+ && TYPE_VECTOR_SUBPARTS (TREE_TYPE (ref)).is_constant (&refnelts))
{
unsigned int j;
for (j = 0; j < 2; ++j)
@@ -2098,11 +2095,9 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
if (j < 2)
{
orig[j] = ref;
- if (j)
- elem += nelts;
- if (elem != i)
+ if (elem != i || j != 0)
maybe_ident = false;
- sel.quick_push (elem);
+ elts.safe_push (std::make_pair (j, elem));
continue;
}
/* Else fallthru. */
@@ -2131,28 +2126,118 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
else if (!operand_equal_p (one_nonconstant, elt->value, 0))
return false;
}
- sel.quick_push (i + nelts);
+ elts.safe_push (std::make_pair (1, i));
maybe_ident = false;
}
if (i < nelts)
return false;
if (! orig[0]
- || ! VECTOR_TYPE_P (TREE_TYPE (orig[0]))
- || maybe_ne (TYPE_VECTOR_SUBPARTS (type),
- TYPE_VECTOR_SUBPARTS (TREE_TYPE (orig[0]))))
+ || ! VECTOR_TYPE_P (TREE_TYPE (orig[0])))
return false;
-
- tree tem;
- if (conv_code != ERROR_MARK
- && (! supportable_convert_operation (conv_code, type,
- TREE_TYPE (orig[0]),
- &tem, &conv_code)
- || conv_code == CALL_EXPR))
+ refnelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (orig[0])).to_constant ();
+ /* We currently do not handle larger destination vectors. */
+ if (refnelts < nelts)
return false;
if (maybe_ident)
{
+ tree conv_src_type
+ = (nelts != refnelts
+ ? (conv_code != ERROR_MARK
+ ? build_vector_type (TREE_TYPE (TREE_TYPE (orig[0])), nelts)
+ : type)
+ : TREE_TYPE (orig[0]));
+ if (conv_code != ERROR_MARK
+ && !supportable_convert_operation (conv_code, type, conv_src_type,
+ &conv_code))
+ {
+ /* Only few targets implement direct conversion patterns so try
+ some simple special cases via VEC_[UN]PACK[_FLOAT]_LO_EXPR. */
+ optab optab;
+ tree halfvectype, dblvectype;
+ if (CONVERT_EXPR_CODE_P (conv_code)
+ && (2 * TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig[0])))
+ == TYPE_PRECISION (TREE_TYPE (type)))
+ && mode_for_vector (as_a <scalar_mode>
+ (TYPE_MODE (TREE_TYPE (TREE_TYPE (orig[0])))),
+ nelts * 2).exists ()
+ && (dblvectype
+ = build_vector_type (TREE_TYPE (TREE_TYPE (orig[0])),
+ nelts * 2))
+ && (optab = optab_for_tree_code (FLOAT_TYPE_P (TREE_TYPE (type))
+ ? VEC_UNPACK_FLOAT_LO_EXPR
+ : VEC_UNPACK_LO_EXPR,
+ dblvectype,
+ optab_default))
+ && (optab_handler (optab, TYPE_MODE (dblvectype))
+ != CODE_FOR_nothing))
+ {
+ gimple_seq stmts = NULL;
+ tree dbl;
+ if (refnelts == nelts)
+ {
+ /* ??? Paradoxical subregs don't exist, so insert into
+ the lower half of a wider zero vector. */
+ dbl = gimple_build (&stmts, BIT_INSERT_EXPR, dblvectype,
+ build_zero_cst (dblvectype), orig[0],
+ bitsize_zero_node);
+ }
+ else if (refnelts == 2 * nelts)
+ dbl = orig[0];
+ else
+ dbl = gimple_build (&stmts, BIT_FIELD_REF, dblvectype,
+ orig[0], TYPE_SIZE (dblvectype),
+ bitsize_zero_node);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ gimple_assign_set_rhs_with_ops (gsi,
+ FLOAT_TYPE_P (TREE_TYPE (type))
+ ? VEC_UNPACK_FLOAT_LO_EXPR
+ : VEC_UNPACK_LO_EXPR,
+ dbl);
+ }
+ else if (CONVERT_EXPR_CODE_P (conv_code)
+ && (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (orig[0])))
+ == 2 * TYPE_PRECISION (TREE_TYPE (type)))
+ && mode_for_vector (as_a <scalar_mode>
+ (TYPE_MODE
+ (TREE_TYPE (TREE_TYPE (orig[0])))),
+ nelts / 2).exists ()
+ && (halfvectype
+ = build_vector_type (TREE_TYPE (TREE_TYPE (orig[0])),
+ nelts / 2))
+ && (optab = optab_for_tree_code (VEC_PACK_TRUNC_EXPR,
+ halfvectype,
+ optab_default))
+ && (optab_handler (optab, TYPE_MODE (halfvectype))
+ != CODE_FOR_nothing))
+ {
+ gimple_seq stmts = NULL;
+ tree low = gimple_build (&stmts, BIT_FIELD_REF, halfvectype,
+ orig[0], TYPE_SIZE (halfvectype),
+ bitsize_zero_node);
+ tree hig = gimple_build (&stmts, BIT_FIELD_REF, halfvectype,
+ orig[0], TYPE_SIZE (halfvectype),
+ TYPE_SIZE (halfvectype));
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ gimple_assign_set_rhs_with_ops (gsi, VEC_PACK_TRUNC_EXPR,
+ low, hig);
+ }
+ else
+ return false;
+ update_stmt (gsi_stmt (*gsi));
+ return true;
+ }
+ if (nelts != refnelts)
+ {
+ gassign *lowpart
+ = gimple_build_assign (make_ssa_name (conv_src_type),
+ build3 (BIT_FIELD_REF, conv_src_type,
+ orig[0], TYPE_SIZE (conv_src_type),
+ bitsize_zero_node));
+ gsi_insert_before (gsi, lowpart, GSI_SAME_STMT);
+ orig[0] = gimple_assign_lhs (lowpart);
+ }
if (conv_code == ERROR_MARK)
gimple_assign_set_rhs_from_tree (gsi, orig[0]);
else
@@ -2161,30 +2246,52 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
}
else
{
- tree mask_type;
+ tree mask_type, perm_type, conv_src_type;
+ perm_type = TREE_TYPE (orig[0]);
+ conv_src_type = (nelts == refnelts
+ ? perm_type
+ : build_vector_type (TREE_TYPE (perm_type), nelts));
+ if (conv_code != ERROR_MARK
+ && !supportable_convert_operation (conv_code, type, conv_src_type,
+ &conv_code))
+ return false;
- vec_perm_indices indices (sel, orig[1] ? 2 : 1, nelts);
- if (!can_vec_perm_const_p (TYPE_MODE (type), indices))
+ /* Now that we know the number of elements of the source build the
+ permute vector.
+ ??? When the second vector has constant values we can shuffle
+ it and its source indexes to make the permutation supported.
+ For now it mimics a blend. */
+ vec_perm_builder sel (refnelts, refnelts, 1);
+ for (i = 0; i < elts.length (); ++i)
+ sel.quick_push (elts[i].second + elts[i].first * refnelts);
+ /* And fill the tail with "something". It's really don't care,
+ and ideally we'd allow VEC_PERM to have a smaller destination
+ vector. */
+ for (; i < refnelts; ++i)
+ sel.quick_push (i - elts.length ());
+ vec_perm_indices indices (sel, orig[1] ? 2 : 1, refnelts);
+ if (!can_vec_perm_const_p (TYPE_MODE (perm_type), indices))
return false;
mask_type
= build_vector_type (build_nonstandard_integer_type (elem_size, 1),
- nelts);
+ refnelts);
if (GET_MODE_CLASS (TYPE_MODE (mask_type)) != MODE_VECTOR_INT
|| maybe_ne (GET_MODE_SIZE (TYPE_MODE (mask_type)),
- GET_MODE_SIZE (TYPE_MODE (type))))
+ GET_MODE_SIZE (TYPE_MODE (perm_type))))
return false;
- op2 = vec_perm_indices_to_tree (mask_type, indices);
- bool convert_orig0 = false;
+ tree op2 = vec_perm_indices_to_tree (mask_type, indices);
+ bool converted_orig1 = false;
+ gimple_seq stmts = NULL;
if (!orig[1])
orig[1] = orig[0];
else if (orig[1] == error_mark_node
&& one_nonconstant)
{
- gimple_seq seq = NULL;
- orig[1] = gimple_build_vector_from_val (&seq, UNKNOWN_LOCATION,
+ orig[1] = gimple_build_vector_from_val (&stmts, UNKNOWN_LOCATION,
type, one_nonconstant);
- gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
- convert_orig0 = true;
+ /* ??? We can see if we can safely convert to the original
+ element type. */
+ converted_orig1 = conv_code != ERROR_MARK;
}
else if (orig[1] == error_mark_node)
{
@@ -2196,30 +2303,45 @@ simplify_vector_constructor (gimple_stmt_iterator *gsi)
/* ??? Push a don't-care value. */
vec.quick_push (one_constant);
orig[1] = vec.build ();
- convert_orig0 = true;
+ /* ??? See if we can convert the vector to the original type. */
+ converted_orig1 = conv_code != ERROR_MARK;
}
- if (conv_code == ERROR_MARK)
- gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR, orig[0],
- orig[1], op2);
- else if (convert_orig0)
- {
- gimple *conv
- = gimple_build_assign (make_ssa_name (type), conv_code, orig[0]);
- orig[0] = gimple_assign_lhs (conv);
- gsi_insert_before (gsi, conv, GSI_SAME_STMT);
- gimple_assign_set_rhs_with_ops (gsi, VEC_PERM_EXPR,
- orig[0], orig[1], op2);
- }
- else
+ tree blend_op2 = NULL_TREE;
+ if (converted_orig1)
{
- gimple *perm
- = gimple_build_assign (make_ssa_name (TREE_TYPE (orig[0])),
- VEC_PERM_EXPR, orig[0], orig[1], op2);
- orig[0] = gimple_assign_lhs (perm);
- gsi_insert_before (gsi, perm, GSI_SAME_STMT);
- gimple_assign_set_rhs_with_ops (gsi, conv_code, orig[0],
- NULL_TREE, NULL_TREE);
+ /* Make sure we can do a blend in the target type. */
+ vec_perm_builder sel (nelts, nelts, 1);
+ for (i = 0; i < elts.length (); ++i)
+ sel.quick_push (elts[i].first
+ ? elts[i].second + nelts : i);
+ vec_perm_indices indices (sel, 2, nelts);
+ if (!can_vec_perm_const_p (TYPE_MODE (type), indices))
+ return false;
+ mask_type
+ = build_vector_type (build_nonstandard_integer_type (elem_size, 1),
+ nelts);
+ if (GET_MODE_CLASS (TYPE_MODE (mask_type)) != MODE_VECTOR_INT
+ || maybe_ne (GET_MODE_SIZE (TYPE_MODE (mask_type)),
+ GET_MODE_SIZE (TYPE_MODE (type))))
+ return false;
+ blend_op2 = vec_perm_indices_to_tree (mask_type, indices);
}
+ tree orig1_for_perm
+ = converted_orig1 ? build_zero_cst (perm_type) : orig[1];
+ tree res = gimple_build (&stmts, VEC_PERM_EXPR, perm_type,
+ orig[0], orig1_for_perm, op2);
+ if (nelts != refnelts)
+ res = gimple_build (&stmts, BIT_FIELD_REF,
+ conv_code != ERROR_MARK ? conv_src_type : type,
+ res, TYPE_SIZE (type), bitsize_zero_node);
+ if (conv_code != ERROR_MARK)
+ res = gimple_build (&stmts, conv_code, type, res);
+ /* Blend in the actual constant. */
+ if (converted_orig1)
+ res = gimple_build (&stmts, VEC_PERM_EXPR, type,
+ res, orig[1], blend_op2);
+ gsi_insert_seq_before (gsi, stmts, GSI_SAME_STMT);
+ gimple_assign_set_rhs_with_ops (gsi, SSA_NAME, res);
}
update_stmt (gsi_stmt (*gsi));
return true;
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 90583096c94..1ae925dc570 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -1381,7 +1381,8 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
/* Turn EQ/NE of extreme values to order comparisons. */
if ((cmp == NE_EXPR || cmp == EQ_EXPR)
- && TREE_CODE (rhs) == INTEGER_CST)
+ && TREE_CODE (rhs) == INTEGER_CST
+ && INTEGRAL_TYPE_P (TREE_TYPE (rhs)))
{
if (wi::eq_p (wi::to_wide (rhs), wi::min_value (TREE_TYPE (rhs))))
{
@@ -1407,7 +1408,8 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
larger = rhs;
/* If we have smaller < CST it is equivalent to smaller <= CST-1.
Likewise smaller <= CST is equivalent to smaller < CST+1. */
- if (TREE_CODE (larger) == INTEGER_CST)
+ if (TREE_CODE (larger) == INTEGER_CST
+ && INTEGRAL_TYPE_P (TREE_TYPE (larger)))
{
if (cmp == LT_EXPR)
{
@@ -1435,7 +1437,8 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
larger = gimple_cond_lhs (cond);
/* If we have larger > CST it is equivalent to larger >= CST+1.
Likewise larger >= CST is equivalent to larger > CST-1. */
- if (TREE_CODE (smaller) == INTEGER_CST)
+ if (TREE_CODE (smaller) == INTEGER_CST
+ && INTEGRAL_TYPE_P (TREE_TYPE (smaller)))
{
wi::overflow_type overflow;
if (cmp == GT_EXPR)
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 8e395675c66..8a7e0475ff8 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -1753,6 +1753,12 @@ void *
vn_walk_cb_data::push_partial_def (const pd_data &pd, tree vuse,
HOST_WIDE_INT maxsizei)
{
+ const HOST_WIDE_INT bufsize = 64;
+ /* We're using a fixed buffer for encoding so fail early if the object
+ we want to interpret is bigger. */
+ if (maxsizei > bufsize * BITS_PER_UNIT)
+ return (void *)-1;
+
if (partial_defs.is_empty ())
{
partial_defs.safe_push (pd);
@@ -1823,16 +1829,17 @@ vn_walk_cb_data::push_partial_def (const pd_data &pd, tree vuse,
/* Now simply native encode all partial defs in reverse order. */
unsigned ndefs = partial_defs.length ();
/* We support up to 512-bit values (for V8DFmode). */
- unsigned char buffer[64];
+ unsigned char buffer[bufsize];
int len;
while (!partial_defs.is_empty ())
{
pd_data pd = partial_defs.pop ();
+ gcc_checking_assert (pd.offset < bufsize);
if (TREE_CODE (pd.rhs) == CONSTRUCTOR)
/* Empty CONSTRUCTOR. */
memset (buffer + MAX (0, pd.offset),
- 0, MIN ((HOST_WIDE_INT)sizeof (buffer) - MAX (0, pd.offset),
+ 0, MIN (bufsize - MAX (0, pd.offset),
pd.size + MIN (0, pd.offset)));
else
{
@@ -1847,7 +1854,7 @@ vn_walk_cb_data::push_partial_def (const pd_data &pd, tree vuse,
pad = GET_MODE_SIZE (mode) - pd.size;
}
len = native_encode_expr (pd.rhs, buffer + MAX (0, pd.offset),
- sizeof (buffer) - MAX (0, pd.offset),
+ bufsize - MAX (0, pd.offset),
MAX (0, -pd.offset) + pad);
if (len <= 0 || len < (pd.size - MAX (0, -pd.offset)))
{
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index 06fa99eb5ac..d46586a90e5 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -4300,7 +4300,8 @@ count_nonzero_bytes (tree exp, unsigned lenrange[3], bool *nulterm,
/* Handle a single or multibyte store other than by a built-in function,
either via a single character assignment or by multi-byte assignment
either via MEM_REF or via a type other than char (such as in
- '*(int*)a = 12345'). Return true when handled. */
+ '*(int*)a = 12345'). Return true to let the caller advance *GSI to
+ the next statement in the basic block and false otherwise. */
static bool
handle_store (gimple_stmt_iterator *gsi, bool *zero_write, const vr_values *rvals)
@@ -4728,8 +4729,8 @@ is_char_type (tree type)
}
/* Check the built-in call at GSI for validity and optimize it.
- Return true to let the caller advance *GSI to the statement
- in the CFG and false otherwise. */
+ Return true to let the caller advance *GSI to the next statement
+ in the basic block and false otherwise. */
static bool
strlen_check_and_optimize_call (gimple_stmt_iterator *gsi,
@@ -4738,16 +4739,13 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi,
{
gimple *stmt = gsi_stmt (*gsi);
+ /* When not optimizing we must be checking printf calls which
+ we do even for user-defined functions when they are declared
+ with attribute format. */
if (!flag_optimize_strlen
|| !strlen_optimize
|| !valid_builtin_call (stmt))
- {
- /* When not optimizing we must be checking printf calls which
- we do even for user-defined functions when they are declared
- with attribute format. */
- handle_printf_call (gsi, rvals);
- return true;
- }
+ return !handle_printf_call (gsi, rvals);
tree callee = gimple_call_fndecl (stmt);
switch (DECL_FUNCTION_CODE (callee))
@@ -4806,7 +4804,8 @@ strlen_check_and_optimize_call (gimple_stmt_iterator *gsi,
return false;
break;
default:
- handle_printf_call (gsi, rvals);
+ if (handle_printf_call (gsi, rvals))
+ return false;
break;
}
@@ -4932,7 +4931,8 @@ handle_integral_assign (gimple_stmt_iterator *gsi, bool *cleanup_eh)
/* Attempt to check for validity of the performed access a single statement
at *GSI using string length knowledge, and to optimize it.
If the given basic block needs clean-up of EH, CLEANUP_EH is set to
- true. */
+ true. Return true to let the caller advance *GSI to the next statement
+ in the basic block and false otherwise. */
static bool
check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
@@ -4973,32 +4973,32 @@ check_and_optimize_stmt (gimple_stmt_iterator *gsi, bool *cleanup_eh,
/* Handle assignment to a character. */
handle_integral_assign (gsi, cleanup_eh);
else if (TREE_CODE (lhs) != SSA_NAME && !TREE_SIDE_EFFECTS (lhs))
- {
- tree type = TREE_TYPE (lhs);
- if (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
+ {
+ tree type = TREE_TYPE (lhs);
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
- bool is_char_store = is_char_type (type);
- if (!is_char_store && TREE_CODE (lhs) == MEM_REF)
- {
- /* To consider stores into char objects via integer types
- other than char but not those to non-character objects,
- determine the type of the destination rather than just
- the type of the access. */
- tree ref = TREE_OPERAND (lhs, 0);
- type = TREE_TYPE (ref);
- if (TREE_CODE (type) == POINTER_TYPE)
- type = TREE_TYPE (type);
- if (TREE_CODE (type) == ARRAY_TYPE)
- type = TREE_TYPE (type);
- if (is_char_type (type))
- is_char_store = true;
- }
+ bool is_char_store = is_char_type (type);
+ if (!is_char_store && TREE_CODE (lhs) == MEM_REF)
+ {
+ /* To consider stores into char objects via integer types
+ other than char but not those to non-character objects,
+ determine the type of the destination rather than just
+ the type of the access. */
+ tree ref = TREE_OPERAND (lhs, 0);
+ type = TREE_TYPE (ref);
+ if (TREE_CODE (type) == POINTER_TYPE)
+ type = TREE_TYPE (type);
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+ if (is_char_type (type))
+ is_char_store = true;
+ }
- /* Handle a single or multibyte assignment. */
- if (is_char_store && !handle_store (gsi, &zero_write, rvals))
- return false;
- }
+ /* Handle a single or multibyte assignment. */
+ if (is_char_store && !handle_store (gsi, &zero_write, rvals))
+ return false;
+ }
}
else if (gcond *cond = dyn_cast<gcond *> (stmt))
{
diff --git a/gcc/tree-vect-generic.c b/gcc/tree-vect-generic.c
index 091226533e7..7ec6b5fc51e 100644
--- a/gcc/tree-vect-generic.c
+++ b/gcc/tree-vect-generic.c
@@ -1697,7 +1697,6 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
gimple *g;
tree lhs = gimple_call_lhs (stmt);
tree arg = gimple_call_arg (stmt, 0);
- tree decl = NULL_TREE;
tree ret_type = TREE_TYPE (lhs);
tree arg_type = TREE_TYPE (arg);
tree new_rhs, compute_type = TREE_TYPE (arg_type);
@@ -1724,16 +1723,9 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
if (modifier == NONE && (code == FIX_TRUNC_EXPR || code == FLOAT_EXPR))
{
- if (supportable_convert_operation (code, ret_type, arg_type, &decl,
- &code1))
+ if (supportable_convert_operation (code, ret_type, arg_type, &code1))
{
- if (code1 == CALL_EXPR)
- {
- g = gimple_build_call (decl, 1, arg);
- gimple_call_set_lhs (g, lhs);
- }
- else
- g = gimple_build_assign (lhs, code1, arg);
+ g = gimple_build_assign (lhs, code1, arg);
gsi_replace (gsi, g, false);
return;
}
@@ -1752,11 +1744,11 @@ expand_vector_conversion (gimple_stmt_iterator *gsi)
tree ret1_type = build_vector_type (TREE_TYPE (ret_type), nelts);
tree arg1_type = build_vector_type (TREE_TYPE (arg_type), nelts);
if (supportable_convert_operation (code, ret1_type, arg1_type,
- &decl, &code1))
+ &code1))
{
new_rhs = expand_vector_piecewise (gsi, do_vec_conversion,
ret_type, arg1_type, arg,
- decl, code1);
+ NULL_TREE, code1);
g = gimple_build_assign (lhs, new_rhs);
gsi_replace (gsi, g, false);
return;
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index ca8c8187f60..77c5a9816e2 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -163,8 +163,7 @@ static stmt_vec_info vect_is_simple_reduction (loop_vec_info, stmt_vec_info,
static opt_result
vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info,
bool vectype_maybe_set_p,
- poly_uint64 *vf,
- vec<stmt_vec_info > *mask_producers)
+ poly_uint64 *vf)
{
gimple *stmt = stmt_info->stmt;
@@ -192,8 +191,6 @@ vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info,
gcc_assert ((STMT_VINFO_DATA_REF (stmt_info)
|| vectype_maybe_set_p)
&& STMT_VINFO_VECTYPE (stmt_info) == stmt_vectype);
- else if (stmt_vectype == boolean_type_node)
- mask_producers->safe_push (stmt_info);
else
STMT_VINFO_VECTYPE (stmt_info) = stmt_vectype;
}
@@ -206,21 +203,17 @@ vect_determine_vf_for_stmt_1 (stmt_vec_info stmt_info,
/* Subroutine of vect_determine_vectorization_factor. Set the vector
types of STMT_INFO and all attached pattern statements and update
- the vectorization factor VF accordingly. If some of the statements
- produce a mask result whose vector type can only be calculated later,
- add them to MASK_PRODUCERS. Return true on success or false if
- something prevented vectorization. */
+ the vectorization factor VF accordingly. Return true on success
+ or false if something prevented vectorization. */
static opt_result
-vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
- vec<stmt_vec_info > *mask_producers)
+vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf)
{
vec_info *vinfo = stmt_info->vinfo;
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "==> examining statement: %G",
stmt_info->stmt);
- opt_result res
- = vect_determine_vf_for_stmt_1 (stmt_info, false, vf, mask_producers);
+ opt_result res = vect_determine_vf_for_stmt_1 (stmt_info, false, vf);
if (!res)
return res;
@@ -239,10 +232,7 @@ vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
dump_printf_loc (MSG_NOTE, vect_location,
"==> examining pattern def stmt: %G",
def_stmt_info->stmt);
- if (!vect_determine_vf_for_stmt_1 (def_stmt_info, true,
- vf, mask_producers))
- res = vect_determine_vf_for_stmt_1 (def_stmt_info, true,
- vf, mask_producers);
+ res = vect_determine_vf_for_stmt_1 (def_stmt_info, true, vf);
if (!res)
return res;
}
@@ -251,7 +241,7 @@ vect_determine_vf_for_stmt (stmt_vec_info stmt_info, poly_uint64 *vf,
dump_printf_loc (MSG_NOTE, vect_location,
"==> examining pattern statement: %G",
stmt_info->stmt);
- res = vect_determine_vf_for_stmt_1 (stmt_info, true, vf, mask_producers);
+ res = vect_determine_vf_for_stmt_1 (stmt_info, true, vf);
if (!res)
return res;
}
@@ -296,7 +286,6 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
tree vectype;
stmt_vec_info stmt_info;
unsigned i;
- auto_vec<stmt_vec_info> mask_producers;
DUMP_VECT_SCOPE ("vect_determine_vectorization_factor");
@@ -354,8 +343,7 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
{
stmt_info = loop_vinfo->lookup_stmt (gsi_stmt (si));
opt_result res
- = vect_determine_vf_for_stmt (stmt_info, &vectorization_factor,
- &mask_producers);
+ = vect_determine_vf_for_stmt (stmt_info, &vectorization_factor);
if (!res)
return res;
}
@@ -373,16 +361,6 @@ vect_determine_vectorization_factor (loop_vec_info loop_vinfo)
return opt_result::failure_at (vect_location,
"not vectorized: unsupported data-type\n");
LOOP_VINFO_VECT_FACTOR (loop_vinfo) = vectorization_factor;
-
- for (i = 0; i < mask_producers.length (); i++)
- {
- stmt_info = mask_producers[i];
- opt_tree mask_type = vect_get_mask_type_for_stmt (stmt_info);
- if (!mask_type)
- return opt_result::propagate_failure (mask_type);
- STMT_VINFO_VECTYPE (stmt_info) = mask_type;
- }
-
return opt_result::success ();
}
@@ -1851,7 +1829,10 @@ vect_dissolve_slp_only_groups (loop_vec_info loop_vinfo)
DR_GROUP_FIRST_ELEMENT (vinfo) = vinfo;
DR_GROUP_NEXT_ELEMENT (vinfo) = NULL;
DR_GROUP_SIZE (vinfo) = 1;
- DR_GROUP_GAP (vinfo) = group_size - 1;
+ if (STMT_VINFO_STRIDED_P (first_element))
+ DR_GROUP_GAP (vinfo) = 0;
+ else
+ DR_GROUP_GAP (vinfo) = group_size - 1;
vinfo = next;
}
}
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index e4cfe858163..2e021287b4e 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -112,7 +112,12 @@ vect_init_pattern_stmt (gimple *pattern_stmt, stmt_vec_info orig_stmt_info,
STMT_VINFO_DEF_TYPE (pattern_stmt_info)
= STMT_VINFO_DEF_TYPE (orig_stmt_info);
if (!STMT_VINFO_VECTYPE (pattern_stmt_info))
- STMT_VINFO_VECTYPE (pattern_stmt_info) = vectype;
+ {
+ gcc_assert (VECTOR_BOOLEAN_TYPE_P (vectype)
+ == vect_use_mask_type_p (orig_stmt_info));
+ STMT_VINFO_VECTYPE (pattern_stmt_info) = vectype;
+ pattern_stmt_info->mask_precision = orig_stmt_info->mask_precision;
+ }
return pattern_stmt_info;
}
@@ -131,17 +136,25 @@ vect_set_pattern_stmt (gimple *pattern_stmt, stmt_vec_info orig_stmt_info,
/* Add NEW_STMT to STMT_INFO's pattern definition statements. If VECTYPE
is nonnull, record that NEW_STMT's vector type is VECTYPE, which might
- be different from the vector type of the final pattern statement. */
+ be different from the vector type of the final pattern statement.
+ If VECTYPE is a mask type, SCALAR_TYPE_FOR_MASK is the scalar type
+ from which it was derived. */
static inline void
append_pattern_def_seq (stmt_vec_info stmt_info, gimple *new_stmt,
- tree vectype = NULL_TREE)
+ tree vectype = NULL_TREE,
+ tree scalar_type_for_mask = NULL_TREE)
{
+ gcc_assert (!scalar_type_for_mask
+ == (!vectype || !VECTOR_BOOLEAN_TYPE_P (vectype)));
vec_info *vinfo = stmt_info->vinfo;
if (vectype)
{
stmt_vec_info new_stmt_info = vinfo->add_stmt (new_stmt);
STMT_VINFO_VECTYPE (new_stmt_info) = vectype;
+ if (scalar_type_for_mask)
+ new_stmt_info->mask_precision
+ = GET_MODE_BITSIZE (SCALAR_TYPE_MODE (scalar_type_for_mask));
}
gimple_seq_add_stmt_without_update (&STMT_VINFO_PATTERN_DEF_SEQ (stmt_info),
new_stmt);
@@ -3886,107 +3899,22 @@ adjust_bool_stmts (hash_set <gimple *> &bool_stmt_set,
return gimple_assign_lhs (pattern_stmt);
}
-/* Helper for search_type_for_mask. */
+/* Return the proper type for converting bool VAR into
+ an integer value or NULL_TREE if no such type exists.
+ The type is chosen so that the converted value has the
+ same number of elements as VAR's vector type. */
static tree
-search_type_for_mask_1 (tree var, vec_info *vinfo,
- hash_map<gimple *, tree> &cache)
+integer_type_for_mask (tree var, vec_info *vinfo)
{
- tree rhs1;
- enum tree_code rhs_code;
- tree res = NULL_TREE, res2;
-
if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (var)))
return NULL_TREE;
stmt_vec_info def_stmt_info = vect_get_internal_def (vinfo, var);
- if (!def_stmt_info)
+ if (!def_stmt_info || !vect_use_mask_type_p (def_stmt_info))
return NULL_TREE;
- gassign *def_stmt = dyn_cast <gassign *> (def_stmt_info->stmt);
- if (!def_stmt)
- return NULL_TREE;
-
- tree *c = cache.get (def_stmt);
- if (c)
- return *c;
-
- rhs_code = gimple_assign_rhs_code (def_stmt);
- rhs1 = gimple_assign_rhs1 (def_stmt);
-
- switch (rhs_code)
- {
- case SSA_NAME:
- case BIT_NOT_EXPR:
- CASE_CONVERT:
- res = search_type_for_mask_1 (rhs1, vinfo, cache);
- break;
-
- case BIT_AND_EXPR:
- case BIT_IOR_EXPR:
- case BIT_XOR_EXPR:
- res = search_type_for_mask_1 (rhs1, vinfo, cache);
- res2 = search_type_for_mask_1 (gimple_assign_rhs2 (def_stmt), vinfo,
- cache);
- if (!res || (res2 && TYPE_PRECISION (res) > TYPE_PRECISION (res2)))
- res = res2;
- break;
-
- default:
- if (TREE_CODE_CLASS (rhs_code) == tcc_comparison)
- {
- tree comp_vectype, mask_type;
-
- if (VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1)))
- {
- res = search_type_for_mask_1 (rhs1, vinfo, cache);
- res2 = search_type_for_mask_1 (gimple_assign_rhs2 (def_stmt),
- vinfo, cache);
- if (!res || (res2 && TYPE_PRECISION (res) > TYPE_PRECISION (res2)))
- res = res2;
- break;
- }
-
- comp_vectype = get_vectype_for_scalar_type (vinfo, TREE_TYPE (rhs1));
- if (comp_vectype == NULL_TREE)
- {
- res = NULL_TREE;
- break;
- }
-
- mask_type = get_mask_type_for_scalar_type (vinfo, TREE_TYPE (rhs1));
- if (!mask_type
- || !expand_vec_cmp_expr_p (comp_vectype, mask_type, rhs_code))
- {
- res = NULL_TREE;
- break;
- }
-
- if (TREE_CODE (TREE_TYPE (rhs1)) != INTEGER_TYPE
- || !TYPE_UNSIGNED (TREE_TYPE (rhs1)))
- {
- scalar_mode mode = SCALAR_TYPE_MODE (TREE_TYPE (rhs1));
- res = build_nonstandard_integer_type (GET_MODE_BITSIZE (mode), 1);
- }
- else
- res = TREE_TYPE (rhs1);
- }
- }
-
- cache.put (def_stmt, res);
- return res;
-}
-
-/* Return the proper type for converting bool VAR into
- an integer value or NULL_TREE if no such type exists.
- The type is chosen so that converted value has the
- same number of elements as VAR's vector type. */
-
-static tree
-search_type_for_mask (tree var, vec_info *vinfo)
-{
- hash_map<gimple *, tree> cache;
- return search_type_for_mask_1 (var, vinfo, cache);
+ return build_nonstandard_integer_type (def_stmt_info->mask_precision, 1);
}
/* Function vect_recog_bool_pattern
@@ -4078,7 +4006,7 @@ vect_recog_bool_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
}
else
{
- tree type = search_type_for_mask (var, vinfo);
+ tree type = integer_type_for_mask (var, vinfo);
tree cst0, cst1, tmp;
if (!type)
@@ -4163,7 +4091,7 @@ vect_recog_bool_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
rhs = adjust_bool_stmts (bool_stmts, TREE_TYPE (vectype), stmt_vinfo);
else
{
- tree type = search_type_for_mask (var, vinfo);
+ tree type = integer_type_for_mask (var, vinfo);
tree cst0, cst1, new_vectype;
if (!type)
@@ -4218,7 +4146,7 @@ build_mask_conversion (tree mask, tree vectype, stmt_vec_info stmt_vinfo)
masktype = truth_type_for (vectype);
tmp = vect_recog_temp_ssa_var (TREE_TYPE (masktype), NULL);
stmt = gimple_build_assign (tmp, CONVERT_EXPR, mask);
- append_pattern_def_seq (stmt_vinfo, stmt, masktype);
+ append_pattern_def_seq (stmt_vinfo, stmt, masktype, TREE_TYPE (vectype));
return tmp;
}
@@ -4284,7 +4212,7 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
}
tree mask_arg = gimple_call_arg (last_stmt, mask_argno);
- tree mask_arg_type = search_type_for_mask (mask_arg, vinfo);
+ tree mask_arg_type = integer_type_for_mask (mask_arg, vinfo);
if (!mask_arg_type)
return NULL;
vectype2 = get_mask_type_for_scalar_type (vinfo, mask_arg_type);
@@ -4337,7 +4265,7 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
if (TREE_CODE (rhs1) == SSA_NAME)
{
- rhs1_type = search_type_for_mask (rhs1, vinfo);
+ rhs1_type = integer_type_for_mask (rhs1, vinfo);
if (!rhs1_type)
return NULL;
}
@@ -4357,7 +4285,7 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
it is better for b1 and b2 to use the mask type associated
with int elements rather bool (byte) elements. */
- rhs1_type = search_type_for_mask (TREE_OPERAND (rhs1, 0), vinfo);
+ rhs1_type = integer_type_for_mask (TREE_OPERAND (rhs1, 0), vinfo);
if (!rhs1_type)
rhs1_type = TREE_TYPE (TREE_OPERAND (rhs1, 0));
}
@@ -4413,7 +4341,8 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
tmp = vect_recog_temp_ssa_var (TREE_TYPE (rhs1), NULL);
pattern_stmt = gimple_build_assign (tmp, rhs1);
rhs1 = tmp;
- append_pattern_def_seq (stmt_vinfo, pattern_stmt, vectype2);
+ append_pattern_def_seq (stmt_vinfo, pattern_stmt, vectype2,
+ rhs1_type);
}
if (maybe_ne (TYPE_VECTOR_SUBPARTS (vectype1),
@@ -4446,8 +4375,8 @@ vect_recog_mask_conversion_pattern (stmt_vec_info stmt_vinfo, tree *type_out)
rhs2 = gimple_assign_rhs2 (last_stmt);
- rhs1_type = search_type_for_mask (rhs1, vinfo);
- rhs2_type = search_type_for_mask (rhs2, vinfo);
+ rhs1_type = integer_type_for_mask (rhs1, vinfo);
+ rhs2_type = integer_type_for_mask (rhs2, vinfo);
if (!rhs1_type || !rhs2_type
|| TYPE_PRECISION (rhs1_type) == TYPE_PRECISION (rhs2_type))
@@ -4508,7 +4437,7 @@ static tree
vect_convert_mask_for_vectype (tree mask, tree vectype,
stmt_vec_info stmt_info, vec_info *vinfo)
{
- tree mask_type = search_type_for_mask (mask, vinfo);
+ tree mask_type = integer_type_for_mask (mask, vinfo);
if (mask_type)
{
tree mask_vectype = get_mask_type_for_scalar_type (vinfo, mask_type);
@@ -4948,6 +4877,148 @@ vect_determine_precisions_from_users (stmt_vec_info stmt_info, gassign *stmt)
vect_set_min_input_precision (stmt_info, type, min_input_precision);
}
+/* Return true if the statement described by STMT_INFO sets a boolean
+ SSA_NAME and if we know how to vectorize this kind of statement using
+ vector mask types. */
+
+static bool
+possible_vector_mask_operation_p (stmt_vec_info stmt_info)
+{
+ tree lhs = gimple_get_lhs (stmt_info->stmt);
+ if (!lhs
+ || TREE_CODE (lhs) != SSA_NAME
+ || !VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (lhs)))
+ return false;
+
+ if (gassign *assign = dyn_cast <gassign *> (stmt_info->stmt))
+ {
+ tree_code rhs_code = gimple_assign_rhs_code (assign);
+ switch (rhs_code)
+ {
+ CASE_CONVERT:
+ case SSA_NAME:
+ case BIT_NOT_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_AND_EXPR:
+ return true;
+
+ default:
+ return TREE_CODE_CLASS (rhs_code) == tcc_comparison;
+ }
+ }
+ return false;
+}
+
+/* If STMT_INFO sets a boolean SSA_NAME, see whether we should use
+ a vector mask type instead of a normal vector type. Record the
+ result in STMT_INFO->mask_precision. */
+
+static void
+vect_determine_mask_precision (stmt_vec_info stmt_info)
+{
+ vec_info *vinfo = stmt_info->vinfo;
+
+ if (!possible_vector_mask_operation_p (stmt_info)
+ || stmt_info->mask_precision)
+ return;
+
+ auto_vec<stmt_vec_info, 32> worklist;
+ worklist.quick_push (stmt_info);
+ while (!worklist.is_empty ())
+ {
+ stmt_info = worklist.last ();
+ unsigned int orig_length = worklist.length ();
+
+ /* If at least one boolean input uses a vector mask type,
+ pick the mask type with the narrowest elements.
+
+ ??? This is the traditional behavior. It should always produce
+ the smallest number of operations, but isn't necessarily the
+ optimal choice. For example, if we have:
+
+ a = b & c
+
+ where:
+
+ - the user of a wants it to have a mask type for 16-bit elements (M16)
+ - b also uses M16
+ - c uses a mask type for 8-bit elements (M8)
+
+ then picking M8 gives:
+
+ - 1 M16->M8 pack for b
+ - 1 M8 AND for a
+ - 2 M8->M16 unpacks for the user of a
+
+ whereas picking M16 would have given:
+
+ - 2 M8->M16 unpacks for c
+ - 2 M16 ANDs for a
+
+ The number of operations are equal, but M16 would have given
+ a shorter dependency chain and allowed more ILP. */
+ unsigned int precision = ~0U;
+ gassign *assign = as_a <gassign *> (stmt_info->stmt);
+ unsigned int nops = gimple_num_ops (assign);
+ for (unsigned int i = 1; i < nops; ++i)
+ {
+ tree rhs = gimple_op (assign, i);
+ if (!VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (rhs)))
+ continue;
+
+ stmt_vec_info def_stmt_info = vinfo->lookup_def (rhs);
+ if (!def_stmt_info)
+ /* Don't let external or constant operands influence the choice.
+ We can convert them to whichever vector type we pick. */
+ continue;
+
+ if (def_stmt_info->mask_precision)
+ {
+ if (precision > def_stmt_info->mask_precision)
+ precision = def_stmt_info->mask_precision;
+ }
+ else if (possible_vector_mask_operation_p (def_stmt_info))
+ worklist.safe_push (def_stmt_info);
+ }
+
+ /* Defer the choice if we need to visit operands first. */
+ if (orig_length != worklist.length ())
+ continue;
+
+ /* If the statement compares two values that shouldn't use vector masks,
+ try comparing the values as normal scalars instead. */
+ tree_code rhs_code = gimple_assign_rhs_code (assign);
+ if (precision == ~0U
+ && TREE_CODE_CLASS (rhs_code) == tcc_comparison)
+ {
+ tree rhs1_type = TREE_TYPE (gimple_assign_rhs1 (assign));
+ scalar_mode mode;
+ tree vectype, mask_type;
+ if (is_a <scalar_mode> (TYPE_MODE (rhs1_type), &mode)
+ && (vectype = get_vectype_for_scalar_type (vinfo, rhs1_type))
+ && (mask_type = get_mask_type_for_scalar_type (vinfo, rhs1_type))
+ && expand_vec_cmp_expr_p (vectype, mask_type, rhs_code))
+ precision = GET_MODE_BITSIZE (mode);
+ }
+
+ if (dump_enabled_p ())
+ {
+ if (precision == ~0U)
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "using normal nonmask vectors for %G",
+ stmt_info->stmt);
+ else
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "using boolean precision %d for %G",
+ precision, stmt_info->stmt);
+ }
+
+ stmt_info->mask_precision = precision;
+ worklist.pop ();
+ }
+}
+
/* Handle vect_determine_precisions for STMT_INFO, given that we
have already done so for the users of its result. */
@@ -4960,6 +5031,7 @@ vect_determine_stmt_precisions (stmt_vec_info stmt_info)
vect_determine_precisions_from_range (stmt_info, stmt);
vect_determine_precisions_from_users (stmt_info, stmt);
}
+ vect_determine_mask_precision (stmt_info);
}
/* Walk backwards through the vectorizable region to determine the
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index a94d2d42491..e35cb7328bd 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -925,17 +925,6 @@ vect_build_slp_tree_1 (unsigned char *swap,
|| rhs_code == LROTATE_EXPR
|| rhs_code == RROTATE_EXPR)
{
- if (vectype == boolean_type_node)
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "Build SLP failed: shift of a"
- " boolean.\n");
- /* Fatal mismatch. */
- matches[0] = false;
- return false;
- }
-
vec_mode = TYPE_MODE (vectype);
/* First see if we have a vector/vector shift. */
@@ -1157,9 +1146,8 @@ vect_build_slp_tree_1 (unsigned char *swap,
if (alt_stmt_code != ERROR_MARK
&& TREE_CODE_CLASS (alt_stmt_code) != tcc_reference)
{
- if (vectype == boolean_type_node
- || !vect_two_operations_perm_ok_p (stmts, group_size,
- vectype, alt_stmt_code))
+ if (!vect_two_operations_perm_ok_p (stmts, group_size,
+ vectype, alt_stmt_code))
{
for (i = 0; i < group_size; ++i)
if (gimple_assign_rhs_code (stmts[i]->stmt) == alt_stmt_code)
@@ -1410,10 +1398,11 @@ vect_build_slp_tree_2 (vec_info *vinfo,
matches, npermutes,
&this_tree_size, bst_map)) != NULL)
{
- /* If we have all children of child built up from scalars then just
- throw that away and build it up this node from scalars. */
+ /* If we have all children of a non-unary child built up from
+ scalars then just throw that away and build it up this node
+ from scalars. */
if (is_a <bb_vec_info> (vinfo)
- && !SLP_TREE_CHILDREN (child).is_empty ()
+ && SLP_TREE_CHILDREN (child).length () > 1
/* ??? Rejecting patterns this way doesn't work. We'd have to
do extra work to cancel the pattern so the uses see the
scalar version. */
@@ -1549,10 +1538,11 @@ vect_build_slp_tree_2 (vec_info *vinfo,
tem, npermutes,
&this_tree_size, bst_map)) != NULL)
{
- /* If we have all children of child built up from scalars then
- just throw that away and build it up this node from scalars. */
+ /* If we have all children of a non-unary child built up from
+ scalars then just throw that away and build it up this node
+ from scalars. */
if (is_a <bb_vec_info> (vinfo)
- && !SLP_TREE_CHILDREN (child).is_empty ()
+ && SLP_TREE_CHILDREN (child).length () > 1
/* ??? Rejecting patterns this way doesn't work. We'd have
to do extra work to cancel the pattern so the uses see the
scalar version. */
@@ -2542,7 +2532,9 @@ vect_detect_hybrid_slp_stmts (slp_tree node, unsigned i, slp_vect_type stype,
/* We need to union stype over the incoming graph edges but we still
want to limit recursion to stay O(N+E). */
- bool only_edge = (++visited.get_or_insert (node) < node->refcnt);
+ unsigned visited_cnt = ++visited.get_or_insert (node);
+ gcc_assert (visited_cnt <= node->refcnt);
+ bool only_edge = (visited_cnt != node->refcnt);
/* Propagate hybrid down the SLP tree. */
if (stype == hybrid)
@@ -2680,12 +2672,19 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
/* Then walk the SLP instance trees marking stmts with uses in
non-SLP stmts as hybrid, also propagating hybrid down the
SLP tree, collecting the above info on-the-fly. */
- hash_map<slp_tree, unsigned> visited;
- FOR_EACH_VEC_ELT (slp_instances, i, instance)
+ for (unsigned j = 0;; ++j)
{
- for (unsigned i = 0; i < SLP_INSTANCE_GROUP_SIZE (instance); ++i)
- vect_detect_hybrid_slp_stmts (SLP_INSTANCE_TREE (instance),
- i, pure_slp, visited);
+ hash_map<slp_tree, unsigned> visited;
+ bool any = false;
+ FOR_EACH_VEC_ELT (slp_instances, i, instance)
+ if (j < SLP_INSTANCE_GROUP_SIZE (instance))
+ {
+ any = true;
+ vect_detect_hybrid_slp_stmts (SLP_INSTANCE_TREE (instance),
+ j, pure_slp, visited);
+ }
+ if (!any)
+ break;
}
}
@@ -2740,24 +2739,6 @@ vect_slp_analyze_node_operations_1 (vec_info *vinfo, slp_tree node,
stmt_vec_info stmt_info = SLP_TREE_SCALAR_STMTS (node)[0];
gcc_assert (STMT_SLP_TYPE (stmt_info) != loop_vect);
- /* For BB vectorization vector types are assigned here.
- Memory accesses already got their vector type assigned
- in vect_analyze_data_refs. */
- bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
- if (bb_vinfo && STMT_VINFO_VECTYPE (stmt_info) == boolean_type_node)
- {
- tree vectype = vect_get_mask_type_for_stmt (stmt_info, node);
- if (!vectype)
- /* vect_get_mask_type_for_stmt has already explained the
- failure. */
- return false;
-
- stmt_vec_info sstmt_info;
- unsigned int i;
- FOR_EACH_VEC_ELT (SLP_TREE_SCALAR_STMTS (node), i, sstmt_info)
- STMT_VINFO_VECTYPE (sstmt_info) = vectype;
- }
-
/* Calculate the number of vector statements to be created for the
scalar stmts in this node. For SLP reductions it is equal to the
number of vector statements in the children (which has already been
@@ -3466,7 +3447,7 @@ vect_slp_bb (basic_block bb)
/* Return 1 if vector type STMT_VINFO is a boolean vector. */
static bool
-vect_mask_constant_operand_p (stmt_vec_info stmt_vinfo)
+vect_mask_constant_operand_p (stmt_vec_info stmt_vinfo, unsigned op_num)
{
enum tree_code code = gimple_expr_code (stmt_vinfo->stmt);
tree op, vectype;
@@ -3491,9 +3472,17 @@ vect_mask_constant_operand_p (stmt_vec_info stmt_vinfo)
tree cond = gimple_assign_rhs1 (stmt);
if (TREE_CODE (cond) == SSA_NAME)
- op = cond;
+ {
+ if (op_num > 0)
+ return VECTOR_BOOLEAN_TYPE_P (STMT_VINFO_VECTYPE (stmt_vinfo));
+ op = cond;
+ }
else
- op = TREE_OPERAND (cond, 0);
+ {
+ if (op_num > 1)
+ return VECTOR_BOOLEAN_TYPE_P (STMT_VINFO_VECTYPE (stmt_vinfo));
+ op = TREE_OPERAND (cond, 0);
+ }
if (!vect_is_simple_use (op, stmt_vinfo->vinfo, &dt, &vectype))
gcc_unreachable ();
@@ -3624,9 +3613,10 @@ duplicate_and_interleave (vec_info *vinfo, gimple_seq *seq, tree vector_type,
operands. */
static void
-vect_get_constant_vectors (slp_tree op_node, slp_tree slp_node,
+vect_get_constant_vectors (slp_tree slp_node, unsigned op_num,
vec<tree> *vec_oprnds)
{
+ slp_tree op_node = SLP_TREE_CHILDREN (slp_node)[op_num];
stmt_vec_info stmt_vinfo = SLP_TREE_SCALAR_STMTS (slp_node)[0];
vec_info *vinfo = stmt_vinfo->vinfo;
unsigned HOST_WIDE_INT nunits;
@@ -3648,7 +3638,7 @@ vect_get_constant_vectors (slp_tree op_node, slp_tree slp_node,
/* Check if vector type is a boolean vector. */
tree stmt_vectype = STMT_VINFO_VECTYPE (stmt_vinfo);
if (VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (op))
- && vect_mask_constant_operand_p (stmt_vinfo))
+ && vect_mask_constant_operand_p (stmt_vinfo, op_num))
vector_type = truth_type_for (stmt_vectype);
else
vector_type = get_vectype_for_scalar_type (vinfo, TREE_TYPE (op), op_node);
@@ -3881,7 +3871,7 @@ vect_get_slp_defs (slp_tree slp_node, vec<vec<tree> > *vec_oprnds, unsigned n)
vect_get_slp_vect_defs (child, &vec_defs);
}
else
- vect_get_constant_vectors (child, slp_node, &vec_defs);
+ vect_get_constant_vectors (slp_node, i, &vec_defs);
vec_oprnds->quick_push (vec_defs);
}
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 6890837bf9f..2cb6b1544ea 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -3325,6 +3325,15 @@ vectorizable_call (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
return false;
}
+ if (VECTOR_BOOLEAN_TYPE_P (vectype_out)
+ != VECTOR_BOOLEAN_TYPE_P (vectype_in))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "mixed mask and nonmask vector types\n");
+ return false;
+ }
+
/* FORNOW */
nunits_in = TYPE_VECTOR_SUBPARTS (vectype_in);
nunits_out = TYPE_VECTOR_SUBPARTS (vectype_out);
@@ -3925,7 +3934,16 @@ vectorizable_simd_clone_call (stmt_vec_info stmt_info,
|| thisarginfo.dt == vect_external_def)
gcc_assert (thisarginfo.vectype == NULL_TREE);
else
- gcc_assert (thisarginfo.vectype != NULL_TREE);
+ {
+ gcc_assert (thisarginfo.vectype != NULL_TREE);
+ if (VECTOR_BOOLEAN_TYPE_P (thisarginfo.vectype))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "vector mask arguments are not supported\n");
+ return false;
+ }
+ }
/* For linear arguments, the analyze phase should have saved
the base and step in STMT_VINFO_SIMD_CLONE_INFO. */
@@ -4482,7 +4500,6 @@ vectorizable_simd_clone_call (stmt_vec_info stmt_info,
static gimple *
vect_gen_widened_results_half (enum tree_code code,
- tree decl,
tree vec_oprnd0, tree vec_oprnd1, int op_type,
tree vec_dest, gimple_stmt_iterator *gsi,
stmt_vec_info stmt_info)
@@ -4491,26 +4508,12 @@ vect_gen_widened_results_half (enum tree_code code,
tree new_temp;
/* Generate half of the widened result: */
- if (code == CALL_EXPR)
- {
- /* Target specific support */
- if (op_type == binary_op)
- new_stmt = gimple_build_call (decl, 2, vec_oprnd0, vec_oprnd1);
- else
- new_stmt = gimple_build_call (decl, 1, vec_oprnd0);
- new_temp = make_ssa_name (vec_dest, new_stmt);
- gimple_call_set_lhs (new_stmt, new_temp);
- }
- else
- {
- /* Generic support */
- gcc_assert (op_type == TREE_CODE_LENGTH (code));
- if (op_type != binary_op)
- vec_oprnd1 = NULL;
- new_stmt = gimple_build_assign (vec_dest, code, vec_oprnd0, vec_oprnd1);
- new_temp = make_ssa_name (vec_dest, new_stmt);
- gimple_assign_set_lhs (new_stmt, new_temp);
- }
+ gcc_assert (op_type == TREE_CODE_LENGTH (code));
+ if (op_type != binary_op)
+ vec_oprnd1 = NULL;
+ new_stmt = gimple_build_assign (vec_dest, code, vec_oprnd0, vec_oprnd1);
+ new_temp = make_ssa_name (vec_dest, new_stmt);
+ gimple_assign_set_lhs (new_stmt, new_temp);
vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
return new_stmt;
@@ -4636,8 +4639,7 @@ vect_create_vectorized_promotion_stmts (vec<tree> *vec_oprnds0,
stmt_vec_info stmt_info, tree vec_dest,
gimple_stmt_iterator *gsi,
enum tree_code code1,
- enum tree_code code2, tree decl1,
- tree decl2, int op_type)
+ enum tree_code code2, int op_type)
{
int i;
tree vop0, vop1, new_tmp1, new_tmp2;
@@ -4653,10 +4655,10 @@ vect_create_vectorized_promotion_stmts (vec<tree> *vec_oprnds0,
vop1 = NULL_TREE;
/* Generate the two halves of promotion operation. */
- new_stmt1 = vect_gen_widened_results_half (code1, decl1, vop0, vop1,
+ new_stmt1 = vect_gen_widened_results_half (code1, vop0, vop1,
op_type, vec_dest, gsi,
stmt_info);
- new_stmt2 = vect_gen_widened_results_half (code2, decl2, vop0, vop1,
+ new_stmt2 = vect_gen_widened_results_half (code2, vop0, vop1,
op_type, vec_dest, gsi,
stmt_info);
if (is_gimple_call (new_stmt1))
@@ -4697,7 +4699,6 @@ vectorizable_conversion (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
enum tree_code code, code1 = ERROR_MARK, code2 = ERROR_MARK;
enum tree_code codecvt1 = ERROR_MARK, codecvt2 = ERROR_MARK;
- tree decl1 = NULL_TREE, decl2 = NULL_TREE;
tree new_temp;
enum vect_def_type dt[2] = {vect_unknown_def_type, vect_unknown_def_type};
int ndts = 2;
@@ -4868,8 +4869,7 @@ vectorizable_conversion (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
&& code != FLOAT_EXPR
&& !CONVERT_EXPR_CODE_P (code))
return false;
- if (supportable_convert_operation (code, vectype_out, vectype_in,
- &decl1, &code1))
+ if (supportable_convert_operation (code, vectype_out, vectype_in, &code1))
break;
/* FALLTHRU */
unsupported:
@@ -4909,7 +4909,7 @@ vectorizable_conversion (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
if (GET_MODE_SIZE (rhs_mode) == fltsz)
{
if (!supportable_convert_operation (code, vectype_out,
- cvt_type, &decl1, &codecvt1))
+ cvt_type, &codecvt1))
goto unsupported;
}
else if (!supportable_widening_operation (code, stmt_info,
@@ -4960,7 +4960,7 @@ vectorizable_conversion (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
if (cvt_type == NULL_TREE)
goto unsupported;
if (!supportable_convert_operation (code, cvt_type, vectype_in,
- &decl1, &codecvt1))
+ &codecvt1))
goto unsupported;
if (supportable_narrowing_operation (NOP_EXPR, vectype_out, cvt_type,
&code1, &multi_step_cvt,
@@ -5079,24 +5079,12 @@ vectorizable_conversion (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
{
stmt_vec_info new_stmt_info;
/* Arguments are ready, create the new vector stmt. */
- if (code1 == CALL_EXPR)
- {
- gcall *new_stmt = gimple_build_call (decl1, 1, vop0);
- new_temp = make_ssa_name (vec_dest, new_stmt);
- gimple_call_set_lhs (new_stmt, new_temp);
- new_stmt_info
- = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
- }
- else
- {
- gcc_assert (TREE_CODE_LENGTH (code1) == unary_op);
- gassign *new_stmt
- = gimple_build_assign (vec_dest, code1, vop0);
- new_temp = make_ssa_name (vec_dest, new_stmt);
- gimple_assign_set_lhs (new_stmt, new_temp);
- new_stmt_info
- = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
- }
+ gcc_assert (TREE_CODE_LENGTH (code1) == unary_op);
+ gassign *new_stmt = gimple_build_assign (vec_dest, code1, vop0);
+ new_temp = make_ssa_name (vec_dest, new_stmt);
+ gimple_assign_set_lhs (new_stmt, new_temp);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
if (slp_node)
SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt_info);
@@ -5188,8 +5176,7 @@ vectorizable_conversion (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
vect_create_vectorized_promotion_stmts (&vec_oprnds0,
&vec_oprnds1, stmt_info,
this_dest, gsi,
- c1, c2, decl1, decl2,
- op_type);
+ c1, c2, op_type);
}
FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
@@ -5197,25 +5184,12 @@ vectorizable_conversion (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
stmt_vec_info new_stmt_info;
if (cvt_type)
{
- if (codecvt1 == CALL_EXPR)
- {
- gcall *new_stmt = gimple_build_call (decl1, 1, vop0);
- new_temp = make_ssa_name (vec_dest, new_stmt);
- gimple_call_set_lhs (new_stmt, new_temp);
- new_stmt_info
- = vect_finish_stmt_generation (stmt_info, new_stmt,
- gsi);
- }
- else
- {
- gcc_assert (TREE_CODE_LENGTH (codecvt1) == unary_op);
- new_temp = make_ssa_name (vec_dest);
- gassign *new_stmt
- = gimple_build_assign (new_temp, codecvt1, vop0);
- new_stmt_info
- = vect_finish_stmt_generation (stmt_info, new_stmt,
- gsi);
- }
+ gcc_assert (TREE_CODE_LENGTH (codecvt1) == unary_op);
+ new_temp = make_ssa_name (vec_dest);
+ gassign *new_stmt
+ = gimple_build_assign (new_temp, codecvt1, vop0);
+ new_stmt_info
+ = vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
}
else
new_stmt_info = vinfo->lookup_def (vop0);
@@ -5258,22 +5232,11 @@ vectorizable_conversion (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
if (cvt_type)
FOR_EACH_VEC_ELT (vec_oprnds0, i, vop0)
{
- if (codecvt1 == CALL_EXPR)
- {
- gcall *new_stmt = gimple_build_call (decl1, 1, vop0);
- new_temp = make_ssa_name (vec_dest, new_stmt);
- gimple_call_set_lhs (new_stmt, new_temp);
- vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
- }
- else
- {
- gcc_assert (TREE_CODE_LENGTH (codecvt1) == unary_op);
- new_temp = make_ssa_name (vec_dest);
- gassign *new_stmt
- = gimple_build_assign (new_temp, codecvt1, vop0);
- vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
- }
-
+ gcc_assert (TREE_CODE_LENGTH (codecvt1) == unary_op);
+ new_temp = make_ssa_name (vec_dest);
+ gassign *new_stmt
+ = gimple_build_assign (new_temp, codecvt1, vop0);
+ vect_finish_stmt_generation (stmt_info, new_stmt, gsi);
vec_oprnds0[i] = new_temp;
}
@@ -5990,6 +5953,21 @@ vectorizable_operation (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
orig_code = code = gimple_assign_rhs_code (stmt);
+ /* Shifts are handled in vectorizable_shift. */
+ if (code == LSHIFT_EXPR
+ || code == RSHIFT_EXPR
+ || code == LROTATE_EXPR
+ || code == RROTATE_EXPR)
+ return false;
+
+ /* Comparisons are handled in vectorizable_comparison. */
+ if (TREE_CODE_CLASS (code) == tcc_comparison)
+ return false;
+
+ /* Conditions are handled in vectorizable_condition. */
+ if (code == COND_EXPR)
+ return false;
+
/* For pointer addition and subtraction, we should use the normal
plus and minus for the vector operation. */
if (code == POINTER_PLUS_EXPR)
@@ -6013,7 +5991,8 @@ vectorizable_operation (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
/* Most operations cannot handle bit-precision types without extra
truncations. */
- if (!VECTOR_BOOLEAN_TYPE_P (vectype_out)
+ bool mask_op_p = VECTOR_BOOLEAN_TYPE_P (vectype_out);
+ if (!mask_op_p
&& !type_has_mode_precision_p (TREE_TYPE (scalar_dest))
/* Exception are bitwise binary operations. */
&& code != BIT_IOR_EXPR
@@ -6075,10 +6054,11 @@ vectorizable_operation (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
if (maybe_ne (nunits_out, nunits_in))
return false;
+ tree vectype2 = NULL_TREE, vectype3 = NULL_TREE;
if (op_type == binary_op || op_type == ternary_op)
{
op1 = gimple_assign_rhs2 (stmt);
- if (!vect_is_simple_use (op1, vinfo, &dt[1]))
+ if (!vect_is_simple_use (op1, vinfo, &dt[1], &vectype2))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -6089,7 +6069,7 @@ vectorizable_operation (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
if (op_type == ternary_op)
{
op2 = gimple_assign_rhs3 (stmt);
- if (!vect_is_simple_use (op2, vinfo, &dt[2]))
+ if (!vect_is_simple_use (op2, vinfo, &dt[2], &vectype3))
{
if (dump_enabled_p ())
dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
@@ -6114,10 +6094,20 @@ vectorizable_operation (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
gcc_assert (ncopies >= 1);
- /* Shifts are handled in vectorizable_shift (). */
- if (code == LSHIFT_EXPR || code == RSHIFT_EXPR || code == LROTATE_EXPR
- || code == RROTATE_EXPR)
- return false;
+ /* Reject attempts to combine mask types with nonmask types, e.g. if
+ we have an AND between a (nonmask) boolean loaded from memory and
+ a (mask) boolean result of a comparison.
+
+ TODO: We could easily fix these cases up using pattern statements. */
+ if (VECTOR_BOOLEAN_TYPE_P (vectype) != mask_op_p
+ || (vectype2 && VECTOR_BOOLEAN_TYPE_P (vectype2) != mask_op_p)
+ || (vectype3 && VECTOR_BOOLEAN_TYPE_P (vectype3) != mask_op_p))
+ {
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "mixed mask and nonmask vector types\n");
+ return false;
+ }
/* Supportable by target? */
@@ -9274,18 +9264,27 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
compute_in_loop = true;
}
+ bool diff_first_stmt_info
+ = first_stmt_info_for_drptr && first_stmt_info != first_stmt_info_for_drptr;
+
if ((alignment_support_scheme == dr_explicit_realign_optimized
|| alignment_support_scheme == dr_explicit_realign)
&& !compute_in_loop)
{
- msq = vect_setup_realignment (first_stmt_info, gsi, &realignment_token,
- alignment_support_scheme, NULL_TREE,
- &at_loop);
+ /* If we have different first_stmt_info, we can't set up realignment
+ here, since we can't guarantee first_stmt_info DR has been
+ initialized yet, use first_stmt_info_for_drptr DR by bumping the
+ distance from first_stmt_info DR instead as below. */
+ if (!diff_first_stmt_info)
+ msq = vect_setup_realignment (first_stmt_info, gsi, &realignment_token,
+ alignment_support_scheme, NULL_TREE,
+ &at_loop);
if (alignment_support_scheme == dr_explicit_realign_optimized)
{
phi = as_a <gphi *> (SSA_NAME_DEF_STMT (msq));
byte_offset = size_binop (MINUS_EXPR, TYPE_SIZE_UNIT (vectype),
size_one_node);
+ gcc_assert (!first_stmt_info_for_drptr);
}
}
else
@@ -9341,8 +9340,7 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
dataref_ptr = unshare_expr (DR_BASE_ADDRESS (first_dr_info->dr));
dataref_offset = build_int_cst (ref_type, 0);
}
- else if (first_stmt_info_for_drptr
- && first_stmt_info != first_stmt_info_for_drptr)
+ else if (diff_first_stmt_info)
{
dataref_ptr
= vect_create_data_ref_ptr (first_stmt_info_for_drptr,
@@ -9359,6 +9357,14 @@ vectorizable_load (stmt_vec_info stmt_info, gimple_stmt_iterator *gsi,
DR_INIT (ptrdr)));
dataref_ptr = bump_vector_ptr (dataref_ptr, ptr_incr, gsi,
stmt_info, diff);
+ if (alignment_support_scheme == dr_explicit_realign)
+ {
+ msq = vect_setup_realignment (first_stmt_info_for_drptr, gsi,
+ &realignment_token,
+ alignment_support_scheme,
+ dataref_ptr, &at_loop);
+ gcc_assert (!compute_in_loop);
+ }
}
else if (STMT_VINFO_GATHER_SCATTER_P (stmt_info))
vect_get_gather_scatter_ops (loop, stmt_info, &gs_info,
@@ -11343,14 +11349,15 @@ get_vectype_for_scalar_type (vec_info *vinfo, tree scalar_type, slp_tree node)
Returns the mask type corresponding to a result of comparison
of vectors of specified SCALAR_TYPE as supported by target.
- NODE, if nonnull, is the SLP tree node that will use the returned
- vector type. */
+ If GROUP_SIZE is nonzero and we're performing BB vectorization,
+ make sure that the number of elements in the vector is no bigger
+ than GROUP_SIZE. */
tree
get_mask_type_for_scalar_type (vec_info *vinfo, tree scalar_type,
- slp_tree node)
+ unsigned int group_size)
{
- tree vectype = get_vectype_for_scalar_type (vinfo, scalar_type, node);
+ tree vectype = get_vectype_for_scalar_type (vinfo, scalar_type, group_size);
if (!vectype)
return NULL;
@@ -12045,9 +12052,6 @@ vect_gen_while_not (gimple_seq *seq, tree mask_type, tree start_index,
- Set *STMT_VECTYPE_OUT to:
- NULL_TREE if the statement doesn't need to be vectorized;
- - boolean_type_node if the statement is a boolean operation whose
- vector type can only be determined once all the other vector types
- are known; and
- the equivalent of STMT_VINFO_VECTYPE otherwise.
- Set *NUNITS_VECTYPE_OUT to the vector type that contains the maximum
@@ -12104,11 +12108,22 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
tree scalar_type = NULL_TREE;
if (group_size == 0 && STMT_VINFO_VECTYPE (stmt_info))
{
- *stmt_vectype_out = vectype = STMT_VINFO_VECTYPE (stmt_info);
+ vectype = STMT_VINFO_VECTYPE (stmt_info);
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location,
"precomputed vectype: %T\n", vectype);
}
+ else if (vect_use_mask_type_p (stmt_info))
+ {
+ unsigned int precision = stmt_info->mask_precision;
+ scalar_type = build_nonstandard_integer_type (precision, 1);
+ vectype = get_mask_type_for_scalar_type (vinfo, scalar_type, group_size);
+ if (!vectype)
+ return opt_result::failure_at (stmt, "not vectorized: unsupported"
+ " data-type %T\n", scalar_type);
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n", vectype);
+ }
else
{
if (data_reference *dr = STMT_VINFO_DATA_REF (stmt_info))
@@ -12118,28 +12133,6 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
else
scalar_type = TREE_TYPE (gimple_get_lhs (stmt));
- /* Pure bool ops don't participate in number-of-units computation.
- For comparisons use the types being compared. */
- if (!STMT_VINFO_DATA_REF (stmt_info)
- && VECT_SCALAR_BOOLEAN_TYPE_P (scalar_type)
- && is_gimple_assign (stmt)
- && gimple_assign_rhs_code (stmt) != COND_EXPR)
- {
- *stmt_vectype_out = boolean_type_node;
-
- tree rhs1 = gimple_assign_rhs1 (stmt);
- if (TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison
- && !VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (rhs1)))
- scalar_type = TREE_TYPE (rhs1);
- else
- {
- if (dump_enabled_p ())
- dump_printf_loc (MSG_NOTE, vect_location,
- "pure bool operation.\n");
- return opt_result::success ();
- }
- }
-
if (dump_enabled_p ())
{
if (group_size)
@@ -12157,18 +12150,15 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
" unsupported data-type %T\n",
scalar_type);
- if (!*stmt_vectype_out)
- *stmt_vectype_out = vectype;
-
if (dump_enabled_p ())
dump_printf_loc (MSG_NOTE, vect_location, "vectype: %T\n", vectype);
}
+ *stmt_vectype_out = vectype;
/* Don't try to compute scalar types if the stmt produces a boolean
vector; use the existing vector type instead. */
tree nunits_vectype = vectype;
- if (!VECTOR_BOOLEAN_TYPE_P (vectype)
- && *stmt_vectype_out != boolean_type_node)
+ if (!VECTOR_BOOLEAN_TYPE_P (vectype))
{
/* The number of units is set according to the smallest scalar
type (or the largest vector size, but we only support one
@@ -12193,9 +12183,8 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
}
}
- gcc_assert (*stmt_vectype_out == boolean_type_node
- || multiple_p (TYPE_VECTOR_SUBPARTS (nunits_vectype),
- TYPE_VECTOR_SUBPARTS (*stmt_vectype_out)));
+ gcc_assert (multiple_p (TYPE_VECTOR_SUBPARTS (nunits_vectype),
+ TYPE_VECTOR_SUBPARTS (*stmt_vectype_out)));
if (dump_enabled_p ())
{
@@ -12207,82 +12196,3 @@ vect_get_vector_types_for_stmt (stmt_vec_info stmt_info,
*nunits_vectype_out = nunits_vectype;
return opt_result::success ();
}
-
-/* Try to determine the correct vector type for STMT_INFO, which is a
- statement that produces a scalar boolean result. Return the vector
- type on success, otherwise return NULL_TREE. NODE, if nonnull,
- is the SLP tree node that will use the returned vector type. */
-
-opt_tree
-vect_get_mask_type_for_stmt (stmt_vec_info stmt_info, slp_tree node)
-{
- vec_info *vinfo = stmt_info->vinfo;
- gimple *stmt = stmt_info->stmt;
- tree mask_type = NULL;
- tree vectype, scalar_type;
-
- if (is_gimple_assign (stmt)
- && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison
- && !VECT_SCALAR_BOOLEAN_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
- {
- scalar_type = TREE_TYPE (gimple_assign_rhs1 (stmt));
- mask_type = get_mask_type_for_scalar_type (vinfo, scalar_type, node);
-
- if (!mask_type)
- return opt_tree::failure_at (stmt,
- "not vectorized: unsupported mask\n");
- }
- else
- {
- tree rhs;
- ssa_op_iter iter;
- enum vect_def_type dt;
-
- FOR_EACH_SSA_TREE_OPERAND (rhs, stmt, iter, SSA_OP_USE)
- {
- if (!vect_is_simple_use (rhs, stmt_info->vinfo, &dt, &vectype))
- return opt_tree::failure_at (stmt,
- "not vectorized:can't compute mask"
- " type for statement, %G", stmt);
-
- /* No vectype probably means external definition.
- Allow it in case there is another operand which
- allows to determine mask type. */
- if (!vectype)
- continue;
-
- if (!mask_type)
- mask_type = vectype;
- else if (maybe_ne (TYPE_VECTOR_SUBPARTS (mask_type),
- TYPE_VECTOR_SUBPARTS (vectype)))
- return opt_tree::failure_at (stmt,
- "not vectorized: different sized mask"
- " types in statement, %T and %T\n",
- mask_type, vectype);
- else if (VECTOR_BOOLEAN_TYPE_P (mask_type)
- != VECTOR_BOOLEAN_TYPE_P (vectype))
- return opt_tree::failure_at (stmt,
- "not vectorized: mixed mask and "
- "nonmask vector types in statement, "
- "%T and %T\n",
- mask_type, vectype);
- }
-
- /* We may compare boolean value loaded as vector of integers.
- Fix mask_type in such case. */
- if (mask_type
- && !VECTOR_BOOLEAN_TYPE_P (mask_type)
- && gimple_code (stmt) == GIMPLE_ASSIGN
- && TREE_CODE_CLASS (gimple_assign_rhs_code (stmt)) == tcc_comparison)
- mask_type = truth_type_for (mask_type);
- }
-
- /* No mask_type should mean loop invariant predicate.
- This is probably a subject for optimization in if-conversion. */
- if (!mask_type)
- return opt_tree::failure_at (stmt,
- "not vectorized: can't compute mask type "
- "for statement: %G", stmt);
-
- return opt_tree::success (mask_type);
-}
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 0eac5bdef88..51a13f1d207 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1089,6 +1089,23 @@ public:
unsigned int operation_precision;
signop operation_sign;
+ /* If the statement produces a boolean result, this value describes
+ how we should choose the associated vector type. The possible
+ values are:
+
+ - an integer precision N if we should use the vector mask type
+ associated with N-bit integers. This is only used if all relevant
+ input booleans also want the vector mask type for N-bit integers,
+ or if we can convert them into that form by pattern-matching.
+
+ - ~0U if we considered choosing a vector mask type but decided
+ to treat the boolean as a normal integer type instead.
+
+ - 0 otherwise. This means either that the operation isn't one that
+ could have a vector mask type (and so should have a normal vector
+ type instead) or that we simply haven't made a choice either way. */
+ unsigned int mask_precision;
+
/* True if this is only suitable for SLP vectorization. */
bool slp_vect_only_p;
};
@@ -1245,6 +1262,15 @@ nested_in_vect_loop_p (class loop *loop, stmt_vec_info stmt_info)
&& (loop->inner == (gimple_bb (stmt_info->stmt))->loop_father));
}
+/* Return true if STMT_INFO should produce a vector mask type rather than
+ a normal nonmask type. */
+
+static inline bool
+vect_use_mask_type_p (stmt_vec_info stmt_info)
+{
+ return stmt_info->mask_precision && stmt_info->mask_precision != ~0U;
+}
+
/* Return TRUE if a statement represented by STMT_INFO is a part of a
pattern. */
@@ -1640,7 +1666,7 @@ extern tree get_related_vectype_for_scalar_type (machine_mode, tree,
poly_uint64 = 0);
extern tree get_vectype_for_scalar_type (vec_info *, tree, unsigned int = 0);
extern tree get_vectype_for_scalar_type (vec_info *, tree, slp_tree);
-extern tree get_mask_type_for_scalar_type (vec_info *, tree, slp_tree = 0);
+extern tree get_mask_type_for_scalar_type (vec_info *, tree, unsigned int = 0);
extern tree get_same_sized_vectype (tree, tree);
extern bool vect_chooses_same_modes_p (vec_info *, machine_mode);
extern bool vect_get_loop_mask_type (loop_vec_info);
@@ -1693,7 +1719,7 @@ extern gcall *vect_gen_while (tree, tree, tree);
extern tree vect_gen_while_not (gimple_seq *, tree, tree, tree);
extern opt_result vect_get_vector_types_for_stmt (stmt_vec_info, tree *,
tree *, unsigned int = 0);
-extern opt_tree vect_get_mask_type_for_stmt (stmt_vec_info, slp_tree = 0);
+extern opt_tree vect_get_mask_type_for_stmt (stmt_vec_info, unsigned int = 0);
/* In tree-vect-data-refs.c. */
extern bool vect_can_force_dr_alignment_p (const_tree, poly_uint64);
diff --git a/gcc/tree.c b/gcc/tree.c
index f9ea79d1799..7a66d1003ee 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -10334,23 +10334,23 @@ build_common_tree_nodes (bool signed_char)
uint64_type_node = make_or_reuse_type (64, 1);
/* Decimal float types. */
- dfloat32_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE;
- SET_TYPE_MODE (dfloat32_type_node, SDmode);
- layout_type (dfloat32_type_node);
- dfloat32_ptr_type_node = build_pointer_type (dfloat32_type_node);
-
- dfloat64_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE;
- SET_TYPE_MODE (dfloat64_type_node, DDmode);
- layout_type (dfloat64_type_node);
- dfloat64_ptr_type_node = build_pointer_type (dfloat64_type_node);
-
- dfloat128_type_node = make_node (REAL_TYPE);
- TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE;
- SET_TYPE_MODE (dfloat128_type_node, TDmode);
- layout_type (dfloat128_type_node);
- dfloat128_ptr_type_node = build_pointer_type (dfloat128_type_node);
+ if (targetm.decimal_float_supported_p ())
+ {
+ dfloat32_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (dfloat32_type_node) = DECIMAL32_TYPE_SIZE;
+ SET_TYPE_MODE (dfloat32_type_node, SDmode);
+ layout_type (dfloat32_type_node);
+
+ dfloat64_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (dfloat64_type_node) = DECIMAL64_TYPE_SIZE;
+ SET_TYPE_MODE (dfloat64_type_node, DDmode);
+ layout_type (dfloat64_type_node);
+
+ dfloat128_type_node = make_node (REAL_TYPE);
+ TYPE_PRECISION (dfloat128_type_node) = DECIMAL128_TYPE_SIZE;
+ SET_TYPE_MODE (dfloat128_type_node, TDmode);
+ layout_type (dfloat128_type_node);
+ }
complex_integer_type_node = build_complex_type (integer_type_node, true);
complex_float_type_node = build_complex_type (float_type_node, true);
@@ -15003,6 +15003,41 @@ default_is_empty_record (const_tree type)
return default_is_empty_type (TYPE_MAIN_VARIANT (type));
}
+/* Determine whether TYPE is a structure with a flexible array member,
+ or a union containing such a structure (possibly recursively). */
+
+bool
+flexible_array_type_p (const_tree type)
+{
+ tree x, last;
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ last = NULL_TREE;
+ for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
+ if (TREE_CODE (x) == FIELD_DECL)
+ last = x;
+ if (last == NULL_TREE)
+ return false;
+ if (TREE_CODE (TREE_TYPE (last)) == ARRAY_TYPE
+ && TYPE_SIZE (TREE_TYPE (last)) == NULL_TREE
+ && TYPE_DOMAIN (TREE_TYPE (last)) != NULL_TREE
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (last))) == NULL_TREE)
+ return true;
+ return false;
+ case UNION_TYPE:
+ for (x = TYPE_FIELDS (type); x != NULL_TREE; x = DECL_CHAIN (x))
+ {
+ if (TREE_CODE (x) == FIELD_DECL
+ && flexible_array_type_p (TREE_TYPE (x)))
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
/* Like int_size_in_bytes, but handle empty records specially. */
HOST_WIDE_INT
@@ -15123,6 +15158,21 @@ max_object_size (void)
return TYPE_MAX_VALUE (ptrdiff_type_node);
}
+/* A wrapper around TARGET_VERIFY_TYPE_CONTEXT that makes the silent_p
+ parameter default to false and that weeds out error_mark_node. */
+
+bool
+verify_type_context (location_t loc, type_context_kind context,
+ const_tree type, bool silent_p)
+{
+ if (type == error_mark_node)
+ return true;
+
+ gcc_assert (TYPE_P (type));
+ return (!targetm.verify_type_context
+ || targetm.verify_type_context (loc, context, type, silent_p));
+}
+
#if CHECKING_P
namespace selftest {
diff --git a/gcc/tree.h b/gcc/tree.h
index 60b6eae7b04..fb09758a05a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4098,9 +4098,6 @@ tree_strip_any_location_wrapper (tree exp)
#define dfloat32_type_node global_trees[TI_DFLOAT32_TYPE]
#define dfloat64_type_node global_trees[TI_DFLOAT64_TYPE]
#define dfloat128_type_node global_trees[TI_DFLOAT128_TYPE]
-#define dfloat32_ptr_type_node global_trees[TI_DFLOAT32_PTR_TYPE]
-#define dfloat64_ptr_type_node global_trees[TI_DFLOAT64_PTR_TYPE]
-#define dfloat128_ptr_type_node global_trees[TI_DFLOAT128_PTR_TYPE]
/* The fixed-point types. */
#define sat_short_fract_type_node global_trees[TI_SAT_SFRACT_TYPE]
@@ -6141,6 +6138,7 @@ extern void gt_pch_nx (tree &, gt_pointer_operator, void *);
extern bool nonnull_arg_p (const_tree);
extern bool default_is_empty_record (const_tree);
+extern bool flexible_array_type_p (const_tree);
extern HOST_WIDE_INT arg_int_size_in_bytes (const_tree);
extern tree arg_size_in_bytes (const_tree);
extern bool expr_type_first_operand_type_p (tree_code);
diff --git a/gcc/ubsan.c b/gcc/ubsan.c
index d2696302bd0..f12674b5649 100644
--- a/gcc/ubsan.c
+++ b/gcc/ubsan.c
@@ -1860,7 +1860,7 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
representable decimal number greater or equal than
1 << (prec - !uns_p). */
mpfr_init2 (m, prec + 2);
- mpfr_set_ui_2exp (m, 1, prec - !uns_p, GMP_RNDN);
+ mpfr_set_ui_2exp (m, 1, prec - !uns_p, MPFR_RNDN);
mpfr_snprintf (buf, sizeof buf, "%.*RUe", p - 1, m);
decimal_real_from_string (&maxval, buf);
max = build_real (expr_type, maxval);
@@ -1873,8 +1873,8 @@ ubsan_instrument_float_cast (location_t loc, tree type, tree expr)
/* Use mpfr_snprintf rounding to compute the largest
representable decimal number less or equal than
(-1 << (prec - 1)) - 1. */
- mpfr_set_si_2exp (m, -1, prec - 1, GMP_RNDN);
- mpfr_sub_ui (m, m, 1, GMP_RNDN);
+ mpfr_set_si_2exp (m, -1, prec - 1, MPFR_RNDN);
+ mpfr_sub_ui (m, m, 1, MPFR_RNDN);
mpfr_snprintf (buf, sizeof buf, "%.*RDe", p - 1, m);
decimal_real_from_string (&minval, buf);
min = build_real (expr_type, minval);
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 57365ad2e76..d9d02b3b263 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -5960,6 +5960,23 @@ do_assemble_alias (tree decl, tree target)
#endif
}
+/* Output .symver directive. */
+
+void
+do_assemble_symver (tree decl, tree target)
+{
+ tree id = DECL_ASSEMBLER_NAME (decl);
+ ultimate_transparent_alias_target (&id);
+ ultimate_transparent_alias_target (&target);
+#ifdef ASM_OUTPUT_SYMVER_DIRECTIVE
+ ASM_OUTPUT_SYMVER_DIRECTIVE (asm_out_file,
+ IDENTIFIER_POINTER (target),
+ IDENTIFIER_POINTER (id));
+#else
+ error ("symver is only supported on ELF platforms");
+#endif
+}
+
/* Emit an assembler directive to make the symbol for DECL an alias to
the symbol for TARGET. */
diff --git a/gcc/varpool.c b/gcc/varpool.c
index ff49ad9f517..1a30ae49d54 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -540,7 +540,10 @@ varpool_node::assemble_aliases (void)
FOR_EACH_ALIAS (this, ref)
{
varpool_node *alias = dyn_cast <varpool_node *> (ref->referring);
- if (!alias->transparent_alias)
+ if (alias->symver)
+ do_assemble_symver (alias->decl,
+ DECL_ASSEMBLER_NAME (decl));
+ else if (!alias->transparent_alias)
do_assemble_alias (alias->decl,
DECL_ASSEMBLER_NAME (decl));
alias->assemble_aliases ();
diff --git a/libcc1/ChangeLog b/libcc1/ChangeLog
index d65a0b22b06..92b5cb735e8 100644
--- a/libcc1/ChangeLog
+++ b/libcc1/ChangeLog
@@ -1,3 +1,8 @@
+2019-11-25 Paolo Carlini <paolo.carlini@oracle.com>
+
+ * libcp1plugin.cc (plugin_pragma_push_user_expression): Update
+ cp_build_indirect_ref call.
+
2019-09-27 Maciej W. Rozycki <macro@wdc.com>
* configure: Regenerate.
diff --git a/libcc1/libcp1plugin.cc b/libcc1/libcp1plugin.cc
index d241ea1033d..232ab976ab5 100644
--- a/libcc1/libcp1plugin.cc
+++ b/libcc1/libcp1plugin.cc
@@ -630,7 +630,8 @@ plugin_pragma_push_user_expression (cpp_reader *)
usable. */
tree this_val = lookup_name (get_identifier ("this"));
current_class_ref = !this_val ? NULL_TREE
- : cp_build_indirect_ref (this_val, RO_NULL, tf_warning_or_error);
+ : cp_build_indirect_ref (input_location, this_val, RO_NULL,
+ tf_warning_or_error);
current_class_ptr = this_val;
}
}
diff --git a/libgfortran/ChangeLog b/libgfortran/ChangeLog
index 91768c0a00f..ac925cc8dc4 100644
--- a/libgfortran/ChangeLog
+++ b/libgfortran/ChangeLog
@@ -1,7 +1,19 @@
+2019-12-01 Jerry DeLisle <jvdelisle@gcc.ngu.org>
+
+ PR fortran/90374
+ * io/format.c (parse_format_list): Add braces to disambiguate
+ conditional.
+
+2019-11-28 Jerry DeLisle <jvdelisle@gcc.ngu.org>
+
+ PR fortran/90374
+ * io/format.c (parse_format_list): Relax format checking to allow
+ e0 exponent specifier.
+
2019-11-24 Jerry DeLisle <jvdelisle@gcc.ngu.org>
PR fortran/92100
- io/transfer.c (data_transfer_init_worker): Use fbuf_reset
+ * io/transfer.c (data_transfer_init_worker): Use fbuf_reset
instead of fbuf_flush before the seek. Note that fbuf_reset
calls fbuf_flush and adjusts fbuf pointers.
diff --git a/libgfortran/io/format.c b/libgfortran/io/format.c
index b33620815d5..0b23721c055 100644
--- a/libgfortran/io/format.c
+++ b/libgfortran/io/format.c
@@ -1028,10 +1028,18 @@ parse_format_list (st_parameter_dt *dtp, bool *seen_dd)
t = format_lex (fmt);
if (t != FMT_POSINT)
{
- fmt->error = "Positive exponent width required in format";
- goto finished;
+ if (t == FMT_ZERO)
+ {
+ notify_std (&dtp->common, GFC_STD_F2018,
+ "Positive exponent width required");
+ }
+ else
+ {
+ fmt->error = "Positive exponent width required in "
+ "format string at %L";
+ goto finished;
+ }
}
-
tail->u.real.e = fmt->value;
}
diff --git a/libgfortran/io/write_float.def b/libgfortran/io/write_float.def
index daa16679f53..ce6aec83114 100644
--- a/libgfortran/io/write_float.def
+++ b/libgfortran/io/write_float.def
@@ -482,7 +482,7 @@ build_float_string (st_parameter_dt *dtp, const fnode *f, char *buffer,
for (i = abs (e); i >= 10; i /= 10)
edigits++;
- if (f->u.real.e < 0)
+ if (f->u.real.e <= 0)
{
/* Width not specified. Must be no more than 3 digits. */
if (e > 999 || e < -999)
diff --git a/libgomp/ChangeLog b/libgomp/ChangeLog
index 65478302ba8..01da5efb8ae 100644
--- a/libgomp/ChangeLog
+++ b/libgomp/ChangeLog
@@ -1,3 +1,24 @@
+2019-11-29 Tobias Burnus <tobias@codesourcery.com>
+
+ * testsuite/libgomp.oacc-fortran/declare-5.f90: Extend by
+ adding a common-block test case.
+
+2019-11-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/60228
+ * testsuite/libgomp.c++/udr-20.C: New test.
+ * testsuite/libgomp.c++/udr-21.C: New test.
+
+2019-11-27 Thomas Schwinge <thomas@codesourcery.com>
+
+ * testsuite/lib/libgomp.exp
+ (check_effective_target_offload_target_nvptx): New proc.
+ * testsuite/libgomp.fortran/target-print-1.f90: Use it with
+ 'dg-skip-if'.
+ * testsuite/libgomp.oacc-fortran/print-1.f90: Likewise.
+ * testsuite/libgomp.fortran/target-print-1-nvptx.f90: New file.
+ * testsuite/libgomp.oacc-fortran/print-1-nvptx.f90: Likewise.
+
2019-11-21 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* testsuite/libgomp.c/pr39591-1.c: Rename err to e.
diff --git a/libgomp/testsuite/lib/libgomp.exp b/libgomp/testsuite/lib/libgomp.exp
index 74d032623c9..06e3186d966 100644
--- a/libgomp/testsuite/lib/libgomp.exp
+++ b/libgomp/testsuite/lib/libgomp.exp
@@ -336,6 +336,27 @@ proc offload_target_to_openacc_device_type { offload_target } {
}
}
+# Return 1 if compiling for offload target nvptx.
+proc check_effective_target_offload_target_nvptx { } {
+ # Consider all actual options, including the flags passed to
+ # 'gcc-dg-runtest', or 'gfortran-dg-runtest' (see the 'libgomp.*/*.exp'
+ # files; in particular, '-foffload', 'libgomp.oacc-*/*.exp'), which don't
+ # get passed on to 'check_effective_target_*' functions. (Not caching the
+ # result due to that.)
+ set options [current_compiler_flags]
+ # Instead of inspecting command-line options, look what the compiler driver
+ # decides. This is somewhat modelled after
+ # 'gcc/testsuite/lib/target-supports.exp:check_configured_with'.
+ set gcc_output [libgomp_target_compile "-v $options" "" "none" ""]
+ if [regexp "(?n)^OFFLOAD_TARGET_NAMES=(.*)" $gcc_output dummy offload_targets] {
+ verbose "compiling for offload targets: $offload_targets"
+ return [string match "*:nvptx*:*" ":$offload_targets:"]
+ }
+
+ verbose "not compiling for any offload targets"
+ return 0
+}
+
# Return 1 if offload device is available.
proc check_effective_target_offload_device { } {
return [check_runtime_nocache offload_device_available_ {
diff --git a/libgomp/testsuite/libgomp.c++/udr-20.C b/libgomp/testsuite/libgomp.c++/udr-20.C
new file mode 100644
index 00000000000..83388758edd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-20.C
@@ -0,0 +1,54 @@
+// PR c++/60228
+// { dg-additional-options "-std=c++11" }
+
+extern "C" void abort ();
+
+struct A
+{
+ typedef int T;
+ #pragma omp declare reduction (x : T : omp_out += omp_in + [](){ return 0; }()) initializer (omp_priv = [](){ return 0; }())
+ static void foo ();
+};
+
+template <typename T>
+struct B
+{
+ #pragma omp declare reduction (x : T : omp_out += omp_in + [](){ return T (0); }()) initializer (omp_priv = [](){ return T (0); }())
+ static void foo ();
+};
+
+void
+A::foo ()
+{
+ int r = 0, s = 0;
+ #pragma omp parallel for reduction (x : r, s)
+ for (int i = 0; i < 64; i++)
+ {
+ r++;
+ s += i;
+ }
+ if (r != 64 || s != (64 * 63) / 2)
+ abort ();
+}
+
+template <typename T>
+void
+B<T>::foo ()
+{
+ T r = 0, s = 0;
+ #pragma omp parallel for reduction (x : r, s)
+ for (int i = 0; i < 64; i++)
+ {
+ r++;
+ s += i;
+ }
+ if (r != 64 || s != (64 * 63) / 2)
+ abort ();
+}
+
+int
+main ()
+{
+ A::foo ();
+ B<long>::foo ();
+}
diff --git a/libgomp/testsuite/libgomp.c++/udr-21.C b/libgomp/testsuite/libgomp.c++/udr-21.C
new file mode 100644
index 00000000000..9ec655718fd
--- /dev/null
+++ b/libgomp/testsuite/libgomp.c++/udr-21.C
@@ -0,0 +1,54 @@
+// PR c++/60228
+// { dg-additional-options "-std=c++11" }
+
+extern "C" void abort ();
+
+struct A
+{
+ typedef int T;
+ #pragma omp declare reduction (y : T : [&omp_out, &omp_in]() { omp_out += omp_in; return 0; }()) initializer (omp_priv = [omp_orig]() { return omp_orig; }())
+ static void foo ();
+};
+
+template <typename T>
+struct B
+{
+ #pragma omp declare reduction (y : T : [&omp_out, &omp_in]() { omp_out += omp_in; return 0; }()) initializer (omp_priv = [omp_orig]() { return omp_orig; }())
+ static void foo ();
+};
+
+void
+A::foo ()
+{
+ int r = 0, s = 0;
+ #pragma omp parallel for reduction (y : r, s)
+ for (int i = 0; i < 64; i++)
+ {
+ r++;
+ s += i;
+ }
+ if (r != 64 || s != (64 * 63) / 2)
+ abort ();
+}
+
+template <typename T>
+void
+B<T>::foo ()
+{
+ T r = 0, s = 0;
+ #pragma omp parallel for reduction (y : r, s)
+ for (int i = 0; i < 64; i++)
+ {
+ r++;
+ s += i;
+ }
+ if (r != 64 || s != (64 * 63) / 2)
+ abort ();
+}
+
+int
+main ()
+{
+ A::foo ();
+ B<short>::foo ();
+}
diff --git a/libgomp/testsuite/libgomp.fortran/target-print-1-nvptx.f90 b/libgomp/testsuite/libgomp.fortran/target-print-1-nvptx.f90
new file mode 100644
index 00000000000..a89c9c33484
--- /dev/null
+++ b/libgomp/testsuite/libgomp.fortran/target-print-1-nvptx.f90
@@ -0,0 +1,11 @@
+! Ensure that write on the offload device works, nvptx offloading variant.
+
+! This doesn't compile: for nvptx offloading we're using a minimal libgfortran
+! configuration.
+! { dg-do link } ! ..., but still apply 'dg-do run' options.
+! { dg-xfail-if "minimal libgfortran" { offload_target_nvptx } }
+
+! Skip duplicated testing.
+! { dg-skip-if "separate file" { ! offload_target_nvptx } }
+
+include 'target-print-1.f90'
diff --git a/libgomp/testsuite/libgomp.fortran/target-print-1.f90 b/libgomp/testsuite/libgomp.fortran/target-print-1.f90
index c71a0952483..327bb22cb6d 100644
--- a/libgomp/testsuite/libgomp.fortran/target-print-1.f90
+++ b/libgomp/testsuite/libgomp.fortran/target-print-1.f90
@@ -1,8 +1,10 @@
-! Ensure that printf on the offload device works.
+! Ensure that write on the offload device works.
! { dg-do run }
! { dg-output "The answer is 42(\n|\r\n|\r)+" }
-! { dg-xfail-if "no write for nvidia" { openacc_nvidia_accel_selected } }
+
+! Separate file 'target-print-1-nvptx.f90' for nvptx offloading.
+! { dg-skip-if "separate file" { offload_target_nvptx } }
program main
implicit none
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/declare-5.f90 b/libgomp/testsuite/libgomp.oacc-fortran/declare-5.f90
index 3ab91147e07..4eb0ecadc76 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/declare-5.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/declare-5.f90
@@ -3,27 +3,105 @@
module vars
implicit none
real b
- !$acc declare device_resident (b)
+ !$acc declare device_resident (b)
+
+ integer :: x, y, z
+ common /block/ x, y, z
+ !$acc declare device_resident (/block/)
end module vars
+subroutine set()
+ use openacc
+ implicit none
+ integer :: a(5), b(1), c, vals(7)
+ common /another/ a, b, c
+ !$acc declare device_resident (/another/)
+ if (.not. acc_is_present (a)) stop 10
+ if (.not. acc_is_present (b)) stop 11
+ if (.not. acc_is_present (c)) stop 12
+
+ vals = 99
+ ! NOTE: The current (Nov 2019) implementation requires the 'present'
+ ! as it tries to otherwises map the device_resident variables;
+ ! following OpenMP 4.0 semantic: 'a' + 'b' are 'copy' (map fromto) and
+ ! 'c' is firstprivate.
+ !$acc parallel copyout(vals) present(a, b, c)
+ a = [11,12,13,14,15]
+ b = 16
+ c = 47
+ vals(1:5) = a
+ vals(6:6) = b
+ vals(7) = c
+ !$acc end parallel
+
+ if (.not. acc_is_present (a)) stop 13
+ if (.not. acc_is_present (b)) stop 14
+ if (.not. acc_is_present (c)) stop 15
+
+ if (any (vals /= [11,12,13,14,15,16,47])) stop 16
+end subroutine set
+
+subroutine check()
+ use openacc
+ implicit none
+ integer :: g, h(3), i(3)
+ common /another/ g, h, i
+ integer :: val(7)
+ !$acc declare device_resident (/another/)
+ if (.not. acc_is_present (g)) stop 20
+ if (.not. acc_is_present (h)) stop 21
+ if (.not. acc_is_present (i)) stop 22
+
+ val = 99
+ !$acc parallel copyout(val) present(g, h, i)
+ val(5:7) = i
+ val(1) = g
+ val(2:4) = h
+ !$acc end parallel
+
+ if (.not. acc_is_present (g)) stop 23
+ if (.not. acc_is_present (h)) stop 24
+ if (.not. acc_is_present (i)) stop 25
+
+
+ !print *, val
+ if (any (val /= [11,12,13,14,15,16,47])) stop 26
+end subroutine check
+
+
program test
use vars
use openacc
implicit none
real a
+ integer :: k
- if (acc_is_present (b) .neqv. .true.) STOP 1
+ call set()
+ call check()
+
+ if (.not. acc_is_present (b)) stop 1
+ if (.not. acc_is_present (x)) stop 2
+ if (.not. acc_is_present (y)) stop 3
+ if (.not. acc_is_present (z)) stop 4
a = 2.0
+ k = 42
- !$acc parallel copy (a)
+ !$acc parallel copy (a, k)
b = a
a = 1.0
a = a + b
+ x = k
+ y = 7*k - 2*x
+ z = 3*y
+ k = k - z + y
!$acc end parallel
- if (acc_is_present (b) .neqv. .true.) STOP 2
-
- if (a .ne. 3.0) STOP 3
+ if (.not. acc_is_present (b)) stop 5
+ if (.not. acc_is_present (x)) stop 6
+ if (.not. acc_is_present (y)) stop 7
+ if (.not. acc_is_present (z)) stop 8
+ if (a /= 3.0) stop 3
+ if (k /= -378) stop 3
end program test
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/print-1-nvptx.f90 b/libgomp/testsuite/libgomp.oacc-fortran/print-1-nvptx.f90
new file mode 100644
index 00000000000..866c8654355
--- /dev/null
+++ b/libgomp/testsuite/libgomp.oacc-fortran/print-1-nvptx.f90
@@ -0,0 +1,11 @@
+! Ensure that write on the offload device works, nvptx offloading variant.
+
+! This doesn't compile: for nvptx offloading we're using a minimal libgfortran
+! configuration.
+! { dg-do link } ! ..., but still apply 'dg-do run' options.
+! { dg-xfail-if "minimal libgfortran" { offload_target_nvptx } }
+
+! Skip duplicated testing.
+! { dg-skip-if "separate file" { ! offload_target_nvptx } }
+
+include 'print-1.f90'
diff --git a/libgomp/testsuite/libgomp.oacc-fortran/print-1.f90 b/libgomp/testsuite/libgomp.oacc-fortran/print-1.f90
index a83280d1edb..7b7f73741fe 100644
--- a/libgomp/testsuite/libgomp.oacc-fortran/print-1.f90
+++ b/libgomp/testsuite/libgomp.oacc-fortran/print-1.f90
@@ -1,8 +1,10 @@
-! Ensure that printf on the offload device works.
+! Ensure that write on the offload device works.
! { dg-do run }
! { dg-output "The answer is 42(\n|\r\n|\r)+" }
-! { dg-xfail-if "no write for nvidia" { openacc_nvidia_accel_selected } }
+
+! Separate file 'print-1-nvptx.f90' for nvptx offloading.
+! { dg-skip-if "separate file" { offload_target_nvptx } }
program main
implicit none
diff --git a/libobjc/ChangeLog b/libobjc/ChangeLog
index e9e110cf538..c998875fa26 100644
--- a/libobjc/ChangeLog
+++ b/libobjc/ChangeLog
@@ -1,3 +1,7 @@
+2019-11-26 Tobias Burnus <tobias@codesourcery.com>
+
+ * Makefile.in (aclocal_deps): Fix path to cet.m4.
+
2019-09-27 Maciej W. Rozycki <macro@wdc.com>
* configure: Regenerate.
diff --git a/libobjc/Makefile.in b/libobjc/Makefile.in
index d733fb2606b..f029880265e 100644
--- a/libobjc/Makefile.in
+++ b/libobjc/Makefile.in
@@ -297,7 +297,7 @@ aclocal_deps = \
$(srcdir)/../ltsugar.m4 \
$(srcdir)/../ltversion.m4 \
$(srcdir)/../lt~obsolete.m4 \
- $(srcdir)/../cet.m4 \
+ $(srcdir)/../config/cet.m4 \
$(srcdir)/acinclude.m4
$(srcdir)/configure: @MAINT@ configure.ac $(srcdir)/aclocal.m4
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog
index 3ae22f7e765..f2a07adca77 100644
--- a/libsanitizer/ChangeLog
+++ b/libsanitizer/ChangeLog
@@ -1,3 +1,10 @@
+2019-11-26 Jakub Jelinek <jakub@redhat.com>
+
+ PR sanitizer/92154
+ * sanitizer_common/sanitizer_platform_limits_posix.h: Cherry-pick
+ llvm-project revision 947f9692440836dcb8d88b74b69dd379d85974ce.
+ * sanitizer_common/sanitizer_platform_limits_posix.cpp: Likewise.
+
2019-11-20 Martin Liska <mliska@suse.cz>
* libtool-version: Remove.
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp
index b4f8f67b664..aa845df4dde 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.cpp
@@ -1128,11 +1128,9 @@ CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
-#if (!defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)) && \
- !defined(__arm__)
-/* On aarch64 glibc 2.20 and earlier provided incorrect mode field. */
-/* On Arm newer glibc provide a different mode field, it's hard to detect
- so just disable the check. */
+#if !SANITIZER_LINUX || __GLIBC_PREREQ (2, 31)
+/* glibc 2.30 and earlier provided 16-bit mode field instead of 32-bit
+ on many architectures. */
CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
#endif
diff --git a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
index 901f390a0b4..d82fd5e4005 100644
--- a/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
+++ b/libsanitizer/sanitizer_common/sanitizer_platform_limits_posix.h
@@ -207,26 +207,13 @@ struct __sanitizer_ipc_perm {
u64 __unused1;
u64 __unused2;
#elif defined(__sparc__)
-#if defined(__arch64__)
unsigned mode;
- unsigned short __pad1;
-#else
- unsigned short __pad1;
- unsigned short mode;
unsigned short __pad2;
-#endif
unsigned short __seq;
unsigned long long __unused1;
unsigned long long __unused2;
-#elif defined(__mips__) || defined(__aarch64__) || defined(__s390x__)
- unsigned int mode;
- unsigned short __seq;
- unsigned short __pad1;
- unsigned long __unused1;
- unsigned long __unused2;
#else
- unsigned short mode;
- unsigned short __pad1;
+ unsigned int mode;
unsigned short __seq;
unsigned short __pad2;
#if defined(__x86_64__) && !defined(_LP64)
diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog
index a479a1219ff..238e356c843 100644
--- a/libstdc++-v3/ChangeLog
+++ b/libstdc++-v3/ChangeLog
@@ -1,3 +1,120 @@
+2019-11-30 Jonathan Wakely <jwakely@redhat.com>
+
+ * acinclude.m4 (GLIBCXX_ENABLE_FILESYSTEM_TS): Enable by default for
+ mingw targets.
+ * configure: Regenerate.
+
+ * include/bits/fs_path.h (u8path(InputIterator, InputIterator))
+ (u8path(const Source&)) [_GLIBCXX_FILESYSTEM_IS_WINDOWS]: Simplify
+ conditions.
+ * include/experimental/bits/fs_path.h [_GLIBCXX_FILESYSTEM_IS_WINDOWS]
+ (__u8path(const Source&, char)): Add overloads for std::string and
+ types convertible to std::string.
+ (_Cvt::_S_wconvert): Add a new overload for char8_t strings and use
+ codecvt_utf8_utf16 to do the correct conversion.
+
+2019-11-29 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/fs_path.h (path::operator/=): Change template-head to
+ use typename instead of class.
+ * include/experimental/bits/fs_path.h (path::operator/=): Likewise.
+ * include/std/ostream (operator<<): Likewise.
+
+2019-11-29 Tom Honermann <tom@honermann.net>
+
+ New tests
+ * testsuite/27_io/basic_ostream/inserters_character/char/deleted.cc:
+ New test to validate deleted overloads of character and string
+ inserters for narrow ostreams.
+ * testsuite/27_io/basic_ostream/inserters_character/wchar_t/deleted.cc:
+ New test to validate deleted overloads of character and string
+ inserters for wide ostreams.
+ * testsuite/27_io/filesystem/path/factory/u8path-char8_t.cc: New test
+ to validate u8path invocations with sequences of char8_t.
+ * testsuite/experimental/filesystem/path/factory/u8path-char8_t.cc:
+ New test to validate u8path invocations with sequences of char8_t.
+
+ Updates to existing tests
+ * testsuite/experimental/feat-char8_t.cc: Updated the expected
+ __cpp_lib_char8_t feature test macro value.
+ * testsuite/27_io/filesystem/path/factory/u8path.cc: Added testing of
+ u8path invocation with std::string, std::string_view, and iterators
+ thereof.
+ * testsuite/experimental/filesystem/path/factory/u8path.cc: Added
+ testing of u8path invocation with std::string, std::string_view, and
+ iterators thereof.
+
+ Update feature test macro, add deleted operators, update u8path
+ * include/bits/c++config: Bumped the value of the __cpp_lib_char8_t
+ feature test macro.
+ * include/bits/fs_path.h (u8path): Modified u8path to accept sequences
+ of char8_t.
+ * include/experimental/bits/fs_path.h (u8path): Modified u8path to
+ accept sequences of char8_t.
+ * include/std/ostream: Added deleted overloads of wchar_t, char8_t,
+ char16_t, and char32_t for ordinary and wide formatted character and
+ string inserters.
+
+ Decouple constraints for u8path from path constructors
+ * include/bits/fs_path.h: Moved helper utilities out of
+ std::filesystem::path into a detail namespace to make them
+ available for use by u8path.
+ * include/experimental/bits/fs_path.h: Moved helper utilities out
+ of std::experimental::filesystem::v1::path into a detail
+ namespace to make them available for use by u8path.
+
+2019-11-29 Jonathan Wakely <jwakely@redhat.com>
+
+ PR libstdc++/91997
+ * python/libstdcxx/v6/printers.py (find_type): Fail more gracefully
+ if we run out of base classes to look at.
+ (llokup_templ_spec, lookup_node_type): New utilities to find node
+ types for node-based containers.
+ (StdListPrinter.children, NodeIteratorPrinter.__init__)
+ (NodeIteratorPrinter.to_string, StdSlistPrinter.children)
+ (StdSlistIteratorPrinter.to_string, StdRbtreeIteratorPrinter.__init__)
+ (StdMapPrinter.children, StdSetPrinter.children)
+ (StdForwardListPrinter.children): Use lookup_node_type instead of
+ find_type.
+ (StdListIteratorPrinter.__init__, StdFwdListIteratorPrinter.__init__):
+ Pass name of node type to NodeIteratorPrinter constructor.
+ (Tr1HashtableIterator.__init__): Rename argument.
+ (StdHashtableIterator.__init__): Likewise. Use lookup_templ_spec
+ instead of find_type.
+ * testsuite/libstdc++-prettyprinters/59161.cc: Remove workaround for
+ _Node typedef not being present in debuginfo.
+ * testsuite/libstdc++-prettyprinters/91997.cc: New test.
+
+2019-11-26 François Dumont <fdumont@gcc.gnu.org>
+
+ * include/debug/helper_functions.h (__valid_range_aux): Use C++98
+ std::input_iterator_tag default constructor invocation.
+
+ * include/debug/array (array<>::fill): Add C++20 constexpr.
+ (array<>::swap): Likewise.
+
+ * include/debug/safe_iterator.h
+ [__cpp_lib_concepts](_Safe_iterator<>::iterator_concept): Define for
+ C++20.
+
+2019-11-25 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/bits/iterator_concepts.h (ranges::iter_swap): Fix parameter
+ types of poison pill overload. Use remove_reference_t when checking
+ constraints.
+ * include/bits/stl_iterator.h (move_sentinel): Define for C++20.
+ (move_iterator): Adjust definitions of nested types for C++20. Add
+ hidden friends for move_sentinel operations, iter_move and iter_swap.
+ (common_iterator, counted_iterator): Define for C++20.
+ * testsuite/24_iterators/move_iterator/cust.cc: New test.
+ * testsuite/24_iterators/move_iterator/sentinel.cc: New test.
+ * testsuite/24_iterators/common_iterator/1.cc: New test.
+ * testsuite/24_iterators/counted_iterator/1.cc: New test.
+
+ PR libstdc++/91786
+ * include/bits/fs_path.h (filesystem_error): Move definition before
+ the use in u8path.
+
2019-11-24 François Dumont <fdumont@gcc.gnu.org>
* include/debug/functions.h: Remove <bits/move.h> include.
diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index ad2cb01d94f..73e07e513bc 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -4436,6 +4436,9 @@ AC_DEFUN([GLIBCXX_ENABLE_FILESYSTEM_TS], [
solaris*)
enable_libstdcxx_filesystem_ts=yes
;;
+ mingw*)
+ enable_libstdcxx_filesystem_ts=yes
+ ;;
*)
enable_libstdcxx_filesystem_ts=no
;;
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index cb67581206d..e1d24132294 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -74551,6 +74551,9 @@ $as_echo_n "checking whether to build Filesystem TS support... " >&6; }
solaris*)
enable_libstdcxx_filesystem_ts=yes
;;
+ mingw*)
+ enable_libstdcxx_filesystem_ts=yes
+ ;;
*)
enable_libstdcxx_filesystem_ts=no
;;
diff --git a/libstdc++-v3/include/bits/c++config b/libstdc++-v3/include/bits/c++config
index 32db60f39e5..7ccfc5f199d 100644
--- a/libstdc++-v3/include/bits/c++config
+++ b/libstdc++-v3/include/bits/c++config
@@ -620,7 +620,7 @@ namespace std
# endif
#endif
#ifdef _GLIBCXX_USE_CHAR8_T
-# define __cpp_lib_char8_t 201811L
+# define __cpp_lib_char8_t 201907L
#endif
/* Define if __float128 is supported on this host. */
diff --git a/libstdc++-v3/include/bits/fs_path.h b/libstdc++-v3/include/bits/fs_path.h
index e1083acf30f..20ec42da57d 100644
--- a/libstdc++-v3/include/bits/fs_path.h
+++ b/libstdc++-v3/include/bits/fs_path.h
@@ -63,99 +63,122 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
* @{
*/
- /// A filesystem path.
- class path
- {
- template<typename _CharT>
- using __is_encoded_char = __is_one_of<remove_const_t<_CharT>,
- char,
+ class path;
+
+ /// @cond undocumented
+namespace __detail
+{
+ template<typename _CharT>
+ using __is_encoded_char = __is_one_of<remove_const_t<_CharT>,
+ char,
#ifdef _GLIBCXX_USE_CHAR8_T
- char8_t,
+ char8_t,
#endif
#if _GLIBCXX_USE_WCHAR_T
- wchar_t,
+ wchar_t,
#endif
- char16_t, char32_t>;
-
- template<typename _Iter,
- typename _Iter_traits = std::iterator_traits<_Iter>>
- using __is_path_iter_src
- = __and_<__is_encoded_char<typename _Iter_traits::value_type>,
- std::is_base_of<std::input_iterator_tag,
- typename _Iter_traits::iterator_category>>;
+ char16_t, char32_t>;
- template<typename _Iter>
- static __is_path_iter_src<_Iter>
- __is_path_src(_Iter, int);
+ template<typename _Iter,
+ typename _Iter_traits = std::iterator_traits<_Iter>>
+ using __is_path_iter_src
+ = __and_<__is_encoded_char<typename _Iter_traits::value_type>,
+ std::is_base_of<std::input_iterator_tag,
+ typename _Iter_traits::iterator_category>>;
- template<typename _CharT, typename _Traits, typename _Alloc>
- static __is_encoded_char<_CharT>
- __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
+ template<typename _Iter>
+ static __is_path_iter_src<_Iter>
+ __is_path_src(_Iter, int);
- template<typename _CharT, typename _Traits>
- static __is_encoded_char<_CharT>
- __is_path_src(const basic_string_view<_CharT, _Traits>&, int);
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ static __is_encoded_char<_CharT>
+ __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
- template<typename _Unknown>
- static std::false_type
- __is_path_src(const _Unknown&, ...);
+ template<typename _CharT, typename _Traits>
+ static __is_encoded_char<_CharT>
+ __is_path_src(const basic_string_view<_CharT, _Traits>&, int);
- template<typename _Tp1, typename _Tp2>
- struct __constructible_from;
+ template<typename _Unknown>
+ static std::false_type
+ __is_path_src(const _Unknown&, ...);
- template<typename _Iter>
- struct __constructible_from<_Iter, _Iter>
- : __is_path_iter_src<_Iter>
- { };
+ template<typename _Tp1, typename _Tp2>
+ struct __constructible_from;
- template<typename _Source>
- struct __constructible_from<_Source, void>
- : decltype(__is_path_src(std::declval<_Source>(), 0))
- { };
+ template<typename _Iter>
+ struct __constructible_from<_Iter, _Iter>
+ : __is_path_iter_src<_Iter>
+ { };
- template<typename _Tp1, typename _Tp2 = void>
- using _Path = typename
- std::enable_if<__and_<__not_<is_same<remove_cv_t<_Tp1>, path>>,
- __not_<is_void<remove_pointer_t<_Tp1>>>,
- __constructible_from<_Tp1, _Tp2>>::value,
- path>::type;
-
- template<typename _Source>
- static _Source
- _S_range_begin(_Source __begin) { return __begin; }
-
- struct __null_terminated { };
-
- template<typename _Source>
- static __null_terminated
- _S_range_end(_Source) { return {}; }
+ template<typename _Source>
+ struct __constructible_from<_Source, void>
+ : decltype(__is_path_src(std::declval<_Source>(), 0))
+ { };
- template<typename _CharT, typename _Traits, typename _Alloc>
- static const _CharT*
- _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
- { return __str.data(); }
+ template<typename _Tp1, typename _Tp2 = void>
+ using _Path = typename
+ std::enable_if<__and_<__not_<is_same<remove_cv_t<_Tp1>, path>>,
+ __not_<is_void<remove_pointer_t<_Tp1>>>,
+ __constructible_from<_Tp1, _Tp2>>::value,
+ path>::type;
- template<typename _CharT, typename _Traits, typename _Alloc>
- static const _CharT*
- _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
- { return __str.data() + __str.size(); }
+ template<typename _Source>
+ static _Source
+ _S_range_begin(_Source __begin) { return __begin; }
- template<typename _CharT, typename _Traits>
- static const _CharT*
- _S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
- { return __str.data(); }
+ struct __null_terminated { };
- template<typename _CharT, typename _Traits>
- static const _CharT*
- _S_range_end(const basic_string_view<_CharT, _Traits>& __str)
- { return __str.data() + __str.size(); }
+ template<typename _Source>
+ static __null_terminated
+ _S_range_end(_Source) { return {}; }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ static const _CharT*
+ _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
+ { return __str.data(); }
+
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ static const _CharT*
+ _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
+ { return __str.data() + __str.size(); }
+
+ template<typename _CharT, typename _Traits>
+ static const _CharT*
+ _S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
+ { return __str.data(); }
+
+ template<typename _CharT, typename _Traits>
+ static const _CharT*
+ _S_range_end(const basic_string_view<_CharT, _Traits>& __str)
+ { return __str.data() + __str.size(); }
+
+ template<typename _Tp,
+ typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
+ typename _Val = typename std::iterator_traits<_Iter>::value_type,
+ typename _UnqualVal = std::remove_const_t<_Val>>
+ using __value_type_is_char
+ = std::enable_if_t<std::is_same_v<_UnqualVal, char>,
+ _UnqualVal>;
+
+ template<typename _Tp,
+ typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
+ typename _Val = typename std::iterator_traits<_Iter>::value_type,
+ typename _UnqualVal = std::remove_const_t<_Val>>
+ using __value_type_is_char_or_char8_t
+ = std::enable_if_t<__or_v<
+ std::is_same<_UnqualVal, char>
+#ifdef _GLIBCXX_USE_CHAR8_T
+ , std::is_same<_UnqualVal, char8_t>
+#endif
+ >,
+ _UnqualVal>;
- template<typename _Tp,
- typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
- typename _Val = typename std::iterator_traits<_Iter>::value_type>
- using __value_type_is_char
- = std::enable_if_t<std::is_same_v<std::remove_const_t<_Val>, char>>;
+} // namespace __detail
+ /// @endcond
+ /// A filesystem path.
+ class path
+ {
public:
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
using value_type = wchar_t;
@@ -193,29 +216,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ _M_split_cmpts(); }
template<typename _Source,
- typename _Require = _Path<_Source>>
+ typename _Require = __detail::_Path<_Source>>
path(_Source const& __source, format = auto_format)
- : _M_pathname(_S_convert(_S_range_begin(__source),
- _S_range_end(__source)))
+ : _M_pathname(_S_convert(__detail::_S_range_begin(__source),
+ __detail::_S_range_end(__source)))
{ _M_split_cmpts(); }
template<typename _InputIterator,
- typename _Require = _Path<_InputIterator, _InputIterator>>
+ typename _Require = __detail::_Path<_InputIterator, _InputIterator>>
path(_InputIterator __first, _InputIterator __last, format = auto_format)
: _M_pathname(_S_convert(__first, __last))
{ _M_split_cmpts(); }
template<typename _Source,
- typename _Require = _Path<_Source>,
- typename _Require2 = __value_type_is_char<_Source>>
+ typename _Require = __detail::_Path<_Source>,
+ typename _Require2 = __detail::__value_type_is_char<_Source>>
path(_Source const& __source, const locale& __loc, format = auto_format)
- : _M_pathname(_S_convert_loc(_S_range_begin(__source),
- _S_range_end(__source), __loc))
+ : _M_pathname(_S_convert_loc(__detail::_S_range_begin(__source),
+ __detail::_S_range_end(__source), __loc))
{ _M_split_cmpts(); }
template<typename _InputIterator,
- typename _Require = _Path<_InputIterator, _InputIterator>,
- typename _Require2 = __value_type_is_char<_InputIterator>>
+ typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
+ typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
path(_InputIterator __first, _InputIterator __last, const locale& __loc,
format = auto_format)
: _M_pathname(_S_convert_loc(__first, __last, __loc))
@@ -231,17 +254,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
path& assign(string_type&& __source);
template<typename _Source>
- _Path<_Source>&
+ __detail::_Path<_Source>&
operator=(_Source const& __source)
{ return *this = path(__source); }
template<typename _Source>
- _Path<_Source>&
+ __detail::_Path<_Source>&
assign(_Source const& __source)
{ return *this = path(__source); }
template<typename _InputIterator>
- _Path<_InputIterator, _InputIterator>&
+ __detail::_Path<_InputIterator, _InputIterator>&
assign(_InputIterator __first, _InputIterator __last)
{ return *this = path(__first, __last); }
@@ -249,24 +272,26 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
path& operator/=(const path& __p);
- template <class _Source>
- _Path<_Source>&
+ template<typename _Source>
+ __detail::_Path<_Source>&
operator/=(_Source const& __source)
{
- _M_append(_S_convert(_S_range_begin(__source), _S_range_end(__source)));
+ _M_append(_S_convert(__detail::_S_range_begin(__source),
+ __detail::_S_range_end(__source)));
return *this;
}
template<typename _Source>
- _Path<_Source>&
+ __detail::_Path<_Source>&
append(_Source const& __source)
{
- _M_append(_S_convert(_S_range_begin(__source), _S_range_end(__source)));
+ _M_append(_S_convert(__detail::_S_range_begin(__source),
+ __detail::_S_range_end(__source)));
return *this;
}
template<typename _InputIterator>
- _Path<_InputIterator, _InputIterator>&
+ __detail::_Path<_InputIterator, _InputIterator>&
append(_InputIterator __first, _InputIterator __last)
{
_M_append(_S_convert(__first, __last));
@@ -282,23 +307,24 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
path& operator+=(basic_string_view<value_type> __x);
template<typename _Source>
- _Path<_Source>&
+ __detail::_Path<_Source>&
operator+=(_Source const& __x) { return concat(__x); }
template<typename _CharT>
- _Path<_CharT*, _CharT*>&
+ __detail::_Path<_CharT*, _CharT*>&
operator+=(_CharT __x);
template<typename _Source>
- _Path<_Source>&
+ __detail::_Path<_Source>&
concat(_Source const& __x)
{
- _M_concat(_S_convert(_S_range_begin(__x), _S_range_end(__x)));
+ _M_concat(_S_convert(__detail::_S_range_begin(__x),
+ __detail::_S_range_end(__x)));
return *this;
}
template<typename _InputIterator>
- _Path<_InputIterator, _InputIterator>&
+ __detail::_Path<_InputIterator, _InputIterator>&
concat(_InputIterator __first, _InputIterator __last)
{
_M_concat(_S_convert(__first, __last));
@@ -496,11 +522,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
struct _Cvt;
static basic_string_view<value_type>
- _S_convert(value_type* __src, __null_terminated)
+ _S_convert(value_type* __src, __detail::__null_terminated)
{ return __src; }
static basic_string_view<value_type>
- _S_convert(const value_type* __src, __null_terminated)
+ _S_convert(const value_type* __src, __detail::__null_terminated)
{ return __src; }
static basic_string_view<value_type>
@@ -522,7 +548,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
template<typename _InputIterator>
static string_type
- _S_convert(_InputIterator __src, __null_terminated)
+ _S_convert(_InputIterator __src, __detail::__null_terminated)
{
// Read from iterator into basic_string until a null value is seen:
auto __s = _S_string_from_iter(__src);
@@ -544,7 +570,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
template<typename _InputIterator>
static string_type
- _S_convert_loc(_InputIterator __src, __null_terminated,
+ _S_convert_loc(_InputIterator __src, __detail::__null_terminated,
const std::locale& __loc)
{
const std::string __s = _S_string_from_iter(__src);
@@ -622,59 +648,6 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
size_t hash_value(const path& __p) noexcept;
- /// Create a path from a UTF-8-encoded sequence of char
- template<typename _InputIterator>
- inline auto
- u8path(_InputIterator __first, _InputIterator __last)
- -> decltype(filesystem::path(__first, __last, std::locale::classic()))
- {
-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
- // XXX This assumes native wide encoding is UTF-16.
- std::codecvt_utf8_utf16<path::value_type> __cvt;
- path::string_type __tmp;
- if constexpr (is_pointer_v<_InputIterator>)
- {
- if (__str_codecvt_in_all(__first, __last, __tmp, __cvt))
- return path{ __tmp };
- }
- else
- {
- const std::string __u8str{__first, __last};
- const char* const __ptr = __u8str.data();
- if (__str_codecvt_in_all(__ptr, __ptr + __u8str.size(), __tmp, __cvt))
- return path{ __tmp };
- }
- _GLIBCXX_THROW_OR_ABORT(filesystem_error(
- "Cannot convert character sequence",
- std::make_error_code(errc::illegal_byte_sequence)));
-#else
- // This assumes native normal encoding is UTF-8.
- return path{ __first, __last };
-#endif
- }
-
- /// Create a path from a UTF-8-encoded sequence of char
- template<typename _Source>
- inline auto
- u8path(const _Source& __source)
- -> decltype(filesystem::path(__source, std::locale::classic()))
- {
-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
- if constexpr (is_convertible_v<const _Source&, std::string_view>)
- {
- const std::string_view __s = __source;
- return filesystem::u8path(__s.data(), __s.data() + __s.size());
- }
- else
- {
- std::string __s = path::_S_string_from_iter(__source);
- return filesystem::u8path(__s.data(), __s.data() + __s.size());
- }
-#else
- return path{ __source };
-#endif
- }
-
/// @}
/// Exception type thrown by the Filesystem library
@@ -706,6 +679,78 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
std::__shared_ptr<const _Impl> _M_impl;
};
+ /** Create a path from a UTF-8-encoded sequence of char
+ *
+ * @relates std::filesystem::path
+ */
+ template<typename _InputIterator,
+ typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
+ typename _CharT
+ = __detail::__value_type_is_char_or_char8_t<_InputIterator>>
+ inline path
+ u8path(_InputIterator __first, _InputIterator __last)
+ {
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+ if constexpr (is_same_v<_CharT, char>)
+ {
+ // XXX This assumes native wide encoding is UTF-16.
+ std::codecvt_utf8_utf16<path::value_type> __cvt;
+ path::string_type __tmp;
+ if constexpr (is_pointer_v<_InputIterator>)
+ {
+ if (__str_codecvt_in_all(__first, __last, __tmp, __cvt))
+ return path{ __tmp };
+ }
+ else
+ {
+ const std::string __u8str{__first, __last};
+ const char* const __p = __u8str.data();
+ if (__str_codecvt_in_all(__p, __p + __u8str.size(), __tmp, __cvt))
+ return path{ __tmp };
+ }
+ _GLIBCXX_THROW_OR_ABORT(filesystem_error(
+ "Cannot convert character sequence",
+ std::make_error_code(errc::illegal_byte_sequence)));
+ }
+ else
+ return path{ __first, __last };
+#else
+ // This assumes native normal encoding is UTF-8.
+ return path{ __first, __last };
+#endif
+ }
+
+ /** Create a path from a UTF-8-encoded sequence of char
+ *
+ * @relates std::filesystem::path
+ */
+ template<typename _Source,
+ typename _Require = __detail::_Path<_Source>,
+ typename _CharT = __detail::__value_type_is_char_or_char8_t<_Source>>
+ inline path
+ u8path(const _Source& __source)
+ {
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+ if constexpr (is_same_v<_CharT, char>)
+ {
+ if constexpr (is_convertible_v<const _Source&, std::string_view>)
+ {
+ const std::string_view __s = __source;
+ return filesystem::u8path(__s.data(), __s.data() + __s.size());
+ }
+ else
+ {
+ std::string __s = path::_S_string_from_iter(__source);
+ return filesystem::u8path(__s.data(), __s.data() + __s.size());
+ }
+ }
+ else
+ return path{ __source };
+#else
+ return path{ __source };
+#endif
+ }
+
/// @cond undocumented
struct path::_Cmpt : path
@@ -944,7 +989,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
}
template<typename _CharT>
- inline path::_Path<_CharT*, _CharT*>&
+ inline __detail::_Path<_CharT*, _CharT*>&
path::operator+=(_CharT __x)
{
auto* __addr = std::__addressof(__x);
diff --git a/libstdc++-v3/include/bits/iterator_concepts.h b/libstdc++-v3/include/bits/iterator_concepts.h
index 3843ba5d57f..97aed72e255 100644
--- a/libstdc++-v3/include/bits/iterator_concepts.h
+++ b/libstdc++-v3/include/bits/iterator_concepts.h
@@ -700,7 +700,7 @@ namespace ranges
namespace __cust_iswap
{
template<typename _It1, typename _It2>
- void iter_swap(_It1&, _It2&) = delete;
+ void iter_swap(_It1, _It2) = delete;
template<typename _Tp, typename _Up>
concept __adl_iswap
@@ -744,7 +744,8 @@ namespace ranges
public:
template<typename _Tp, typename _Up>
requires __adl_iswap<_Tp, _Up>
- || (readable<_Tp> && readable<_Up>
+ || (readable<remove_reference_t<_Tp>>
+ && readable<remove_reference_t<_Up>>
&& swappable_with<iter_reference_t<_Tp>, iter_reference_t<_Up>>)
|| (indirectly_movable_storable<_Tp, _Up>
&& indirectly_movable_storable<_Up, _Tp>)
diff --git a/libstdc++-v3/include/bits/stl_iterator.h b/libstdc++-v3/include/bits/stl_iterator.h
index a707621c9ed..89cca64438c 100644
--- a/libstdc++-v3/include/bits/stl_iterator.h
+++ b/libstdc++-v3/include/bits/stl_iterator.h
@@ -73,6 +73,11 @@
# define __cpp_lib_array_constexpr 201803
#endif
+#if __cplusplus > 201703L
+# include <compare>
+# include <new>
+#endif
+
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
@@ -1055,12 +1060,61 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __it.base(); }
#if __cplusplus >= 201103L
-
/**
* @addtogroup iterators
* @{
*/
+#if __cplusplus > 201703L && __cpp_lib_concepts
+ template<semiregular _Sent>
+ class move_sentinel
+ {
+ public:
+ constexpr
+ move_sentinel()
+ noexcept(is_nothrow_default_constructible_v<_Sent>)
+ : _M_last() { }
+
+ constexpr explicit
+ move_sentinel(_Sent __s)
+ noexcept(is_nothrow_move_constructible_v<_Sent>)
+ : _M_last(std::move(__s)) { }
+
+ template<typename _S2> requires convertible_to<const _S2&, _Sent>
+ constexpr
+ move_sentinel(const move_sentinel<_S2>& __s)
+ noexcept(is_nothrow_constructible_v<_Sent, const _S2&>)
+ : _M_last(__s.base())
+ { }
+
+ template<typename _S2> requires assignable_from<_Sent&, const _S2&>
+ constexpr move_sentinel&
+ operator=(const move_sentinel<_S2>& __s)
+ noexcept(is_nothrow_assignable_v<_Sent, const _S2&>)
+ {
+ _M_last = __s.base();
+ return *this;
+ }
+
+ constexpr _Sent
+ base() const
+ noexcept(is_nothrow_copy_constructible_v<_Sent>)
+ { return _M_last; }
+
+ private:
+ _Sent _M_last;
+ };
+
+ namespace __detail
+ {
+ // Weaken iterator_category _Cat to _Limit if it is derived from that,
+ // otherwise use _Otherwise.
+ template<typename _Cat, typename _Limit, typename _Otherwise = _Cat>
+ using __clamp_iter_cat
+ = conditional_t<derived_from<_Cat, _Limit>, _Limit, _Otherwise>;
+ }
+#endif // C++20
+
// 24.4.3 Move iterators
/**
* Class template move_iterator is an iterator adapter with the same
@@ -1073,14 +1127,27 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
template<typename _Iterator>
class move_iterator
{
- protected:
_Iterator _M_current;
- typedef iterator_traits<_Iterator> __traits_type;
- typedef typename __traits_type::reference __base_ref;
+ using __traits_type = iterator_traits<_Iterator>;
+#if __cplusplus > 201703L && __cpp_lib_concepts
+ using __base_cat = typename __traits_type::iterator_category;
+#else
+ using __base_ref = typename __traits_type::reference;
+#endif
public:
- typedef _Iterator iterator_type;
+ using iterator_type = _Iterator;
+
+#if __cplusplus > 201703L && __cpp_lib_concepts
+ using iterator_concept = input_iterator_tag;
+ using iterator_category
+ = __detail::__clamp_iter_cat<__base_cat, random_access_iterator_tag>;
+ using value_type = iter_value_t<_Iterator>;
+ using difference_type = iter_difference_t<_Iterator>;
+ using pointer = _Iterator;
+ using reference = iter_rvalue_reference_t<_Iterator>;
+#else
typedef typename __traits_type::iterator_category iterator_category;
typedef typename __traits_type::value_type value_type;
typedef typename __traits_type::difference_type difference_type;
@@ -1091,6 +1158,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef typename conditional<is_reference<__base_ref>::value,
typename remove_reference<__base_ref>::type&&,
__base_ref>::type reference;
+#endif
_GLIBCXX17_CONSTEXPR
move_iterator()
@@ -1172,6 +1240,34 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
_GLIBCXX17_CONSTEXPR reference
operator[](difference_type __n) const
{ return std::move(_M_current[__n]); }
+
+#if __cplusplus > 201703L && __cpp_lib_concepts
+ template<sentinel_for<_Iterator> _Sent>
+ friend constexpr bool
+ operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y)
+ { return __x.base() == __y.base(); }
+
+ template<sized_sentinel_for<_Iterator> _Sent>
+ friend constexpr iter_difference_t<_Iterator>
+ operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y)
+ { return __x.base() - __y.base(); }
+
+ template<sized_sentinel_for<_Iterator> _Sent>
+ friend constexpr iter_difference_t<_Iterator>
+ operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y)
+ { return __x.base() - __y.base(); }
+
+ friend constexpr iter_rvalue_reference_t<_Iterator>
+ iter_move(const move_iterator& __i)
+ noexcept(noexcept(ranges::iter_move(__i._M_current)))
+ { return ranges::iter_move(__i._M_current); }
+
+ template<indirectly_swappable<_Iterator> _Iter2>
+ friend constexpr void
+ iter_swap(const move_iterator& __x, const move_iterator<_Iter2>& __y)
+ noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current)))
+ { return ranges::iter_swap(__x._M_current, __y._M_current); }
+#endif // C++20
};
// Note: See __normal_iterator operators note from Gaby to understand
@@ -1285,6 +1381,592 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__make_move_if_noexcept_iterator(_Tp* __i)
{ return _ReturnType(__i); }
+#if __cplusplus > 201703L && __cpp_lib_concepts
+ // [iterators.common] Common iterators
+
+ namespace __detail
+ {
+ template<input_or_output_iterator _It>
+ class _Common_iter_proxy
+ {
+ iter_value_t<_It> _M_keep;
+
+ _Common_iter_proxy(iter_reference_t<_It>&& __x)
+ : _M_keep(std::move(__x)) { }
+
+ template<typename _Iter, typename _Sent>
+ friend class common_iterator;
+
+ public:
+ const iter_value_t<_It>*
+ operator->() const
+ { return std::__addressof(_M_keep); }
+ };
+
+ template<typename _It>
+ concept __common_iter_has_arrow = readable<const _It>
+ && (requires(const _It& __it) { __it.operator->(); }
+ || is_reference_v<iter_reference_t<_It>>
+ || constructible_from<iter_value_t<_It>, iter_reference_t<_It>>);
+
+ } // namespace __detail
+
+ /// An iterator/sentinel adaptor for representing a non-common range.
+ template<input_or_output_iterator _It, sentinel_for<_It> _Sent>
+ requires (!same_as<_It, _Sent>)
+ class common_iterator
+ {
+ template<typename _Tp, typename _Up>
+ static constexpr bool
+ _S_noexcept1()
+ {
+ if constexpr (is_trivially_default_constructible_v<_Tp>)
+ return is_nothrow_assignable_v<_Tp, _Up>;
+ else
+ return is_nothrow_constructible_v<_Tp, _Up>;
+ }
+
+ template<typename _It2, typename _Sent2>
+ static constexpr bool
+ _S_noexcept()
+ { return _S_noexcept1<_It, _It2>() && _S_noexcept1<_Sent, _Sent2>(); }
+
+ public:
+ constexpr
+ common_iterator()
+ noexcept(is_nothrow_default_constructible_v<_It>)
+ : _M_it(), _M_index(0)
+ { }
+
+ constexpr
+ common_iterator(_It __i)
+ noexcept(is_nothrow_move_constructible_v<_It>)
+ : _M_it(std::move(__i)), _M_index(0)
+ { }
+
+ constexpr
+ common_iterator(_Sent __s)
+ noexcept(is_nothrow_move_constructible_v<_Sent>)
+ : _M_sent(std::move(__s)), _M_index(1)
+ { }
+
+ template<typename _It2, typename _Sent2>
+ requires convertible_to<const _It2&, _It>
+ && convertible_to<const _Sent2&, _Sent>
+ constexpr
+ common_iterator(const common_iterator<_It2, _Sent2>& __x)
+ noexcept(_S_noexcept<const _It2&, const _Sent2&>())
+ : _M_valueless(), _M_index(__x._M_index)
+ {
+ if (_M_index == 0)
+ {
+ if constexpr (is_trivially_default_constructible_v<_It>)
+ _M_it = std::move(__x._M_it);
+ else
+ ::new((void*)std::__addressof(_M_it)) _It(__x._M_it);
+ }
+ else if (_M_index == 1)
+ {
+ if constexpr (is_trivially_default_constructible_v<_Sent>)
+ _M_sent = std::move(__x._M_sent);
+ else
+ ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent);
+ }
+ }
+
+ constexpr
+ common_iterator(const common_iterator& __x)
+ noexcept(_S_noexcept<const _It&, const _Sent&>())
+ : _M_valueless(), _M_index(__x._M_index)
+ {
+ if (_M_index == 0)
+ {
+ if constexpr (is_trivially_default_constructible_v<_It>)
+ _M_it = std::move(__x._M_it);
+ else
+ ::new((void*)std::__addressof(_M_it)) _It(__x._M_it);
+ }
+ else if (_M_index == 1)
+ {
+ if constexpr (is_trivially_default_constructible_v<_Sent>)
+ _M_sent = std::move(__x._M_sent);
+ else
+ ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent);
+ }
+ }
+
+ common_iterator&
+ operator=(const common_iterator& __x)
+ noexcept(is_nothrow_copy_assignable_v<_It>
+ && is_nothrow_copy_assignable_v<_Sent>
+ && is_nothrow_copy_constructible_v<_It>
+ && is_nothrow_copy_constructible_v<_Sent>)
+ {
+ return this->operator=<_It, _Sent>(__x);
+ }
+
+ template<typename _It2, typename _Sent2>
+ requires convertible_to<const _It2&, _It>
+ && convertible_to<const _Sent2&, _Sent>
+ && assignable_from<_It&, const _It2&>
+ && assignable_from<_Sent&, const _Sent2&>
+ common_iterator&
+ operator=(const common_iterator<_It2, _Sent2>& __x)
+ noexcept(is_nothrow_constructible_v<_It, const _It2&>
+ && is_nothrow_constructible_v<_Sent, const _Sent2&>
+ && is_nothrow_assignable_v<_It, const _It2&>
+ && is_nothrow_assignable_v<_Sent, const _Sent2&>)
+ {
+ switch(_M_index << 2 | __x._M_index)
+ {
+ case 0b0000:
+ _M_it = __x._M_it;
+ break;
+ case 0b0101:
+ _M_sent = __x._M_sent;
+ break;
+ case 0b0001:
+ _M_it.~_It();
+ _M_index = -1;
+ [[fallthrough]];
+ case 0b1001:
+ ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent);
+ _M_index = 1;
+ break;
+ case 0b0100:
+ _M_sent.~_Sent();
+ _M_index = -1;
+ [[fallthrough]];
+ case 0b1000:
+ ::new((void*)std::__addressof(_M_it)) _It(__x._M_it);
+ _M_index = 0;
+ break;
+ default:
+ __glibcxx_assert(__x._M_has_value());
+ __builtin_unreachable();
+ }
+ return *this;
+ }
+
+ ~common_iterator()
+ {
+ switch (_M_index)
+ {
+ case 0:
+ _M_it.~_It();
+ break;
+ case 1:
+ _M_sent.~_Sent();
+ break;
+ }
+ }
+
+ decltype(auto)
+ operator*()
+ {
+ __glibcxx_assert(_M_index == 0);
+ return *_M_it;
+ }
+
+ decltype(auto)
+ operator*() const requires __detail::__dereferenceable<const _It>
+ {
+ __glibcxx_assert(_M_index == 0);
+ return *_M_it;
+ }
+
+ decltype(auto)
+ operator->() const requires __detail::__common_iter_has_arrow<_It>
+ {
+ __glibcxx_assert(_M_index == 0);
+ if constexpr (is_pointer_v<_It> || requires { _M_it.operator->(); })
+ return _M_it;
+ else if constexpr (is_reference_v<iter_reference_t<_It>>)
+ {
+ auto&& __tmp = *_M_it;
+ return std::__addressof(__tmp);
+ }
+ else
+ return _Common_iter_proxy(*_M_it);
+ }
+
+ common_iterator&
+ operator++()
+ {
+ __glibcxx_assert(_M_index == 0);
+ ++_M_it;
+ return *this;
+ }
+
+ decltype(auto)
+ operator++(int)
+ {
+ __glibcxx_assert(_M_index == 0);
+ if constexpr (forward_iterator<_It>)
+ {
+ common_iterator __tmp = *this;
+ ++*this;
+ return __tmp;
+ }
+ else
+ return _M_it++;
+ }
+
+ template<typename _It2, sentinel_for<_It> _Sent2>
+ requires sentinel_for<_Sent, _It2>
+ friend bool
+ operator==(const common_iterator& __x,
+ const common_iterator<_It2, _Sent2>& __y)
+ {
+ switch(__x._M_index << 2 | __y._M_index)
+ {
+ case 0b0000:
+ case 0b0101:
+ return true;
+ case 0b0001:
+ return __x._M_it == __y._M_sent;
+ case 0b0100:
+ return __x._M_sent == __y._M_it;
+ default:
+ __glibcxx_assert(__x._M_has_value());
+ __glibcxx_assert(__y._M_has_value());
+ __builtin_unreachable();
+ }
+ }
+
+ template<typename _It2, sentinel_for<_It> _Sent2>
+ requires sentinel_for<_Sent, _It2> && equality_comparable_with<_It, _It2>
+ friend bool
+ operator==(const common_iterator& __x,
+ const common_iterator<_It2, _Sent2>& __y)
+ {
+ switch(__x._M_index << 2 | __y._M_index)
+ {
+ case 0b0101:
+ return true;
+ case 0b0000:
+ return __x._M_it == __y._M_it;
+ case 0b0001:
+ return __x._M_it == __y._M_sent;
+ case 0b0100:
+ return __x._M_sent == __y._M_it;
+ default:
+ __glibcxx_assert(__x._M_has_value());
+ __glibcxx_assert(__y._M_has_value());
+ __builtin_unreachable();
+ }
+ }
+
+ template<sized_sentinel_for<_It> _It2, sized_sentinel_for<_It> _Sent2>
+ requires sized_sentinel_for<_Sent, _It2>
+ friend iter_difference_t<_It2>
+ operator-(const common_iterator& __x,
+ const common_iterator<_It2, _Sent2>& __y)
+ {
+ switch(__x._M_index << 2 | __y._M_index)
+ {
+ case 0b0101:
+ return 0;
+ case 0b0000:
+ return __x._M_it - __y._M_it;
+ case 0b0001:
+ return __x._M_it - __y._M_sent;
+ case 0b0100:
+ return __x._M_sent - __y._M_it;
+ default:
+ __glibcxx_assert(__x._M_has_value());
+ __glibcxx_assert(__y._M_has_value());
+ __builtin_unreachable();
+ }
+ }
+
+ friend iter_rvalue_reference_t<_It>
+ iter_move(const common_iterator& __i)
+ noexcept(noexcept(ranges::iter_move(std::declval<const _It&>())))
+ requires input_iterator<_It>
+ {
+ __glibcxx_assert(__i._M_index == 0);
+ return ranges::iter_move(__i._M_it);
+ }
+
+ template<indirectly_swappable<_It> _It2, typename _Sent2>
+ friend void
+ iter_swap(const common_iterator& __x,
+ const common_iterator<_It2, _Sent2>& __y)
+ noexcept(noexcept(ranges::iter_swap(std::declval<const _It&>(),
+ std::declval<const _It2&>())))
+ {
+ __glibcxx_assert(__x._M_index == 0);
+ __glibcxx_assert(__y._M_index == 0);
+ return ranges::iter_swap(__x._M_it, __y._M_it);
+ }
+
+ private:
+ template<input_or_output_iterator _It2, sentinel_for<_It2> _Sent2>
+ friend class common_iterator;
+
+ bool _M_has_value() const noexcept { return _M_index < 2; }
+
+ union
+ {
+ _It _M_it;
+ _Sent _M_sent;
+ unsigned char _M_valueless;
+ };
+ unsigned char _M_index; // 0==_M_it, 1==_M_sent, 2==valueless
+ };
+
+ template<typename _It, typename _Sent>
+ struct incrementable_traits<common_iterator<_It, _Sent>>
+ {
+ using difference_type = iter_difference_t<_It>;
+ };
+
+ namespace __detail
+ {
+ // FIXME: This has to be at namespace-scope because of PR 92078.
+ template<typename _Iter>
+ struct __common_iter_ptr
+ {
+ using type = void;
+ };
+
+ template<typename _Iter>
+ requires __detail::__common_iter_has_arrow<_Iter>
+ struct __common_iter_ptr<_Iter>
+ {
+ using type = decltype(std::declval<const _Iter&>().operator->());
+ };
+ } // namespace __detail
+
+ template<input_iterator _It, typename _Sent>
+ struct iterator_traits<common_iterator<_It, _Sent>>
+ {
+ using iterator_concept = conditional_t<forward_iterator<_It>,
+ forward_iterator_tag, input_iterator_tag>;
+ using iterator_category = __detail::__clamp_iter_cat<
+ typename iterator_traits<_It>::iterator_category,
+ forward_iterator_tag, input_iterator_tag>;
+ using value_type = iter_value_t<_It>;
+ using difference_type = iter_difference_t<_It>;
+ using pointer = typename
+ __detail::__common_iter_ptr<common_iterator<_It, _Sent>>::type;
+ using reference = iter_reference_t<_It>;
+ };
+
+ // [iterators.counted] Counted iterators
+
+ /// An iterator adaptor that keeps track of the distance to the end.
+ template<input_or_output_iterator _It>
+ class counted_iterator
+ {
+ public:
+ using iterator_type = _It;
+
+ constexpr counted_iterator() = default;
+
+ constexpr
+ counted_iterator(_It __i, iter_difference_t<_It> __n)
+ : _M_current(__i), _M_length(__n)
+ { __glibcxx_assert(__n >= 0); }
+
+ template<typename _It2>
+ requires convertible_to<const _It2&, _It>
+ constexpr
+ counted_iterator(const counted_iterator<_It2>& __x)
+ : _M_current(__x._M_current), _M_length(__x._M_length)
+ { }
+
+ template<typename _It2>
+ requires assignable_from<_It&, const _It2&>
+ constexpr counted_iterator&
+ operator=(const counted_iterator<_It2>& __x)
+ {
+ _M_current = __x._M_current;
+ _M_length = __x._M_length;
+ return *this;
+ }
+
+ constexpr _It
+ base() const &
+ noexcept(is_nothrow_copy_constructible_v<_It>)
+ requires copy_constructible<_It>
+ { return _M_current; }
+
+ constexpr _It
+ base() &&
+ noexcept(is_nothrow_move_constructible_v<_It>)
+ { return std::move(_M_current); }
+
+ constexpr iter_difference_t<_It>
+ count() const noexcept { return _M_length; }
+
+ constexpr decltype(auto)
+ operator*()
+ noexcept(noexcept(*_M_current))
+ { return *_M_current; }
+
+ constexpr decltype(auto)
+ operator*() const
+ noexcept(noexcept(*_M_current))
+ requires __detail::__dereferenceable<const _It>
+ { return *_M_current; }
+
+ constexpr counted_iterator&
+ operator++()
+ {
+ __glibcxx_assert(_M_length > 0);
+ ++_M_current;
+ --_M_length;
+ return *this;
+ }
+
+ decltype(auto)
+ operator++(int)
+ {
+ __glibcxx_assert(_M_length > 0);
+ --_M_length;
+ __try
+ {
+ return _M_current++;
+ } __catch(...) {
+ ++_M_length;
+ throw;
+ }
+
+ }
+
+ constexpr counted_iterator
+ operator++(int) requires forward_iterator<_It>
+ {
+ auto __tmp = *this;
+ ++*this;
+ return __tmp;
+ }
+
+ constexpr counted_iterator&
+ operator--() requires bidirectional_iterator<_It>
+ {
+ --_M_current;
+ ++_M_length;
+ return *this;
+ }
+
+ constexpr counted_iterator
+ operator--(int) requires bidirectional_iterator<_It>
+ {
+ auto __tmp = *this;
+ --*this;
+ return __tmp;
+ }
+
+ constexpr counted_iterator
+ operator+(iter_difference_t<_It> __n) const
+ requires random_access_iterator<_It>
+ { return counted_iterator(_M_current + __n, _M_length - __n); }
+
+ friend constexpr counted_iterator
+ operator+(iter_difference_t<_It> __n, const counted_iterator& __x)
+ requires random_access_iterator<_It>
+ { return __x + __n; }
+
+ constexpr counted_iterator&
+ operator+=(iter_difference_t<_It> __n)
+ requires random_access_iterator<_It>
+ {
+ __glibcxx_assert(__n <= _M_length);
+ _M_current += __n;
+ _M_length -= __n;
+ return *this;
+ }
+
+ constexpr counted_iterator
+ operator-(iter_difference_t<_It> __n) const
+ requires random_access_iterator<_It>
+ { return counted_iterator(_M_current - __n, _M_length + __n); }
+
+ template<common_with<_It> _It2>
+ friend constexpr iter_difference_t<_It2>
+ operator-(const counted_iterator& __x,
+ const counted_iterator<_It2>& __y)
+ { return __y._M_length - __x._M_length; }
+
+ friend constexpr iter_difference_t<_It>
+ operator-(const counted_iterator& __x, default_sentinel_t)
+ { return -__x._M_length; }
+
+ friend constexpr iter_difference_t<_It>
+ operator-(default_sentinel_t, const counted_iterator& __y)
+ { return __y._M_length; }
+
+ constexpr counted_iterator&
+ operator-=(iter_difference_t<_It> __n)
+ requires random_access_iterator<_It>
+ {
+ __glibcxx_assert(-__n <= _M_length);
+ _M_current -= __n;
+ _M_length += __n;
+ return *this;
+ }
+
+ constexpr decltype(auto)
+ operator[](iter_difference_t<_It> __n) const
+ noexcept(noexcept(_M_current[__n]))
+ requires random_access_iterator<_It>
+ {
+ __glibcxx_assert(__n < _M_length);
+ return _M_current[__n];
+ }
+
+ template<common_with<_It> _It2>
+ friend constexpr bool
+ operator==(const counted_iterator& __x,
+ const counted_iterator<_It2>& __y)
+ { return __x._M_length == __y._M_length; }
+
+ friend constexpr bool
+ operator==(const counted_iterator& __x, default_sentinel_t)
+ { return __x._M_length == 0; }
+
+ template<common_with<_It> _It2>
+ friend constexpr strong_ordering
+ operator<=>(const counted_iterator& __x,
+ const counted_iterator<_It2>& __y)
+ { return __y._M_length <=> __x._M_length; }
+
+ friend constexpr iter_rvalue_reference_t<_It>
+ iter_move(const counted_iterator& __i)
+ noexcept(noexcept(ranges::iter_move(__i._M_current)))
+ requires input_iterator<_It>
+ { return ranges::iter_move(__i._M_current); }
+
+ template<indirectly_swappable<_It> _It2>
+ friend constexpr void
+ iter_swap(const counted_iterator& __x,
+ const counted_iterator<_It2>& __y)
+ noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current)))
+ { ranges::iter_swap(__x._M_current, __y._M_current); }
+
+ private:
+ template<input_or_output_iterator _It2> friend class counted_iterator;
+
+ _It _M_current = _It();
+ iter_difference_t<_It> _M_length = 0;
+ };
+
+ template<typename _It>
+ struct incrementable_traits<counted_iterator<_It>>
+ {
+ using difference_type = iter_difference_t<_It>;
+ };
+
+ template<input_iterator _It>
+ struct iterator_traits<counted_iterator<_It>> : iterator_traits<_It>
+ {
+ using pointer = void;
+ };
+#endif // C++20
+
// @} group iterators
template<typename _Iterator>
@@ -1332,8 +2014,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
using __iter_to_alloc_t =
pair<add_const_t<__iter_key_t<_InputIterator>>,
__iter_val_t<_InputIterator>>;
-
-#endif
+#endif // __cpp_deduction_guides
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace
diff --git a/libstdc++-v3/include/debug/array b/libstdc++-v3/include/debug/array
index 5566a087f9a..4e0fac8daac 100644
--- a/libstdc++-v3/include/debug/array
+++ b/libstdc++-v3/include/debug/array
@@ -80,11 +80,11 @@ namespace __debug
// No explicit construct/copy/destroy for aggregate type.
// DR 776.
- void
+ _GLIBCXX20_CONSTEXPR void
fill(const value_type& __u)
{ std::fill_n(begin(), size(), __u); }
- void
+ _GLIBCXX20_CONSTEXPR void
swap(array& __other)
noexcept(_AT_Type::_Is_nothrow_swappable::value)
{ std::swap_ranges(begin(), end(), __other.begin()); }
@@ -282,6 +282,7 @@ namespace __debug
#endif
template<typename _Tp, std::size_t _Nm>
+ _GLIBCXX20_CONSTEXPR
inline void
swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two)
noexcept(noexcept(__one.swap(__two)))
diff --git a/libstdc++-v3/include/debug/helper_functions.h b/libstdc++-v3/include/debug/helper_functions.h
index ac93ee04720..0344f27143b 100644
--- a/libstdc++-v3/include/debug/helper_functions.h
+++ b/libstdc++-v3/include/debug/helper_functions.h
@@ -168,7 +168,7 @@ namespace __gnu_debug
std::random_access_iterator_tag)
{
return
- __valid_range_aux(__first, __last, std::input_iterator_tag{})
+ __valid_range_aux(__first, __last, std::input_iterator_tag())
&& __first <= __last;
}
@@ -192,7 +192,7 @@ namespace __gnu_debug
typename _Distance_traits<_InputIterator>::__type& __dist,
std::__false_type)
{
- if (!__valid_range_aux(__first, __last, std::input_iterator_tag{}))
+ if (!__valid_range_aux(__first, __last, std::input_iterator_tag()))
return false;
__dist = __get_distance(__first, __last);
diff --git a/libstdc++-v3/include/debug/safe_iterator.h b/libstdc++-v3/include/debug/safe_iterator.h
index 6700eafca0b..fa0d03f39dc 100644
--- a/libstdc++-v3/include/debug/safe_iterator.h
+++ b/libstdc++-v3/include/debug/safe_iterator.h
@@ -140,6 +140,10 @@ namespace __gnu_debug
typedef typename _Traits::reference reference;
typedef typename _Traits::pointer pointer;
+#if __cplusplus > 201703L && __cpp_lib_concepts
+ using iterator_concept = std::__detail::__iter_concept<_Iterator>;
+#endif
+
/// @post the iterator is singular and unattached
_Safe_iterator() _GLIBCXX_NOEXCEPT : _Iter_base() { }
diff --git a/libstdc++-v3/include/experimental/bits/fs_path.h b/libstdc++-v3/include/experimental/bits/fs_path.h
index a3655f616f2..5ce012eec81 100644
--- a/libstdc++-v3/include/experimental/bits/fs_path.h
+++ b/libstdc++-v3/include/experimental/bits/fs_path.h
@@ -71,111 +71,129 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
using std::basic_string_view;
#endif
- /**
- * @addtogroup filesystem-ts
- * @{
+ /** @addtogroup filesystem-ts
+ * @{
*/
- /// A filesystem path.
- class path
- {
- template<typename _CharT,
- typename _Ch = typename remove_const<_CharT>::type>
- using __is_encoded_char
- = __or_<is_same<_Ch, char>,
- is_same<_Ch, wchar_t>,
+ /// @cond undocumented
+namespace __detail
+{
+ template<typename _CharT,
+ typename _Ch = typename remove_const<_CharT>::type>
+ using __is_encoded_char
+ = __or_<is_same<_Ch, char>,
+ is_same<_Ch, wchar_t>,
#ifdef _GLIBCXX_USE_CHAR8_T
- is_same<_Ch, char8_t>,
+ is_same<_Ch, char8_t>,
#endif
- is_same<_Ch, char16_t>,
- is_same<_Ch, char32_t>>;
+ is_same<_Ch, char16_t>,
+ is_same<_Ch, char32_t>>;
- template<typename _Iter,
- typename _Iter_traits = std::iterator_traits<_Iter>>
- using __is_path_iter_src
- = __and_<__is_encoded_char<typename _Iter_traits::value_type>,
- std::is_base_of<std::input_iterator_tag,
- typename _Iter_traits::iterator_category>>;
+ template<typename _Iter,
+ typename _Iter_traits = std::iterator_traits<_Iter>>
+ using __is_path_iter_src
+ = __and_<__is_encoded_char<typename _Iter_traits::value_type>,
+ std::is_base_of<std::input_iterator_tag,
+ typename _Iter_traits::iterator_category>>;
- template<typename _Iter>
- static __is_path_iter_src<_Iter>
- __is_path_src(_Iter, int);
+ template<typename _Iter>
+ static __is_path_iter_src<_Iter>
+ __is_path_src(_Iter, int);
- template<typename _CharT, typename _Traits, typename _Alloc>
- static __is_encoded_char<_CharT>
- __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ static __is_encoded_char<_CharT>
+ __is_path_src(const basic_string<_CharT, _Traits, _Alloc>&, int);
#if __cplusplus >= 201402L
- template<typename _CharT, typename _Traits>
- static __is_encoded_char<_CharT>
- __is_path_src(const basic_string_view<_CharT, _Traits>&, int);
+ template<typename _CharT, typename _Traits>
+ static __is_encoded_char<_CharT>
+ __is_path_src(const basic_string_view<_CharT, _Traits>&, int);
#endif
- template<typename _Unknown>
- static std::false_type
- __is_path_src(const _Unknown&, ...);
+ template<typename _Unknown>
+ static std::false_type
+ __is_path_src(const _Unknown&, ...);
- template<typename _Tp1, typename _Tp2>
- struct __constructible_from;
+ template<typename _Tp1, typename _Tp2>
+ struct __constructible_from;
- template<typename _Iter>
- struct __constructible_from<_Iter, _Iter>
- : __is_path_iter_src<_Iter>
- { };
+ template<typename _Iter>
+ struct __constructible_from<_Iter, _Iter>
+ : __is_path_iter_src<_Iter>
+ { };
- template<typename _Source>
- struct __constructible_from<_Source, void>
- : decltype(__is_path_src(std::declval<_Source>(), 0))
- { };
-
- template<typename _Tp1, typename _Tp2 = void,
- typename _Tp1_nocv = typename remove_cv<_Tp1>::type,
- typename _Tp1_noptr = typename remove_pointer<_Tp1>::type>
- using _Path = typename
- std::enable_if<__and_<__not_<is_same<_Tp1_nocv, path>>,
- __not_<is_void<_Tp1_noptr>>,
- __constructible_from<_Tp1, _Tp2>>::value,
- path>::type;
+ template<typename _Source>
+ struct __constructible_from<_Source, void>
+ : decltype(__is_path_src(std::declval<_Source>(), 0))
+ { };
+
+ template<typename _Tp1, typename _Tp2 = void,
+ typename _Tp1_nocv = typename remove_cv<_Tp1>::type,
+ typename _Tp1_noptr = typename remove_pointer<_Tp1>::type>
+ using _Path = typename
+ std::enable_if<__and_<__not_<is_same<_Tp1_nocv, path>>,
+ __not_<is_void<_Tp1_noptr>>,
+ __constructible_from<_Tp1, _Tp2>>::value,
+ path>::type;
- template<typename _Source>
- static _Source
- _S_range_begin(_Source __begin) { return __begin; }
+ template<typename _Source>
+ static _Source
+ _S_range_begin(_Source __begin) { return __begin; }
- struct __null_terminated { };
+ struct __null_terminated { };
- template<typename _Source>
- static __null_terminated
- _S_range_end(_Source) { return {}; }
+ template<typename _Source>
+ static __null_terminated
+ _S_range_end(_Source) { return {}; }
- template<typename _CharT, typename _Traits, typename _Alloc>
- static const _CharT*
- _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
- { return __str.data(); }
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ static const _CharT*
+ _S_range_begin(const basic_string<_CharT, _Traits, _Alloc>& __str)
+ { return __str.data(); }
- template<typename _CharT, typename _Traits, typename _Alloc>
- static const _CharT*
- _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
- { return __str.data() + __str.size(); }
+ template<typename _CharT, typename _Traits, typename _Alloc>
+ static const _CharT*
+ _S_range_end(const basic_string<_CharT, _Traits, _Alloc>& __str)
+ { return __str.data() + __str.size(); }
#if __cplusplus >= 201402L
- template<typename _CharT, typename _Traits>
- static const _CharT*
- _S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
- { return __str.data(); }
-
- template<typename _CharT, typename _Traits>
- static const _CharT*
- _S_range_end(const basic_string_view<_CharT, _Traits>& __str)
- { return __str.data() + __str.size(); }
+ template<typename _CharT, typename _Traits>
+ static const _CharT*
+ _S_range_begin(const basic_string_view<_CharT, _Traits>& __str)
+ { return __str.data(); }
+
+ template<typename _CharT, typename _Traits>
+ static const _CharT*
+ _S_range_end(const basic_string_view<_CharT, _Traits>& __str)
+ { return __str.data() + __str.size(); }
+#endif
+
+ template<typename _Tp,
+ typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
+ typename _Val = typename std::iterator_traits<_Iter>::value_type,
+ typename _UnqualVal = typename std::remove_const<_Val>::type>
+ using __value_type_is_char = typename std::enable_if<
+ std::is_same<_UnqualVal, char>::value,
+ _UnqualVal>::type;
+
+ template<typename _Tp,
+ typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
+ typename _Val = typename std::iterator_traits<_Iter>::value_type,
+ typename _UnqualVal = typename std::remove_const<_Val>::type>
+ using __value_type_is_char_or_char8_t = typename std::enable_if<
+ __or_<
+ std::is_same<_UnqualVal, char>
+#ifdef _GLIBCXX_USE_CHAR8_T
+ ,std::is_same<_UnqualVal, char8_t>
#endif
+ >::value, _UnqualVal>::type;
- template<typename _Tp,
- typename _Iter = decltype(_S_range_begin(std::declval<_Tp>())),
- typename _Val = typename std::iterator_traits<_Iter>::value_type>
- using __value_type_is_char = typename std::enable_if<
- std::is_same<typename std::remove_const<_Val>::type, char>::value
- >::type;
+} // namespace __detail
+ /// @endcond
+ /// A filesystem path.
+ class path
+ {
public:
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
typedef wchar_t value_type;
@@ -205,29 +223,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
{ _M_split_cmpts(); }
template<typename _Source,
- typename _Require = _Path<_Source>>
+ typename _Require = __detail::_Path<_Source>>
path(_Source const& __source)
- : _M_pathname(_S_convert(_S_range_begin(__source),
- _S_range_end(__source)))
+ : _M_pathname(_S_convert(__detail::_S_range_begin(__source),
+ __detail::_S_range_end(__source)))
{ _M_split_cmpts(); }
template<typename _InputIterator,
- typename _Require = _Path<_InputIterator, _InputIterator>>
+ typename _Require = __detail::_Path<_InputIterator, _InputIterator>>
path(_InputIterator __first, _InputIterator __last)
: _M_pathname(_S_convert(__first, __last))
{ _M_split_cmpts(); }
template<typename _Source,
- typename _Require = _Path<_Source>,
- typename _Require2 = __value_type_is_char<_Source>>
+ typename _Require = __detail::_Path<_Source>,
+ typename _Require2 = __detail::__value_type_is_char<_Source>>
path(_Source const& __source, const locale& __loc)
- : _M_pathname(_S_convert_loc(_S_range_begin(__source),
- _S_range_end(__source), __loc))
+ : _M_pathname(_S_convert_loc(__detail::_S_range_begin(__source),
+ __detail::_S_range_end(__source), __loc))
{ _M_split_cmpts(); }
template<typename _InputIterator,
- typename _Require = _Path<_InputIterator, _InputIterator>,
- typename _Require2 = __value_type_is_char<_InputIterator>>
+ typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
+ typename _Require2 = __detail::__value_type_is_char<_InputIterator>>
path(_InputIterator __first, _InputIterator __last, const locale& __loc)
: _M_pathname(_S_convert_loc(__first, __last, __loc))
{ _M_split_cmpts(); }
@@ -242,17 +260,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
path& assign(string_type&& __source);
template<typename _Source>
- _Path<_Source>&
+ __detail::_Path<_Source>&
operator=(_Source const& __source)
{ return *this = path(__source); }
template<typename _Source>
- _Path<_Source>&
+ __detail::_Path<_Source>&
assign(_Source const& __source)
{ return *this = path(__source); }
template<typename _InputIterator>
- _Path<_InputIterator, _InputIterator>&
+ __detail::_Path<_InputIterator, _InputIterator>&
assign(_InputIterator __first, _InputIterator __last)
{ return *this = path(__first, __last); }
@@ -260,21 +278,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
path& operator/=(const path& __p) { return _M_append(__p._M_pathname); }
- template <class _Source>
- _Path<_Source>&
+ template<typename _Source>
+ __detail::_Path<_Source>&
operator/=(_Source const& __source)
{ return append(__source); }
template<typename _Source>
- _Path<_Source>&
+ __detail::_Path<_Source>&
append(_Source const& __source)
{
- return _M_append(_S_convert(_S_range_begin(__source),
- _S_range_end(__source)));
+ return _M_append(_S_convert(__detail::_S_range_begin(__source),
+ __detail::_S_range_end(__source)));
}
template<typename _InputIterator>
- _Path<_InputIterator, _InputIterator>&
+ __detail::_Path<_InputIterator, _InputIterator>&
append(_InputIterator __first, _InputIterator __last)
{ return _M_append(_S_convert(__first, __last)); }
@@ -289,20 +307,23 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#endif
template<typename _Source>
- _Path<_Source>&
+ __detail::_Path<_Source>&
operator+=(_Source const& __x) { return concat(__x); }
template<typename _CharT>
- _Path<_CharT*, _CharT*>&
+ __detail::_Path<_CharT*, _CharT*>&
operator+=(_CharT __x);
template<typename _Source>
- _Path<_Source>&
+ __detail::_Path<_Source>&
concat(_Source const& __x)
- { return *this += _S_convert(_S_range_begin(__x), _S_range_end(__x)); }
+ {
+ return *this += _S_convert(__detail::_S_range_begin(__x),
+ __detail::_S_range_end(__x));
+ }
template<typename _InputIterator>
- _Path<_InputIterator, _InputIterator>&
+ __detail::_Path<_InputIterator, _InputIterator>&
concat(_InputIterator __first, _InputIterator __last)
{ return *this += _S_convert(__first, __last); }
@@ -446,11 +467,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
struct _Cvt;
static string_type
- _S_convert(value_type* __src, __null_terminated)
+ _S_convert(value_type* __src, __detail::__null_terminated)
{ return string_type(__src); }
static string_type
- _S_convert(const value_type* __src, __null_terminated)
+ _S_convert(const value_type* __src, __detail::__null_terminated)
{ return string_type(__src); }
template<typename _Iter>
@@ -464,7 +485,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
template<typename _InputIterator>
static string_type
- _S_convert(_InputIterator __src, __null_terminated)
+ _S_convert(_InputIterator __src, __detail::__null_terminated)
{
auto __s = _S_string_from_iter(__src);
return _S_convert(__s.c_str(), __s.c_str() + __s.size());
@@ -484,7 +505,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
template<typename _InputIterator>
static string_type
- _S_convert_loc(_InputIterator __src, __null_terminated,
+ _S_convert_loc(_InputIterator __src, __detail::__null_terminated,
const std::locale& __loc)
{
const std::string __s = _S_string_from_iter(__src);
@@ -580,12 +601,11 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
}
/// Create a path from a UTF-8-encoded sequence of char
- // TODO constrain with _Path<InputIterator, InputIterator> and __value_type_is_char
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
template<typename _InputIterator>
inline path
- u8path(_InputIterator __first, _InputIterator __last)
+ __u8path(_InputIterator __first, _InputIterator __last, char)
{
-#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
// XXX This assumes native wide encoding is UTF-16.
std::codecvt_utf8_utf16<path::value_type> __cvt;
path::string_type __tmp;
@@ -596,20 +616,75 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
_GLIBCXX_THROW_OR_ABORT(filesystem_error(
"Cannot convert character sequence",
std::make_error_code(errc::illegal_byte_sequence)));
+ }
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<typename _InputIterator>
+ inline path
+ __u8path(_InputIterator __first, _InputIterator __last, char8_t)
+ {
+ return path{ __first, __last };
+ }
+#endif // _GLIBCXX_USE_CHAR8_T
+#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
+
+ template<typename _InputIterator,
+ typename _Require = __detail::_Path<_InputIterator, _InputIterator>,
+ typename _CharT =
+ __detail::__value_type_is_char_or_char8_t<_InputIterator>>
+ inline path
+ u8path(_InputIterator __first, _InputIterator __last)
+ {
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+ return __u8path(__first, __last, _CharT{});
#else
return path{ __first, __last };
#endif
}
/// Create a path from a UTF-8-encoded sequence of char
- // TODO constrain with _Path<Source> and __value_type_is_char
+#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+ inline path
+ __u8path(const string& __s, char)
+ {
+ return filesystem::u8path(__s.data(), __s.data() + __s.size());
+ }
+
+ template<typename _Source>
+ inline __enable_if_t<is_convertible<const _Source&, string>::value, path>
+ __u8path(const _Source& __source, char)
+ {
+ std::string __s = __source;
+ return filesystem::u8path(__s.data(), __s.data() + __s.size());
+ }
+
+ template<typename _Source>
+ inline __enable_if_t<!is_convertible<const _Source&, string>::value, path>
+ __u8path(const _Source& __source, char)
+ {
+ std::string __s = path::_S_string_from_iter(__source);
+ return filesystem::u8path(__s.data(), __s.data() + __s.size());
+ }
+
+#ifdef _GLIBCXX_USE_CHAR8_T
template<typename _Source>
inline path
+ __u8path(const _Source& __source, char8_t)
+ {
+ return path{ __source };
+ }
+#endif // _GLIBCXX_USE_CHAR8_T
+#endif // _GLIBCXX_FILESYSTEM_IS_WINDOWS
+
+ template<typename _Source,
+ typename _Require = __detail::_Path<_Source>,
+ typename _CharT =
+ __detail::__value_type_is_char_or_char8_t<_Source>>
+ inline path
u8path(const _Source& __source)
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
- std::string __s = path::_S_string_from_iter(__source);
- return filesystem::u8path(__s.data(), __s.data() + __s.size());
+ return __u8path(__source, _CharT{});
#else
return path{ __source };
#endif
@@ -672,8 +747,21 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
struct path::_Cvt
{
#ifdef _GLIBCXX_FILESYSTEM_IS_WINDOWS
+#ifdef _GLIBCXX_USE_CHAR8_T
+ static string_type
+ _S_wconvert(const char8_t* __f, const char8_t* __l, const char8_t*)
+ {
+ const char* __f2 = (const char*)__f;
+ const char* __l2 = (const char*)__l;
+ std::wstring __wstr;
+ std::codecvt_utf8_utf16<wchar_t> __wcvt;
+ if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt))
+ return __wstr;
+ }
+#endif
+
static string_type
- _S_wconvert(const char* __f, const char* __l, true_type)
+ _S_wconvert(const char* __f, const char* __l, const char*)
{
using _Cvt = std::codecvt<wchar_t, char, mbstate_t>;
const auto& __cvt = std::use_facet<_Cvt>(std::locale{});
@@ -686,36 +774,29 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
}
static string_type
- _S_wconvert(const _CharT* __f, const _CharT* __l, false_type)
+ _S_wconvert(const _CharT* __f, const _CharT* __l, const void*)
{
-#ifdef _GLIBCXX_USE_CHAR8_T
- if constexpr (is_same<_CharT, char8_t>::value)
- return _S_wconvert((const char*)__f, (const char*)__l, true_type());
- else
-#endif
+ struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t>
+ { } __cvt;
+ std::string __str;
+ if (__str_codecvt_out_all(__f, __l, __str, __cvt))
{
- struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t>
- { } __cvt;
- std::string __str;
- if (__str_codecvt_out_all(__f, __l, __str, __cvt))
- {
- const char* __f2 = __str.data();
- const char* __l2 = __f2 + __str.size();
- std::codecvt_utf8_utf16<wchar_t> __wcvt;
- std::wstring __wstr;
- if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt))
- return __wstr;
- }
- _GLIBCXX_THROW_OR_ABORT(filesystem_error(
- "Cannot convert character sequence",
- std::make_error_code(errc::illegal_byte_sequence)));
+ const char* __f2 = __str.data();
+ const char* __l2 = __f2 + __str.size();
+ std::codecvt_utf8_utf16<wchar_t> __wcvt;
+ std::wstring __wstr;
+ if (__str_codecvt_in_all(__f2, __l2, __wstr, __wcvt))
+ return __wstr;
}
+ _GLIBCXX_THROW_OR_ABORT(filesystem_error(
+ "Cannot convert character sequence",
+ std::make_error_code(errc::illegal_byte_sequence)));
}
static string_type
_S_convert(const _CharT* __f, const _CharT* __l)
{
- return _S_wconvert(__f, __l, is_same<_CharT, char>{});
+ return _S_wconvert(__f, __l, (const _CharT*)nullptr);
}
#else
static string_type
@@ -725,19 +806,17 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
if constexpr (is_same<_CharT, char8_t>::value)
return string_type(__f, __l);
else
- {
#endif
+ {
struct _UCvt : std::codecvt<_CharT, char, std::mbstate_t>
{ } __cvt;
std::string __str;
if (__str_codecvt_out_all(__f, __l, __str, __cvt))
return __str;
-#ifdef _GLIBCXX_USE_CHAR8_T
+ _GLIBCXX_THROW_OR_ABORT(filesystem_error(
+ "Cannot convert character sequence",
+ std::make_error_code(errc::illegal_byte_sequence)));
}
-#endif
- _GLIBCXX_THROW_OR_ABORT(filesystem_error(
- "Cannot convert character sequence",
- std::make_error_code(errc::illegal_byte_sequence)));
}
#endif
@@ -872,7 +951,7 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
#endif
template<typename _CharT>
- inline path::_Path<_CharT*, _CharT*>&
+ inline __detail::_Path<_CharT*, _CharT*>&
path::operator+=(_CharT __x)
{
auto* __addr = std::__addressof(__x);
diff --git a/libstdc++-v3/include/std/ostream b/libstdc++-v3/include/std/ostream
index 2541d978886..895e4d7ab4e 100644
--- a/libstdc++-v3/include/std/ostream
+++ b/libstdc++-v3/include/std/ostream
@@ -512,21 +512,62 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return (__out << __out.widen(__c)); }
// Specialization
- template <class _Traits>
+ template<typename _Traits>
inline basic_ostream<char, _Traits>&
operator<<(basic_ostream<char, _Traits>& __out, char __c)
{ return __ostream_insert(__out, &__c, 1); }
// Signed and unsigned
- template<class _Traits>
+ template<typename _Traits>
inline basic_ostream<char, _Traits>&
operator<<(basic_ostream<char, _Traits>& __out, signed char __c)
{ return (__out << static_cast<char>(__c)); }
- template<class _Traits>
+ template<typename _Traits>
inline basic_ostream<char, _Traits>&
operator<<(basic_ostream<char, _Traits>& __out, unsigned char __c)
{ return (__out << static_cast<char>(__c)); }
+
+#if __cplusplus > 201703L
+ // The following deleted overloads prevent formatting character values as
+ // numeric values.
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ template<typename _Traits>
+ basic_ostream<char, _Traits>&
+ operator<<(basic_ostream<char, _Traits>&, wchar_t) = delete;
+#endif // _GLIBCXX_USE_WCHAR_T
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<typename _Traits>
+ basic_ostream<char, _Traits>&
+ operator<<(basic_ostream<char, _Traits>&, char8_t) = delete;
+#endif
+
+ template<typename _Traits>
+ basic_ostream<char, _Traits>&
+ operator<<(basic_ostream<char, _Traits>&, char16_t) = delete;
+
+ template<typename _Traits>
+ basic_ostream<char, _Traits>&
+ operator<<(basic_ostream<char, _Traits>&, char32_t) = delete;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<typename _Traits>
+ basic_ostream<wchar_t, _Traits>&
+ operator<<(basic_ostream<wchar_t, _Traits>&, char8_t) = delete;
+#endif // _GLIBCXX_USE_CHAR8_T
+
+ template<typename _Traits>
+ basic_ostream<wchar_t, _Traits>&
+ operator<<(basic_ostream<wchar_t, _Traits>&, char16_t) = delete;
+
+ template<typename _Traits>
+ basic_ostream<wchar_t, _Traits>&
+ operator<<(basic_ostream<wchar_t, _Traits>&, char32_t) = delete;
+#endif // _GLIBCXX_USE_WCHAR_T
+#endif // C++20
//@}
//@{
@@ -560,7 +601,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s);
// Partial specializations
- template<class _Traits>
+ template<typename _Traits>
inline basic_ostream<char, _Traits>&
operator<<(basic_ostream<char, _Traits>& __out, const char* __s)
{
@@ -573,15 +614,56 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
// Signed and unsigned
- template<class _Traits>
+ template<typename _Traits>
inline basic_ostream<char, _Traits>&
operator<<(basic_ostream<char, _Traits>& __out, const signed char* __s)
{ return (__out << reinterpret_cast<const char*>(__s)); }
- template<class _Traits>
+ template<typename _Traits>
inline basic_ostream<char, _Traits> &
operator<<(basic_ostream<char, _Traits>& __out, const unsigned char* __s)
{ return (__out << reinterpret_cast<const char*>(__s)); }
+
+#if __cplusplus > 201703L
+ // The following deleted overloads prevent formatting strings as
+ // pointer values.
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+ template<typename _Traits>
+ basic_ostream<char, _Traits>&
+ operator<<(basic_ostream<char, _Traits>&, const wchar_t*) = delete;
+#endif // _GLIBCXX_USE_WCHAR_T
+
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<typename _Traits>
+ basic_ostream<char, _Traits>&
+ operator<<(basic_ostream<char, _Traits>&, const char8_t*) = delete;
+#endif // _GLIBCXX_USE_CHAR8_T
+
+ template<typename _Traits>
+ basic_ostream<char, _Traits>&
+ operator<<(basic_ostream<char, _Traits>&, const char16_t*) = delete;
+
+ template<typename _Traits>
+ basic_ostream<char, _Traits>&
+ operator<<(basic_ostream<char, _Traits>&, const char32_t*) = delete;
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+#ifdef _GLIBCXX_USE_CHAR8_T
+ template<typename _Traits>
+ basic_ostream<wchar_t, _Traits>&
+ operator<<(basic_ostream<wchar_t, _Traits>&, const char8_t*) = delete;
+#endif
+
+ template<typename _Traits>
+ basic_ostream<wchar_t, _Traits>&
+ operator<<(basic_ostream<wchar_t, _Traits>&, const char16_t*) = delete;
+
+ template<typename _Traits>
+ basic_ostream<wchar_t, _Traits>&
+ operator<<(basic_ostream<wchar_t, _Traits>&, const char32_t*) = delete;
+#endif // _GLIBCXX_USE_WCHAR_T
+#endif // C++20
//@}
// Standard basic_ostream manipulators
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py b/libstdc++-v3/python/libstdcxx/v6/printers.py
index cd79a1fa6e6..869a8286675 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -94,13 +94,78 @@ def find_type(orig, name):
# The type was not found, so try the superclass. We only need
# to check the first superclass, so we don't bother with
# anything fancier here.
- field = typ.fields()[0]
- if not field.is_base_class:
+ fields = typ.fields()
+ if len(fields) and fields[0].is_base_class:
+ typ = fields[0].type
+ else:
raise ValueError("Cannot find type %s::%s" % (str(orig), name))
- typ = field.type
_versioned_namespace = '__8::'
+def lookup_templ_spec(templ, *args):
+ """
+ Lookup template specialization templ<args...>
+ """
+ t = '{}<{}>'.format(templ, ', '.join([str(a) for a in args]))
+ try:
+ return gdb.lookup_type(t)
+ except gdb.error as e:
+ # Type not found, try again in versioned namespace.
+ global _versioned_namespace
+ if _versioned_namespace and _versioned_namespace not in templ:
+ t = t.replace('::', '::' + _versioned_namespace, 1)
+ try:
+ return gdb.lookup_type(t)
+ except gdb.error:
+ # If that also fails, rethrow the original exception
+ pass
+ raise e
+
+# Use this to find container node types instead of find_type,
+# see https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91997 for details.
+def lookup_node_type(nodename, containertype):
+ """
+ Lookup specialization of template NODENAME corresponding to CONTAINERTYPE.
+ e.g. if NODENAME is '_List_node' and CONTAINERTYPE is std::list<int>
+ then return the type std::_List_node<int>.
+ Returns None if not found.
+ """
+ # If nodename is unqualified, assume it's in namespace std.
+ if '::' not in nodename:
+ nodename = 'std::' + nodename
+ try:
+ valtype = find_type(containertype, 'value_type')
+ except:
+ valtype = containertype.template_argument(0)
+ valtype = valtype.strip_typedefs()
+ try:
+ return lookup_templ_spec(nodename, valtype)
+ except gdb.error as e:
+ # For debug mode containers the node is in std::__cxx1998.
+ if is_member_of_namespace(nodename, 'std'):
+ if is_member_of_namespace(containertype, 'std::__cxx1998',
+ 'std::__debug', '__gnu_debug'):
+ nodename = nodename.replace('::', '::__cxx1998::', 1)
+ return lookup_templ_spec(nodename, valtype)
+ try:
+ return lookup_templ_spec(nodename, valtype)
+ except gdb.error:
+ pass
+ return None
+
+def is_member_of_namespace(typ, *namespaces):
+ """
+ Test whether a type is a member of one of the specified namespaces.
+ The type can be specified as a string or a gdb.Type object.
+ """
+ if type(typ) is gdb.Type:
+ typ = str(typ)
+ typ = strip_versioned_namespace(typ)
+ for namespace in namespaces:
+ if typ.startswith(namespace + '::'):
+ return True
+ return False
+
def is_specialization_of(x, template_name):
"Test if a type is a given template instantiation."
global _versioned_namespace
@@ -253,40 +318,40 @@ class StdListPrinter:
self.val = val
def children(self):
- nodetype = find_type(self.val.type, '_Node')
- nodetype = nodetype.strip_typedefs().pointer()
+ nodetype = lookup_node_type('_List_node', self.val.type).pointer()
return self._iterator(nodetype, self.val['_M_impl']['_M_node'])
def to_string(self):
- if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']:
+ headnode = self.val['_M_impl']['_M_node']
+ if headnode['_M_next'] == headnode.address:
return 'empty %s' % (self.typename)
return '%s' % (self.typename)
class NodeIteratorPrinter:
- def __init__(self, typename, val, contname):
+ def __init__(self, typename, val, contname, nodename):
self.val = val
self.typename = typename
self.contname = contname
+ self.nodetype = lookup_node_type(nodename, val.type)
def to_string(self):
if not self.val['_M_node']:
return 'non-dereferenceable iterator for std::%s' % (self.contname)
- nodetype = find_type(self.val.type, '_Node')
- nodetype = nodetype.strip_typedefs().pointer()
- node = self.val['_M_node'].cast(nodetype).dereference()
+ node = self.val['_M_node'].cast(self.nodetype.pointer()).dereference()
return str(get_value_from_list_node(node))
class StdListIteratorPrinter(NodeIteratorPrinter):
"Print std::list::iterator"
def __init__(self, typename, val):
- NodeIteratorPrinter.__init__(self, typename, val, 'list')
+ NodeIteratorPrinter.__init__(self, typename, val, 'list', '_List_node')
class StdFwdListIteratorPrinter(NodeIteratorPrinter):
"Print std::forward_list::iterator"
def __init__(self, typename, val):
- NodeIteratorPrinter.__init__(self, typename, val, 'forward_list')
+ NodeIteratorPrinter.__init__(self, typename, val, 'forward_list',
+ '_Fwd_list_node')
class StdSlistPrinter:
"Print a __gnu_cxx::slist"
@@ -313,9 +378,8 @@ class StdSlistPrinter:
self.val = val
def children(self):
- nodetype = find_type(self.val.type, '_Node')
- nodetype = nodetype.strip_typedefs().pointer()
- return self._iterator(nodetype, self.val)
+ nodetype = lookup_node_type('__gnu_cxx::_Slist_node', self.val.type)
+ return self._iterator(nodetype.pointer(), self.val)
def to_string(self):
if self.val['_M_head']['_M_next'] == 0:
@@ -331,8 +395,7 @@ class StdSlistIteratorPrinter:
def to_string(self):
if not self.val['_M_node']:
return 'non-dereferenceable iterator for __gnu_cxx::slist'
- nodetype = find_type(self.val.type, '_Node')
- nodetype = nodetype.strip_typedefs().pointer()
+ nodetype = lookup_node_type('__gnu_cxx::_Slist_node', self.val.type).pointer()
return str(self.val['_M_node'].cast(nodetype).dereference()['_M_data'])
class StdVectorPrinter:
@@ -583,12 +646,8 @@ class StdRbtreeIteratorPrinter:
def __init__ (self, typename, val):
self.val = val
- valtype = self.val.type.template_argument(0).strip_typedefs()
- nodetype = '_Rb_tree_node<' + str(valtype) + '>'
- if _versioned_namespace and typename.startswith('std::' + _versioned_namespace):
- nodetype = _versioned_namespace + nodetype
- nodetype = gdb.lookup_type('std::' + nodetype)
- self.link_type = nodetype.strip_typedefs().pointer()
+ nodetype = lookup_node_type('_Rb_tree_node', self.val.type)
+ self.link_type = nodetype.pointer()
def to_string (self):
if not self.val['_M_node']:
@@ -653,9 +712,7 @@ class StdMapPrinter:
num_elements(len(RbtreeIterator (self.val))))
def children (self):
- rep_type = find_type(self.val.type, '_Rep_type')
- node = find_type(rep_type, '_Link_type')
- node = node.strip_typedefs()
+ node = lookup_node_type('_Rb_tree_node', self.val.type).pointer()
return self._iter (RbtreeIterator (self.val), node)
def display_hint (self):
@@ -693,9 +750,7 @@ class StdSetPrinter:
num_elements(len(RbtreeIterator (self.val))))
def children (self):
- rep_type = find_type(self.val.type, '_Rep_type')
- node = find_type(rep_type, '_Link_type')
- node = node.strip_typedefs()
+ node = lookup_node_type('_Rb_tree_node', self.val.type).pointer()
return self._iter (RbtreeIterator (self.val), node)
class StdBitsetPrinter:
@@ -853,11 +908,11 @@ class StdStringPrinter:
return 'string'
class Tr1HashtableIterator(Iterator):
- def __init__ (self, hash):
- self.buckets = hash['_M_buckets']
+ def __init__ (self, hashtable):
+ self.buckets = hashtable['_M_buckets']
self.bucket = 0
- self.bucket_count = hash['_M_bucket_count']
- self.node_type = find_type(hash.type, '_Node').pointer()
+ self.bucket_count = hashtable['_M_bucket_count']
+ self.node_type = find_type(hashtable.type, '_Node').pointer()
self.node = 0
while self.bucket != self.bucket_count:
self.node = self.buckets[self.bucket]
@@ -884,9 +939,13 @@ class Tr1HashtableIterator(Iterator):
return result
class StdHashtableIterator(Iterator):
- def __init__(self, hash):
- self.node = hash['_M_before_begin']['_M_nxt']
- self.node_type = find_type(hash.type, '__node_type').pointer()
+ def __init__(self, hashtable):
+ self.node = hashtable['_M_before_begin']['_M_nxt']
+ valtype = hashtable.type.template_argument(1)
+ cached = hashtable.type.template_argument(9).template_argument(0)
+ node_type = lookup_templ_spec('std::__detail::_Hash_node', str(valtype),
+ 'true' if cached else 'false')
+ self.node_type = node_type.pointer()
def __iter__(self):
return self
@@ -901,7 +960,7 @@ class StdHashtableIterator(Iterator):
return valptr.dereference()
class Tr1UnorderedSetPrinter:
- "Print a tr1::unordered_set"
+ "Print a std::unordered_set or tr1::unordered_set"
def __init__ (self, typename, val):
self.typename = strip_versioned_namespace(typename)
@@ -927,7 +986,7 @@ class Tr1UnorderedSetPrinter:
return izip (counter, StdHashtableIterator (self.hashtable()))
class Tr1UnorderedMapPrinter:
- "Print a tr1::unordered_map"
+ "Print a std::unordered_map or tr1::unordered_map"
def __init__ (self, typename, val):
self.typename = strip_versioned_namespace(typename)
@@ -998,8 +1057,7 @@ class StdForwardListPrinter:
self.typename = strip_versioned_namespace(typename)
def children(self):
- nodetype = find_type(self.val.type, '_Node')
- nodetype = nodetype.strip_typedefs().pointer()
+ nodetype = lookup_node_type('_Fwd_list_node', self.val.type).pointer()
return self._iterator(nodetype, self.val['_M_impl']['_M_head'])
def to_string(self):
diff --git a/libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc b/libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc
new file mode 100644
index 00000000000..275ef53fe6a
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/common_iterator/1.cc
@@ -0,0 +1,160 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <iterator>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ using I = std::common_iterator<int*, const int*>;
+ static_assert( std::is_default_constructible_v<I> );
+ static_assert( std::is_copy_constructible_v<I> );
+ static_assert( std::is_copy_assignable_v<I> );
+ static_assert( std::is_constructible_v<I, int*> );
+ static_assert( std::is_constructible_v<I, const int*> );
+
+ struct sentinel { operator int*() const { return nullptr; } };
+ using K = std::common_iterator<int*, sentinel>;
+ static_assert( std::is_constructible_v<I, const K&> );
+ static_assert( std::is_assignable_v<I, const K&> );
+
+ struct sentinel2
+ {
+ const int* p;
+ sentinel2(const int* p = 0) : p(p) { }
+ bool operator==(const int* p) const { return p == this->p; }
+ };
+
+ using J = std::common_iterator<const int*, sentinel2>;
+ static_assert( std::is_constructible_v<J, const I&> );
+ static_assert( std::is_convertible_v<const I&, J> );
+}
+
+void
+test02()
+{
+ struct sentinel { int limit; };
+
+ struct iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = int;
+ using difference_type = std::ptrdiff_t;
+ using reference = const int&;
+
+ const int& operator*() const { return counter; }
+
+ iterator& operator++() { ++counter; return *this; }
+
+ iterator operator++(int) { auto i = *this; ++counter; return i; }
+
+ bool operator==(sentinel s) const { return counter == s.limit; }
+
+ int counter = 0;
+ };
+
+ static_assert( std::sentinel_for<sentinel, iterator> );
+
+ int out[5] = { };
+ std::common_iterator<int*, const int*> obegin = std::begin(out);
+ std::common_iterator<int*, const int*> oend = std::cend(out);
+
+ iterator i;
+ sentinel s{5};
+ std::common_iterator<iterator, sentinel> begin = i, end = s;
+ while (begin != end)
+ *obegin++ = *begin++;
+
+ VERIFY(obegin == oend);
+ for (int& i : out)
+ VERIFY( i == (&i - out) );
+}
+
+void
+test03()
+{
+ int arr[2] = { 1, 2 };
+ std::common_iterator<int*, const int*> i = std::ranges::begin(arr);
+ std::common_iterator<int*, const int*> end = std::ranges::cend(arr);
+ VERIFY( i != end );
+ VERIFY( (end - i) == 2 );
+ VERIFY( (i - end) == -2 );
+ auto j = i;
+ VERIFY( j == i );
+ VERIFY( (j - i) == 0 );
+ j = end;
+ VERIFY( j != i );
+ VERIFY( j == end );
+ j = std::ranges::next(i);
+ VERIFY( j != i );
+ VERIFY( j != end );
+ VERIFY( (end - j) == 1 );
+ VERIFY( (j - i) == 1 );
+ VERIFY( (i - j) == -1 );
+ ++j;
+ VERIFY( j == end );
+ VERIFY( (end - j) == 0 );
+ j = i;
+ VERIFY( j == i );
+ VERIFY( (j - end) == -2 );
+ VERIFY( (j - i) == 0 );
+
+ try
+ {
+ struct S { operator const int*() const { throw 1; } };
+ i = std::common_iterator<int*, S>(S{});
+ VERIFY( false );
+ }
+ catch (int)
+ {
+ }
+}
+
+void
+test04()
+{
+ struct X
+ {
+ X(int i) : i(i) { }
+ X(X&& x) : i(x.i) { x.i = -1; }
+ X& operator=(X&& x) { i = x.i; x.i = 0; return *this; }
+ int i;
+ };
+
+ X arr[] = { 1, 2 };
+ std::common_iterator<X*, const X*> i(arr), j(arr+1);
+ std::ranges::iter_swap(i, j);
+ VERIFY( arr[0].i == 2 );
+ VERIFY( arr[1].i == 1 );
+
+ X x = std::ranges::iter_move(i);
+ VERIFY( arr[0].i == -1 );
+ VERIFY( x.i == 2 );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+ test04();
+}
diff --git a/libstdc++-v3/testsuite/24_iterators/counted_iterator/1.cc b/libstdc++-v3/testsuite/24_iterators/counted_iterator/1.cc
new file mode 100644
index 00000000000..b31469cdebf
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/counted_iterator/1.cc
@@ -0,0 +1,101 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <iterator>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ using I = std::counted_iterator<int*>;
+ static_assert( std::is_default_constructible_v<I> );
+ static_assert( std::is_copy_constructible_v<I> );
+ static_assert( std::is_copy_assignable_v<I> );
+ static_assert( ! std::is_constructible_v<I, int*> );
+ static_assert( std::is_constructible_v<I, int*, std::ptrdiff_t> );
+
+ using J = std::counted_iterator<const int*>;
+ static_assert( std::is_constructible_v<J, const I&> );
+ static_assert( std::is_convertible_v<const I&, J> );
+}
+
+void
+test02()
+{
+ int in[3] = { 1, 2, 3 };
+ std::counted_iterator<const int*> in_iter(std::begin(in), std::ssize(in));
+ VERIFY( in_iter.base() == in );
+ VERIFY( (std::default_sentinel - in_iter) == 3 );
+ VERIFY( (in_iter - std::default_sentinel) == -3 );
+
+ int out[4] = { };
+ std::counted_iterator<int*> out_iter(std::begin(out), std::ssize(out));
+ VERIFY( out_iter.base() == out );
+ VERIFY( (std::default_sentinel - out_iter) == 4 );
+ VERIFY( (out_iter - std::default_sentinel) == -4 );
+
+ while (in_iter != std::default_sentinel && out_iter != std::default_sentinel)
+ *out_iter++ = *in_iter++;
+
+ VERIFY(in_iter == std::default_sentinel);
+ VERIFY(out_iter != std::default_sentinel);
+ VERIFY( out[0] == 1 );
+ VERIFY( out[1] == 2 );
+ VERIFY( out[2] == 3 );
+ VERIFY( out[3] == 0 );
+
+ auto out2 = out_iter;
+ out2 += 1;
+ VERIFY( out2 == std::default_sentinel );
+ VERIFY( (out2 <=> out_iter) == std::strong_ordering::greater );
+ out2 -= 3;
+ VERIFY( (out_iter - out2) == 2 );
+ VERIFY( (out2 <=> out_iter) == std::strong_ordering::less );
+}
+
+void
+test03()
+{
+ struct X
+ {
+ X(int i) : i(i) { }
+ X(X&& x) : i(x.i) { x.i = -1; }
+ X& operator=(X&& x) { i = x.i; x.i = 0; return *this; }
+ int i;
+ };
+
+ X arr[] = { 1, 2 };
+ std::counted_iterator<X*> i(arr, 2), j(arr + 1, 1);
+ std::ranges::iter_swap(i, j);
+ VERIFY( arr[0].i == 2 );
+ VERIFY( arr[1].i == 1 );
+
+ X x = std::ranges::iter_move(i);
+ VERIFY( arr[0].i == -1 );
+ VERIFY( x.i == 2 );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+ test03();
+}
diff --git a/libstdc++-v3/testsuite/24_iterators/move_iterator/cust.cc b/libstdc++-v3/testsuite/24_iterators/move_iterator/cust.cc
new file mode 100644
index 00000000000..6d0817dc204
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/move_iterator/cust.cc
@@ -0,0 +1,50 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <iterator>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ struct X
+ {
+ X(int i) : i(i) { }
+ X(X&& x) : i(x.i) { x.i = -1; }
+ X& operator=(X&& x) { i = x.i; x.i = 0; return *this; }
+ int i;
+ };
+
+ X arr[] = { 1, 2 };
+ std::move_iterator<X*> i(arr), j(arr + 1);
+ std::ranges::iter_swap(i, j);
+ VERIFY( arr[0].i == 2 );
+ VERIFY( arr[1].i == 1 );
+
+ X x = std::ranges::iter_move(i);
+ VERIFY( arr[0].i == -1 );
+ VERIFY( x.i == 2 );
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/24_iterators/move_iterator/sentinel.cc b/libstdc++-v3/testsuite/24_iterators/move_iterator/sentinel.cc
new file mode 100644
index 00000000000..875a8fc37c4
--- /dev/null
+++ b/libstdc++-v3/testsuite/24_iterators/move_iterator/sentinel.cc
@@ -0,0 +1,91 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do run { target c++2a } }
+
+#include <iterator>
+#include <testsuite_hooks.h>
+
+void
+test01()
+{
+ using S = std::move_sentinel<const int*>;
+ using M = std::move_iterator<int*>;
+
+ static_assert( std::is_default_constructible_v<S> );
+ static_assert( std::is_copy_constructible_v<S> );
+ static_assert( std::is_copy_assignable_v<S> );
+ static_assert( std::is_constructible_v<S, std::move_sentinel<int*>> );
+ static_assert( std::is_assignable_v<S, std::move_sentinel<int*>> );
+
+ constexpr S s;
+ static_assert( s.base() == nullptr );
+
+ constexpr M m;
+ static_assert( m == s );
+ static_assert( s == m );
+ static_assert( !(m != s) );
+ static_assert( !(s != m) );
+
+ int i = 0;
+ M m2(&i);
+ VERIFY( m2 != s );
+ VERIFY( s != m2 );
+ VERIFY( !(m2 == s) );
+ VERIFY( !(s == m2) );
+}
+
+void
+test02()
+{
+ struct sentinel { int limit; };
+
+ struct iterator
+ {
+ using iterator_category = std::input_iterator_tag;
+ using value_type = int;
+ using difference_type = std::ptrdiff_t;
+ using reference = const int&;
+
+ const int& operator*() const { return counter; }
+
+ iterator& operator++() { ++counter; return *this; }
+
+ iterator operator++(int) { auto i = *this; ++counter; return i; }
+
+ bool operator==(sentinel s) const { return counter == s.limit; }
+
+ int counter = 0;
+ };
+
+ static_assert( std::sentinel_for<sentinel, iterator> );
+
+ iterator i;
+ sentinel s{5};
+ int count = 0;
+ for (auto m = std::make_move_iterator(i); m != std::move_sentinel{s}; ++m)
+ ++count;
+ VERIFY( count == 5 );
+}
+
+int
+main()
+{
+ test01();
+ test02();
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/char/deleted.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/char/deleted.cc
new file mode 100644
index 00000000000..f2eb538f42e
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/char/deleted.cc
@@ -0,0 +1,43 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 29.7.2 Header <ostream> synopsys; deleted character inserters.
+
+// Test character inserters defined as deleted by P1423.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <ostream>
+
+void test_character_inserters(std::ostream &os)
+{
+ os << 'x'; // ok.
+ os << L'x'; // { dg-error "use of deleted function" }
+ os << u8'x'; // { dg-error "use of deleted function" }
+ os << u'x'; // { dg-error "use of deleted function" }
+ os << U'x'; // { dg-error "use of deleted function" }
+}
+
+void test_string_inserters(std::ostream &os)
+{
+ os << "text"; // ok.
+ os << L"text"; // { dg-error "use of deleted function" }
+ os << u8"text"; // { dg-error "use of deleted function" }
+ os << u"text"; // { dg-error "use of deleted function" }
+ os << U"text"; // { dg-error "use of deleted function" }
+}
diff --git a/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/wchar_t/deleted.cc b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/wchar_t/deleted.cc
new file mode 100644
index 00000000000..1422a01aab3
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/basic_ostream/inserters_character/wchar_t/deleted.cc
@@ -0,0 +1,43 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// 29.7.2 Header <ostream> synopsys; deleted character inserters.
+
+// Test wide character inserters defined as deleted by P1423.
+
+// { dg-options "-std=gnu++2a" }
+// { dg-do compile { target c++2a } }
+
+#include <ostream>
+
+void test_character_inserters(std::wostream &os)
+{
+ os << 'x'; // ok.
+ os << L'x'; // ok.
+ os << u8'x'; // { dg-error "use of deleted function" }
+ os << u'x'; // { dg-error "use of deleted function" }
+ os << U'x'; // { dg-error "use of deleted function" }
+}
+
+void test_string_inserters(std::wostream &os)
+{
+ os << "text"; // ok.
+ os << L"text"; // ok.
+ os << u8"text"; // { dg-error "use of deleted function" }
+ os << u"text"; // { dg-error "use of deleted function" }
+ os << U"text"; // { dg-error "use of deleted function" }
+}
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path-char8_t.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path-char8_t.cc
new file mode 100644
index 00000000000..867ee5b3856
--- /dev/null
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path-char8_t.cc
@@ -0,0 +1,60 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17 -fchar8_t" }
+// { dg-do run { target c++17 } }
+
+#include <filesystem>
+#include <string_view>
+#include <testsuite_hooks.h>
+
+namespace fs = std::filesystem;
+
+void
+test01()
+{
+ fs::path p = fs::u8path(u8"");
+ VERIFY( p.empty() );
+
+ p = fs::u8path(u8"filename1");
+ VERIFY( p.u8string() == u8"filename1" );
+
+ p = fs::u8path(u8"\xf0\x9d\x84\x9e");
+ VERIFY( p.u8string() == u8"\U0001D11E" );
+
+ std::u8string s1 = u8"filename2";
+ p = fs::u8path(s1);
+ VERIFY( p.u8string() == u8"filename2" );
+
+ std::u8string s2 = u8"filename3";
+ p = fs::u8path(s2.begin(), s2.end());
+ VERIFY( p.u8string() == u8"filename3" );
+
+ std::u8string_view sv1{ s1 };
+ p = fs::u8path(sv1);
+ VERIFY( p.u8string() == u8"filename2" );
+
+ std::u8string_view sv2{ s2 };
+ p = fs::u8path(sv2.begin(), sv2.end());
+ VERIFY( p.u8string() == u8"filename3" );
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path.cc b/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path.cc
index aff722b5867..fb337ce1284 100644
--- a/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path.cc
+++ b/libstdc++-v3/testsuite/27_io/filesystem/path/factory/u8path.cc
@@ -19,6 +19,7 @@
// { dg-do run { target c++17 } }
#include <filesystem>
+#include <string_view>
#include <testsuite_hooks.h>
namespace fs = std::filesystem;
@@ -34,6 +35,22 @@ test01()
p = fs::u8path("\xf0\x9d\x84\x9e");
VERIFY( p.u8string() == u8"\U0001D11E" );
+
+ std::string s1 = "filename2";
+ p = fs::u8path(s1);
+ VERIFY( p.u8string() == u8"filename2" );
+
+ std::string s2 = "filename3";
+ p = fs::u8path(s2.begin(), s2.end());
+ VERIFY( p.u8string() == u8"filename3" );
+
+ std::string_view sv1{ s1 };
+ p = fs::u8path(sv1);
+ VERIFY( p.u8string() == u8"filename2" );
+
+ std::string_view sv2{ s2 };
+ p = fs::u8path(sv2.begin(), sv2.end());
+ VERIFY( p.u8string() == u8"filename3" );
}
void
diff --git a/libstdc++-v3/testsuite/experimental/feat-char8_t.cc b/libstdc++-v3/testsuite/experimental/feat-char8_t.cc
index e843604266c..c9b277a4626 100644
--- a/libstdc++-v3/testsuite/experimental/feat-char8_t.cc
+++ b/libstdc++-v3/testsuite/experimental/feat-char8_t.cc
@@ -12,6 +12,6 @@
#ifndef __cpp_lib_char8_t
# error "__cpp_lib_char8_t"
-#elif __cpp_lib_char8_t != 201811L
-# error "__cpp_lib_char8_t != 201811L"
+#elif __cpp_lib_char8_t != 201907L
+# error "__cpp_lib_char8_t != 201907L"
#endif
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path-char8_t.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path-char8_t.cc
new file mode 100644
index 00000000000..dc509c3f912
--- /dev/null
+++ b/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path-char8_t.cc
@@ -0,0 +1,52 @@
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-lstdc++fs -fchar8_t" }
+// { dg-do run { target c++11 } }
+// { dg-require-filesystem-ts "" }
+
+#include <experimental/filesystem>
+#include <testsuite_hooks.h>
+
+namespace fs = std::experimental::filesystem;
+
+void
+test01()
+{
+ fs::path p = fs::u8path(u8"");
+ VERIFY( p.empty() );
+
+ p = fs::u8path(u8"filename1");
+ VERIFY( p.u8string() == u8"filename1" );
+
+ p = fs::u8path(u8"\xf0\x9d\x84\x9e");
+ VERIFY( p.u8string() == u8"\U0001D11E" );
+
+ std::u8string s1 = u8"filename2";
+ p = fs::u8path(s1);
+ VERIFY( p.u8string() == u8"filename2" );
+
+ std::u8string s2 = u8"filename3";
+ p = fs::u8path(s2.begin(), s2.end());
+ VERIFY( p.u8string() == u8"filename3" );
+}
+
+int
+main()
+{
+ test01();
+}
diff --git a/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path.cc b/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path.cc
index bdeb3946a15..83219b7ddda 100644
--- a/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path.cc
+++ b/libstdc++-v3/testsuite/experimental/filesystem/path/factory/u8path.cc
@@ -35,6 +35,14 @@ test01()
p = fs::u8path("\xf0\x9d\x84\x9e");
VERIFY( p.u8string() == u8"\U0001D11E" );
+
+ std::string s1 = "filename2";
+ p = fs::u8path(s1);
+ VERIFY( p.u8string() == u8"filename2" );
+
+ std::string s2 = "filename3";
+ p = fs::u8path(s2.begin(), s2.end());
+ VERIFY( p.u8string() == u8"filename3" );
}
void
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc
index 215899f3d2e..af629496b47 100644
--- a/libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/59161.cc
@@ -45,8 +45,6 @@ int main()
std::list<C> l;
l.push_back(c);
std::list<C>::iterator liter = l.begin();
- // Need to ensure the list<C>::iterator::_Node typedef is in the debuginfo:
- int tmp __attribute__((unused)) = (*liter).ref;
// { dg-final { regexp-test liter {ref = @0x.*} } }
__gnu_cxx::slist<C> sl;
diff --git a/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc b/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc
new file mode 100644
index 00000000000..393c5680e2e
--- /dev/null
+++ b/libstdc++-v3/testsuite/libstdc++-prettyprinters/91997.cc
@@ -0,0 +1,53 @@
+// { dg-options "-std=gnu++17 -g -O0 -Wno-unused" }
+// { dg-do run { target c++17 } }
+
+// Copyright (C) 2019 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include <forward_list>
+#include <list>
+#include <set>
+#include <map>
+#include <string>
+#include <any>
+#include <iostream>
+
+int main()
+{
+ std::list<std::string> list{"a"};
+ std::list<std::string>::iterator lit = list.begin();
+ // { dg-final { note-test lit {"a"} } }
+
+ std::forward_list<std::string> flist{"b"};
+ std::forward_list<std::string>::iterator flit = flist.begin();
+ // { dg-final { note-test flit {"b"} } }
+
+ std::map<int, int> m{ {1, 2} };
+ auto mit = m.begin();
+ // { dg-final { note-test mit {{first = 1, second = 2}} } }
+
+ std::any a = m;
+ // { dg-final { note-test a {std::any containing std::map with 1 element = {[1] = 2}} } }
+
+ std::set<int> s{1, 2};
+ auto sit = s.begin();
+ // { dg-final { note-test sit {1} } }
+
+ std::cout << "\n";
+ return 0; // Mark SPOT
+}
+// { dg-final { gdb-test SPOT } }