aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Liska <mliska@suse.cz>2021-11-22 13:58:10 +0100
committerMartin Liska <mliska@suse.cz>2021-11-22 13:58:10 +0100
commitffa33d36af92357098870be1e7dbedad0f883a37 (patch)
treeb0b103262ec24c8cc3e086c50731fb9949c3c3c1 /gcc
parent42369195bef1204e5249f211d33cc64619530167 (diff)
parentf456eaf2e0fb3ceb51c641fd348429bf59d215a9 (diff)
downloadgcc-ffa33d36af92357098870be1e7dbedad0f883a37.zip
gcc-ffa33d36af92357098870be1e7dbedad0f883a37.tar.gz
gcc-ffa33d36af92357098870be1e7dbedad0f883a37.tar.bz2
Merge branch 'master' into devel/sphinx
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog736
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/analyzer/ChangeLog57
-rw-r--r--gcc/analyzer/constraint-manager.cc4
-rw-r--r--gcc/analyzer/engine.cc10
-rw-r--r--gcc/analyzer/program-state.cc9
-rw-r--r--gcc/analyzer/program-state.h3
-rw-r--r--gcc/analyzer/region-model-impl-calls.cc69
-rw-r--r--gcc/analyzer/region-model-manager.cc7
-rw-r--r--gcc/analyzer/region-model.cc85
-rw-r--r--gcc/analyzer/region-model.h21
-rw-r--r--gcc/analyzer/svalue.cc8
-rw-r--r--gcc/c-family/ChangeLog41
-rw-r--r--gcc/c-family/c-common.c66
-rw-r--r--gcc/c-family/c-common.h2
-rw-r--r--gcc/c-family/c.opt24
-rw-r--r--gcc/c/ChangeLog29
-rw-r--r--gcc/c/c-decl.c11
-rw-r--r--gcc/c/c-parser.c20
-rw-r--r--gcc/c/c-typeck.c5
-rw-r--r--gcc/cgraph.c10
-rw-r--r--gcc/cgraph.h3
-rw-r--r--gcc/cgraphclones.c1
-rw-r--r--gcc/cgraphunit.c7
-rw-r--r--gcc/common.opt2
-rw-r--r--gcc/config/aarch64/aarch64-modes.def5
-rw-r--r--gcc/config/aarch64/aarch64-sve.md19
-rw-r--r--gcc/config/aarch64/aarch64.c4
-rw-r--r--gcc/config/aarch64/iterators.md2
-rw-r--r--gcc/config/bfin/bfin.md9
-rw-r--r--gcc/config/darwin-driver.c18
-rw-r--r--gcc/config/darwin.c24
-rw-r--r--gcc/config/darwin.h98
-rw-r--r--gcc/config/darwin.opt4
-rw-r--r--gcc/config/i386/avx512fp16intrin.h39
-rw-r--r--gcc/config/i386/avx512fp16vlintrin.h17
-rw-r--r--gcc/config/i386/constraints.md5
-rw-r--r--gcc/config/i386/darwin.h31
-rw-r--r--gcc/config/i386/darwin32-biarch.h13
-rw-r--r--gcc/config/i386/darwin64-biarch.h13
-rw-r--r--gcc/config/i386/i386-expand.c7
-rw-r--r--gcc/config/i386/i386-options.c5
-rw-r--r--gcc/config/i386/i386-opts.h7
-rw-r--r--gcc/config/i386/i386-protos.h1
-rw-r--r--gcc/config/i386/i386.c95
-rw-r--r--gcc/config/i386/i386.h5
-rw-r--r--gcc/config/i386/i386.md30
-rw-r--r--gcc/config/i386/i386.opt24
-rw-r--r--gcc/config/i386/x86-tune-costs.h4
-rw-r--r--gcc/config/rs6000/driver-rs6000.c3
-rw-r--r--gcc/config/rs6000/emmintrin.h24
-rw-r--r--gcc/config/rs6000/mma.md10
-rw-r--r--gcc/config/rs6000/predicates.md4
-rw-r--r--gcc/config/s390/s390.md2
-rw-r--r--gcc/config/visium/visium.md50
-rw-r--r--gcc/config/xtensa/xtensa.md4
-rw-r--r--gcc/cp/ChangeLog128
-rw-r--r--gcc/cp/constexpr.c9
-rw-r--r--gcc/cp/cp-gimplify.c65
-rw-r--r--gcc/cp/cp-objcp-common.c1
-rw-r--r--gcc/cp/cp-tree.h12
-rw-r--r--gcc/cp/decl.c3
-rw-r--r--gcc/cp/init.c194
-rw-r--r--gcc/cp/lambda.c19
-rw-r--r--gcc/cp/parser.c14
-rw-r--r--gcc/cp/pt.c62
-rw-r--r--gcc/cp/ptree.c3
-rw-r--r--gcc/cp/semantics.c37
-rw-r--r--gcc/cp/tree.c7
-rw-r--r--gcc/cp/typeck.c2
-rw-r--r--gcc/cp/typeck2.c26
-rw-r--r--gcc/d/ChangeLog5
-rw-r--r--gcc/d/decl.cc5
-rw-r--r--gcc/doc/extend.texi18
-rw-r--r--gcc/doc/invoke.texi64
-rw-r--r--gcc/doc/md.texi4
-rw-r--r--gcc/fortran/ChangeLog84
-rw-r--r--gcc/fortran/check.c6
-rw-r--r--gcc/fortran/gfortran.h41
-rw-r--r--gcc/fortran/interface.c77
-rw-r--r--gcc/fortran/intrinsic.c53
-rw-r--r--gcc/fortran/resolve.c3
-rw-r--r--gcc/fortran/trans-array.c35
-rw-r--r--gcc/fortran/trans-array.h2
-rw-r--r--gcc/fortran/trans-expr.c9
-rw-r--r--gcc/fortran/trans-intrinsic.c68
-rw-r--r--gcc/fortran/trans-stmt.c22
-rw-r--r--gcc/fortran/trans-types.c4
-rw-r--r--gcc/fortran/trans.h4
-rw-r--r--gcc/gcc.c3
-rw-r--r--gcc/ggc-common.c39
-rw-r--r--gcc/gimple-array-bounds.cc25
-rw-r--r--gcc/gimple-fold.c24
-rw-r--r--gcc/gimple-harden-conditionals.cc9
-rw-r--r--gcc/gimple-range-fold.cc16
-rw-r--r--gcc/gimple-range-gori.cc20
-rw-r--r--gcc/gimple-ssa-warn-access.cc33
-rw-r--r--gcc/gimplify.c79
-rw-r--r--gcc/internal-fn.c4
-rw-r--r--gcc/internal-fn.def2
-rw-r--r--gcc/ipa-modref-tree.c46
-rw-r--r--gcc/ipa-modref-tree.h9
-rw-r--r--gcc/ipa-modref.c1209
-rw-r--r--gcc/ipa-modref.h1
-rw-r--r--gcc/ipa-pure-const.c4
-rw-r--r--gcc/jit/ChangeLog51
-rw-r--r--gcc/jit/docs/topics/compatibility.rst43
-rw-r--r--gcc/jit/docs/topics/functions.rst26
-rw-r--r--gcc/jit/docs/topics/types.rst122
-rw-r--r--gcc/jit/jit-recording.h7
-rw-r--r--gcc/jit/libgccjit.c264
-rw-r--r--gcc/jit/libgccjit.h89
-rw-r--r--gcc/jit/libgccjit.map21
-rw-r--r--gcc/langhooks.h2
-rw-r--r--gcc/lto-cgraph.c4
-rw-r--r--gcc/lto/ChangeLog4
-rw-r--r--gcc/lto/lto-partition.c1
-rw-r--r--gcc/match.pd31
-rw-r--r--gcc/optabs.def2
-rw-r--r--gcc/opts.c1
-rw-r--r--gcc/pointer-query.cc30
-rw-r--r--gcc/pointer-query.h3
-rw-r--r--gcc/print-tree.c3
-rw-r--r--gcc/symtab.c2
-rw-r--r--gcc/testsuite/ChangeLog492
-rw-r--r--gcc/testsuite/c-c++-common/Waddress-5.c133
-rw-r--r--gcc/testsuite/c-c++-common/Waddress-6.c32
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-1.c12
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-10.c27
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-11.c13
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-12.c19
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-13.c17
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-14.c38
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-15.c59
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-16.c26
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-17.c30
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-2.c9
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-3.c11
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-4.c188
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-5.c188
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-6.c155
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-7.c9
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-8.c13
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-9.c29
-rw-r--r--gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c54
-rw-r--r--gcc/testsuite/c-c++-common/builtin-assoc-barrier-1.c71
-rw-r--r--gcc/testsuite/c-c++-common/cpp/dir-only-9.c13
-rw-r--r--gcc/testsuite/g++.dg/analyzer/pr102662.C39
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto25.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested9.C41
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/eval-order11.C89
-rw-r--r--gcc/testsuite/g++.dg/cpp23/auto-fncast1.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp23/auto-fncast2.C62
-rw-r--r--gcc/testsuite/g++.dg/cpp23/auto-fncast3.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp23/auto-fncast4.C26
-rw-r--r--gcc/testsuite/g++.dg/cpp23/auto-fncast5.C39
-rw-r--r--gcc/testsuite/g++.dg/cpp23/auto-fncast6.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/concepts-this1.C30
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/fn-template23.C36
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/fn-template24.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/fn-template25.C12
-rw-r--r--gcc/testsuite/g++.dg/gomp/masked-1.C14
-rw-r--r--gcc/testsuite/g++.dg/pr102988.C17
-rw-r--r--gcc/testsuite/g++.dg/pr103326.C15
-rw-r--r--gcc/testsuite/g++.dg/torture/pr103266.C23
-rw-r--r--gcc/testsuite/g++.dg/torture/pr103351.C88
-rw-r--r--gcc/testsuite/g++.dg/warn/Waddress-7.C76
-rw-r--r--gcc/testsuite/g++.dg/warn/Walways-true-2.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-14.C31
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-15.C118
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-16.C12
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-17.C33
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-18.C22
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-19.C50
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-20.C16
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-21.C20
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-22.C37
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-23.C24
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-24.C89
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-25.C12
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-26.C22
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-27.C20
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-28.C59
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-29.C59
-rw-r--r--gcc/testsuite/g++.dg/warn/Wuninitialized-30.C13
-rw-r--r--gcc/testsuite/g++.target/i386/pr101180.C25
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr103288-1.c6
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr103314-1.c6
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr103317-1.c13
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr103052.c35
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr103255.c41
-rw-r--r--gcc/testsuite/gcc.dg/Walways-true-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/Warray-parameter-10.c20
-rw-r--r--gcc/testsuite/gcc.dg/Warray-parameter-11.c24
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-82.c29
-rw-r--r--gcc/testsuite/gcc.dg/Wstringop-overflow-84.c15
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/capacity-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/capacity-3.c4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/explode-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr102695.c44
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr103217.c42
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/pr94858-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/analyzer/strchr-1.c26
-rw-r--r--gcc/testsuite/gcc.dg/devnull-dump.c7
-rw-r--r--gcc/testsuite/gcc.dg/lto/semantic-interposition-1_0.c13
-rw-r--r--gcc/testsuite/gcc.dg/lto/semantic-interposition-1_1.c5
-rw-r--r--gcc/testsuite/gcc.dg/pr103248.c8
-rw-r--r--gcc/testsuite/gcc.dg/pr103254.c25
-rw-r--r--gcc/testsuite/gcc.dg/pr103277.c14
-rw-r--r--gcc/testsuite/gcc.dg/pr25530.c2
-rw-r--r--gcc/testsuite/gcc.dg/signbit-2.c3
-rw-r--r--gcc/testsuite/gcc.dg/torture/20211118-1.c27
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/merge_block.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c3
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/modref-15.c9
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/modref-dse-4.c26
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/modref-dse-6.c23
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr103218-1.c28
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr103220-1.c15
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr103220-2.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr103228-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr103257-1.c11
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr55177-1.c14
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-18.c19
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp116.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-double.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-float.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-double.c7
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-float.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-double.c5
-rw-r--r--gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-float.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr103253.c16
-rw-r--r--gcc/testsuite/gcc.dg/vla-stexp-3.c11
-rw-r--r--gcc/testsuite/gcc.dg/vla-stexp-4.c94
-rw-r--r--gcc/testsuite/gcc.dg/vla-stexp-5.c30
-rw-r--r--gcc/testsuite/gcc.dg/vla-stexp-6.c94
-rw-r--r--gcc/testsuite/gcc.dg/vla-stexp-7.c44
-rw-r--r--gcc/testsuite/gcc.dg/vla-stexp-8.c47
-rw-r--r--gcc/testsuite/gcc.dg/vla-stexp-9.c53
-rw-r--r--gcc/testsuite/gcc.dg/weak/weak-3.c6
-rw-r--r--gcc/testsuite/gcc.target/aarch64/pr103311.c16
-rw-r--r--gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c2
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_5.c28
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_5_run.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_6.c22
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_6_run.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_7.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_7_run.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_8.c26
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_8_run.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_5.c29
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_5_run.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_6.c23
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_6_run.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_7.c28
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_7_run.c4
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_8.c27
-rw-r--r--gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_8_run.c4
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c20
-rw-r--r--gcc/testsuite/gcc.target/i386/harden-sls-1.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/harden-sls-2.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/harden-sls-3.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/harden-sls-4.c16
-rw-r--r--gcc/testsuite/gcc.target/i386/harden-sls-5.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c14
-rw-r--r--gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c15
-rw-r--r--gcc/testsuite/gcc.target/i386/pr101180.c12
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102543.c35
-rw-r--r--gcc/testsuite/gcc.target/i386/pr103069-2.c11
-rw-r--r--gcc/testsuite/gcc.target/i386/pr103275.c83
-rw-r--r--gcc/testsuite/gcc.target/mips/frame-header-1.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/frame-header-2.c2
-rw-r--r--gcc/testsuite/gcc.target/mips/octeon-bbit-1.c4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/pr102976.c14
-rw-r--r--gcc/testsuite/gcc.target/s390/20211119.c12
-rw-r--r--gcc/testsuite/gcc.target/s390/mul-wide.c9
-rw-r--r--gcc/testsuite/gcc.target/s390/umul-wide.c9
-rw-r--r--gcc/testsuite/gfortran.dg/dec_math_5.f90104
-rw-r--r--gcc/testsuite/gfortran.dg/pr101329.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/pr103286.f9011
-rw-r--r--gcc/testsuite/jit.dg/all-non-failing-tests.h10
-rw-r--r--gcc/testsuite/jit.dg/test-reflection.c95
-rw-r--r--gcc/testsuite/lib/target-supports.exp6
-rw-r--r--gcc/tree-eh.c12
-rw-r--r--gcc/tree-ssa-alias.c2
-rw-r--r--gcc/tree-ssa-dce.c4
-rw-r--r--gcc/tree-ssa-dse.c68
-rw-r--r--gcc/tree-ssa-dse.h2
-rw-r--r--gcc/tree-ssa-loop-im.c180
-rw-r--r--gcc/tree-ssa-math-opts.c15
-rw-r--r--gcc/tree-ssa-phiopt.c6
-rw-r--r--gcc/tree-ssa-strlen.c152
-rw-r--r--gcc/tree-vect-slp-patterns.c26
-rw-r--r--gcc/tree.c1
-rw-r--r--gcc/varasm.c6
-rw-r--r--gcc/varasm.h2
-rw-r--r--gcc/varpool.c8
308 files changed, 9230 insertions, 1322 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 52de288..1e94c54 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,739 @@
+2021-11-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/101180
+ * config/i386/i386-options.c (ix86_valid_target_attribute_p): If
+ fndecl already has DECL_FUNCTION_SPECIFIC_TARGET, use that as base
+ instead of target_option_default_node.
+
+2021-11-21 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/103227
+ * ipa-modref.c (parm_map_for_arg): Rename to ...
+ (parm_map_for_ptr): .. this one; handle static chain and calls to
+ malloc functions.
+ (modref_access_analysis::get_access): Use parm_map_for_ptr.
+ (modref_access_analysis::process_fnspec): Update.
+ (modref_access_analysis::analyze_load): Update.
+ (modref_access_analysis::analyze_store): Update.
+
+2021-11-21 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-modref.c (ignore_nondeterminism_p): Move earlier in source
+ code.
+ (ignore_retval_p): Likewise.
+ (ignore_stores_p): Likewise.
+ (parm_map_for_arg): Likewise.
+ (class modref_access_analysis): New class.
+ (modref_access_analysis::set_side_effects): New member function.
+ (modref_access_analysis::set_nondeterministic): New member function.
+ (get_access): Turn to ...
+ (modref_access_analysis::get_access): ... this one.
+ (record_access): Turn to ...
+ (modref_access_analysis::record_access): ... this one.
+ (record_access_lto): Turn to ...
+ (modref_access_analysis::record_access_lto): ... This one.
+ (record_access_p): Turn to ...
+ (modref_access_analysis::record_access_p): ... This one
+ (modref_access_analysis::record_unknown_load): New member function.
+ (modref_access_analysis::record_unknown_store): New member function.
+ (get_access_for_fnspec): Turn to ...
+ (modref_access_analysis::get_access_for_fnspec): ... this one.
+ (merge_call_side_effects): Turn to ...
+ (moderf_access_analysis::merge_call_side_effects): Turn to ...
+ (collapse_loads): Move later in source code.
+ (collapse_stores): Move later in source code.
+ (process_fnspec): Turn to ...
+ (modref_access_analysis::process_fnspec): ... this one.
+ (analyze_call): Turn to ...
+ (modref_access_analysis::analyze_call): ... this one.
+ (struct summary_ptrs): Remove.
+ (analyze_load): Turn to ...
+ (modref_access_analysis::analyze_load): ... this one.
+ (analyze_store): Turn to ...
+ (modref_access_analysis::analyze_store): ... this one.
+ (analyze_stmt): Turn to ...
+ (modref_access_analysis::analyze_stmt): ... This one.
+ (remove_summary): Remove.
+ (modref_access_analysis::propagate): Break out from ...
+ (modref_access_analysis::analyze): Break out from ...
+ (analyze_function): ... here.
+
+2021-11-21 Roger Sayle <roger@nextmovesoftware.com>
+ Robin Dapp <rdapp@linux.ibm.com>
+
+ PR target/102117
+ * tree-ssa-math-opts.c (convert_mult_to_widen): Recognize
+ signed WIDEN_MULT_EXPR if the target supports umul_widen_optab.
+
+2021-11-20 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/103052
+ * ipa-modref.c (ignore_nondeterminism_p): Allow looping pure/cont.
+ (merge_call_side_effects): Improve debug output.
+
+2021-11-20 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/103052
+ * ipa-pure-const.c (propagate_pure_const): Fix merging of loping flag.
+
+2021-11-20 Jeff Law <jeffreyalaw@gmail.com>
+
+ PR tree-optimization/103226
+ * config/bfin/bfin.md (doloop pattern, splitter and expander): Clobber
+ CC.
+
+2021-11-20 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103220
+ * match.pd ((type) X bitop CST): Don't check if CST
+ fits into the type if only the sign changes.
+
+2021-11-20 Alexandre Oliva <oliva@adacore.com>
+
+ PR tree-optimization/102988
+ * gimple-harden-conditionals.cc (detach_value): Copy SSA_NAME
+ without decl sharing.
+
+2021-11-19 Iain Sandoe <iain@sandoe.co.uk>
+
+ * doc/invoke.texi: Remove whitespace after an @option.
+
+2021-11-19 Paul A. Clarke <pc@us.ibm.com>
+
+ * config/rs6000/emmintrin.h (_mm_sad_epu8): Use vec_absd when
+ _ARCH_PWR9, optimize vec_sum2s when LE.
+
+2021-11-19 Iain Sandoe <iain@sandoe.co.uk>
+
+ PR target/80556
+ * config/darwin-driver.c (darwin_driver_init): Handle exported
+ symbols and symbol lists (suppress automatic export of the TLS
+ symbols).
+ * config/darwin.c (darwin_rename_builtins): Remove workaround.
+ * config/darwin.h (LINK_GCC_C_SEQUENCE_SPEC): Likewise.
+ (REAL_LIBGCC_SPEC): Handle revised library uses.
+ * config/darwin.opt (nodefaultexport): New.
+ * config/i386/darwin.h (PR80556_WORKAROUND): Remove.
+ * config/i386/darwin32-biarch.h (PR80556_WORKAROUND): Likewise.
+ * config/i386/darwin64-biarch.h (PR80556_WORKAROUND): Likewise.
+
+2021-11-19 Martin Jambor <mjambor@suse.cz>
+
+ * opts.c (default_options_table): Switch off
+ flag_semantic_interposition at Ofast.
+ * doc/invoke.texi (Optimize Options): Document that Ofast switches off
+ -fsemantic-interposition.
+
+2021-11-19 Jan Hubicka <hubicka@ucw.cz>
+
+ * tree-ssa-alias.c (ref_maybe_used_by_call_p_1): Do not guard modref
+ by !gimple_call_chain.
+
+2021-11-19 Martin Sebor <msebor@redhat.com>
+
+ PR c++/33925
+ PR c/102867
+ * doc/invoke.texi (-Waddress): Update.
+
+2021-11-19 Andrew MacLeod <amacleod@redhat.com>
+
+ PR tree-optimization/103254
+ * gimple-range-gori.cc (range_def_chain::get_def_chain): Limit the
+ depth for all statements with multple ssa names.
+
+2021-11-19 Stefan Schulze Frielinghaus <stefansf@linux.ibm.com>
+
+ * config/s390/s390.md (define_peephole2): Variable insn points
+ to the first matched insn. Use peep2_next_insn(1) to refer to
+ the second matched insn.
+
+2021-11-19 Tamar Christina <tamar.christina@arm.com>
+
+ PR tree-optimization/103311
+ PR target/103330
+ * tree-vect-slp-patterns.c (vect_validate_multiplication): Fix CONJ
+ test to new codegen.
+ (complex_mul_pattern::matches): Move check downwards.
+
+2021-11-19 Martin Liska <mliska@suse.cz>
+
+ Revert:
+ 2021-11-19 Martin Liska <mliska@suse.cz>
+
+ * cfgexpand.c (pass_expand::execute): Use option directly.
+ * function.c (allocate_struct_function): Likewise.
+ * gimple-low.c (lower_function_body): Likewise.
+ (lower_stmt): Likewise.
+ * gimple-ssa-backprop.c (backprop::prepare_change): Likewise.
+ * ipa-param-manipulation.c (ipa_param_adjustments::modify_call): Likewise.
+ * ipa-split.c (split_function): Likewise.
+ * lto-streamer-in.c (input_function): Likewise.
+ * sese.c (sese_insert_phis_for_liveouts): Likewise.
+ * ssa-iterators.h (num_imm_uses): Likewise.
+ * tree-cfg.c (make_blocks): Likewise.
+ (gimple_merge_blocks): Likewise.
+ * tree-inline.c (tree_function_versioning): Likewise.
+ * tree-loop-distribution.c (generate_loops_for_partition): Likewise.
+ * tree-sra.c (analyze_access_subtree): Likewise.
+ * tree-ssa-dce.c (remove_dead_stmt): Likewise.
+ * tree-ssa-loop-ivopts.c (remove_unused_ivs): Likewise.
+ * tree-ssa-phiopt.c (spaceship_replacement): Likewise.
+ * tree-ssa-reassoc.c (reassoc_remove_stmt): Likewise.
+ * tree-ssa-tail-merge.c (tail_merge_optimize): Likewise.
+ * tree-ssa-threadedge.c (propagate_threaded_block_debug_into): Likewise.
+ * tree-ssa.c (gimple_replace_ssa_lhs): Likewise.
+ (target_for_debug_bind): Likewise.
+ (insert_debug_temp_for_var_def): Likewise.
+ (insert_debug_temps_for_defs): Likewise.
+ (reset_debug_uses): Likewise.
+ * tree-ssanames.c (release_ssa_name_fn): Likewise.
+ * tree-vect-loop-manip.c (adjust_vec_debug_stmts): Likewise.
+ (adjust_debug_stmts): Likewise.
+ (adjust_phi_and_debug_stmts): Likewise.
+ (vect_do_peeling): Likewise.
+ * tree-vect-loop.c (vect_transform_loop_stmt): Likewise.
+ (vect_transform_loop): Likewise.
+ * tree.h (MAY_HAVE_DEBUG_MARKER_STMTS): Remove
+ (MAY_HAVE_DEBUG_BIND_STMTS): Remove.
+ (MAY_HAVE_DEBUG_STMTS): Use options directly.
+
+2021-11-19 Giuliano Belinassi <gbelinassi@suse.de>
+
+ * gcc.c (process_command): Skip dumpdir override if file is a
+ not_actual_file_p.
+ * doc/invoke.texi: Update -dumpdir documentation.
+
+2021-11-19 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103314
+ * match.pd ((type) X op CST): Restrict the equal
+ TYPE_PRECISION case to GIMPLE only.
+
+2021-11-19 Martin Liska <mliska@suse.cz>
+
+ PR ipa/103230
+ * ipa-modref-tree.h (struct modref_parm_map): Add default
+ constructor.
+ * ipa-modref.c (ipa_merge_modref_summary_after_inlining): Use it.
+
+2021-11-19 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/103248
+ * tree-eh.c (operation_could_trap_helper_p): Properly handle
+ fixed-point RDIV_EXPR.
+
+2021-11-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102436
+ * tree-ssa-loop-im.c (execute_sm_if_changed): Add mode
+ to just create the if structure and return the then block.
+ (execute_sm): Add flag to indicate the var will re-use
+ another flag var.
+ (hoist_memory_references): Support a single conditional
+ block with all stores as special case.
+
+2021-11-19 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103317
+ * tree-ssa-phiopt.c (minmax_replacement): For the non empty
+ middle bb case, check to make sure it has a single predecessor.
+
+2021-11-19 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103257
+ * match.pd
+ ((m1 >/</>=/<= m2) * d -> (m1 >/</>=/<= m2) ? d : 0):
+ Disable until !canonicalize_math_p ().
+
+2021-11-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/19808
+ PR c++/96121
+ * doc/invoke.texi: Update documentation for -Wuninitialized.
+ * tree.c (stabilize_reference): Set location.
+
+2021-11-19 liuhongt <hongtao.liu@intel.com>
+
+ PR target/102543
+ * config/i386/x86-tune-costs.h (skylake_cost): Reduce cost of
+ storing 256/512-bit SSE register to be equal to cost of
+ unaligned store to avoid odd alignment peeling.
+ (icelake_cost): Ditto.
+
+2021-11-18 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/predicates.md (current_file_function_operand):
+ Add flag_semantic_interposition to call of decl_replaceable_p.
+
+2021-11-18 Martin Liska <mliska@suse.cz>
+
+ * ipa-modref.c (analyze_function): Do not execute the code
+ only if dump_file != NULL.
+
+2021-11-18 Martin Liska <mliska@suse.cz>
+
+ * ipa-modref.c (analyze_function): Use fnode instead of repeated
+ cgraph_node::get (current_function_decl).
+
+2021-11-18 Jan Hubicka <hubicka@ucw.cz>
+
+ * cgraph.c (cgraph_node::get_availability): Update call of
+ decl_replaceable_p.
+ (cgraph_node::verify_node): Verify that semantic_interposition flag
+ is set correclty.
+ * cgraph.h: (symtab_node): Add semantic_interposition flag.
+ * cgraphclones.c (set_new_clone_decl_and_node_flags): Clear
+ semantic_interposition flag.
+ * cgraphunit.c (cgraph_node::finalize_function): Set
+ semantic_interposition flag.
+ (cgraph_node::add_new_function): Likewise.
+ (varpool_node::finalize_decl): Likewise.
+ (cgraph_node::create_wrapper): Likewise.
+ * common.opt (fsemantic-interposition): Turn to optimization node.
+ * lto-cgraph.c (lto_output_node): Stream semantic_interposition.
+ (lto_output_varpool_node): Likewise.
+ (input_overwrite_node): Likewise.
+ (input_varpool_node): Likewise.
+ * symtab.c (symtab_node::dump_base): Dump new flag.
+ * varasm.c (decl_replaceable_p): Add semantic_interposition_p
+ parameter.
+ * varasm.h (decl_replaceable_p): Update declaration.
+ * varpool.c (varpool_node::ctor_useable_for_folding_p):
+ Use semantic_interposition flag.
+ (varpool_node::get_availability): Likewise.
+ (varpool_node::create_alias): Copy semantic_interposition flag.
+
+2021-11-18 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/103266
+ * ipa-modref.c (modref_eaf_analysis::merge_call_lhs_flags): Unused
+ parameter may still be returned.
+ (modref_eaf_analysis::analyze_ssa_name): Call merge_call_lhs_flags
+ even for unused function args.
+
+2021-11-18 Tamar Christina <tamar.christina@arm.com>
+
+ PR tree-optimization/103311
+ * tree-vect-slp-patterns.c (complex_mul_pattern::matches,
+ complex_fms_pattern::matches): Check for multiplications.
+
+2021-11-18 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/102952
+ * config/i386/i386.c (ix86_output_jmp_thunk_or_indirect): Emit
+ CS prefix for -mindirect-branch-cs-prefix.
+ (ix86_output_indirect_branch_via_reg): Likewise.
+ * config/i386/i386.opt: Add -mindirect-branch-cs-prefix.
+ * doc/invoke.texi: Document -mindirect-branch-cs-prefix.
+
+2021-11-18 David Edelsohn <dje.gcc@gmail.com>
+
+ * config/rs6000/driver-rs6000.c (detect_processor_aix): Add
+ power10.
+
+2021-11-18 Tamar Christina <tamar.christina@arm.com>
+
+ PR tree-optimization/103253
+ * tree-ssa-math-opts.c (convert_mult_to_fma): Check for LHS.
+
+2021-11-18 Matthias Kretz <m.kretz@gsi.de>
+
+ * doc/extend.texi: Document __builtin_assoc_barrier.
+
+2021-11-18 Martin Liska <mliska@suse.cz>
+
+ * cfgexpand.c (pass_expand::execute): Use option directly.
+ * function.c (allocate_struct_function): Likewise.
+ * gimple-low.c (lower_function_body): Likewise.
+ (lower_stmt): Likewise.
+ * gimple-ssa-backprop.c (backprop::prepare_change): Likewise.
+ * ipa-param-manipulation.c (ipa_param_adjustments::modify_call): Likewise.
+ * ipa-split.c (split_function): Likewise.
+ * lto-streamer-in.c (input_function): Likewise.
+ * sese.c (sese_insert_phis_for_liveouts): Likewise.
+ * ssa-iterators.h (num_imm_uses): Likewise.
+ * tree-cfg.c (make_blocks): Likewise.
+ (gimple_merge_blocks): Likewise.
+ * tree-inline.c (tree_function_versioning): Likewise.
+ * tree-loop-distribution.c (generate_loops_for_partition): Likewise.
+ * tree-sra.c (analyze_access_subtree): Likewise.
+ * tree-ssa-dce.c (remove_dead_stmt): Likewise.
+ * tree-ssa-loop-ivopts.c (remove_unused_ivs): Likewise.
+ * tree-ssa-phiopt.c (spaceship_replacement): Likewise.
+ * tree-ssa-reassoc.c (reassoc_remove_stmt): Likewise.
+ * tree-ssa-tail-merge.c (tail_merge_optimize): Likewise.
+ * tree-ssa-threadedge.c (propagate_threaded_block_debug_into): Likewise.
+ * tree-ssa.c (gimple_replace_ssa_lhs): Likewise.
+ (target_for_debug_bind): Likewise.
+ (insert_debug_temp_for_var_def): Likewise.
+ (insert_debug_temps_for_defs): Likewise.
+ (reset_debug_uses): Likewise.
+ * tree-ssanames.c (release_ssa_name_fn): Likewise.
+ * tree-vect-loop-manip.c (adjust_vec_debug_stmts): Likewise.
+ (adjust_debug_stmts): Likewise.
+ (adjust_phi_and_debug_stmts): Likewise.
+ (vect_do_peeling): Likewise.
+ * tree-vect-loop.c (vect_transform_loop_stmt): Likewise.
+ (vect_transform_loop): Likewise.
+ * tree.h (MAY_HAVE_DEBUG_MARKER_STMTS): Remove
+ (MAY_HAVE_DEBUG_BIND_STMTS): Remove.
+ (MAY_HAVE_DEBUG_STMTS): Use options directly.
+
+2021-11-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/103277
+ * tree-ssa-dse.c (need_ab_cleanup): New.
+ (dse_optimize_redundant_stores): Adjust.
+ (delete_dead_or_redundant_assignment): Get extra
+ need_ab_cleanup argument and set when abnormal cleanup is
+ needed.
+ (dse_optimize_call): Adjust.
+ (dse_optimize_stmt): Likewise.
+ (pass_dse::execute): Allocate and deallocate need_ab_cleanup.
+ Perform abnormal cleanup.
+ * tree-ssa-dse.h (delete_dead_or_redundant_assignment): Adjust.
+
+2021-11-18 Hongyu Wang <hongyu.wang@intel.com>
+
+ * config/i386/i386-expand.c (ix86_expand_atomic_fetch_op_loop):
+ Adjust generated cfg to avoid infinite loop.
+
+2021-11-18 konglin1 <lingling.kong@intel.com>
+
+ * config/i386/avx512fp16intrin.h (_mm512_mul_pch): Add alias for _mm512_fmul_pch.
+ (_mm512_mask_mul_pch): Likewise.
+ (_mm512_maskz_mul_pch): Likewise.
+ (_mm512_mul_round_pch): Likewise.
+ (_mm512_mask_mul_round_pch): Likewise.
+ (_mm512_maskz_mul_round_pch): Likewise.
+ (_mm512_cmul_pch): Likewise.
+ (_mm512_mask_cmul_pch): Likewise.
+ (_mm512_maskz_cmul_pch): Likewise.
+ (_mm512_cmul_round_pch): Likewise.
+ (_mm512_mask_cmul_round_pch): Likewise.
+ (_mm512_maskz_cmul_round_pch): Likewise.
+ (_mm_mul_sch): Likewise.
+ (_mm_mask_mul_sch): Likewise.
+ (_mm_maskz_mul_sch): Likewise.
+ (_mm_mul_round_sch): Likewise.
+ (_mm_mask_mul_round_sch): Likewise.
+ (_mm_maskz_mul_round_sch): Likewise.
+ (_mm_cmul_sch): Likewise.
+ (_mm_mask_cmul_sch): Likewise.
+ (_mm_maskz_cmul_sch): Likewise.
+ (_mm_cmul_round_sch): Likewise.
+ (_mm_mask_cmul_round_sch): Likewise.
+ (_mm_maskz_cmul_round_sch): Likewise.
+ * config/i386/avx512fp16vlintrin.h (_mm_mul_pch): Likewise.
+ (_mm_mask_mul_pch): Likewise.
+ (_mm_maskz_mul_pch): Likewise.
+ (_mm256_mul_pch): Likewise.
+ (_mm256_mask_mul_pch): Likewise.
+ (_mm256_maskz_mul_pch): Likewise.
+ (_mm_cmul_pch): Likewise.
+ (_mm_mask_cmul_pch): Likewise.
+ (_mm_maskz_cmul_pch): Likewise.
+ (_mm256_cmul_pch): Likewise.
+ (_mm256_mask_cmul_pch): Likewise.
+ (_mm256_maskz_cmul_pch): Likewise.
+
+2021-11-17 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103228
+ PR tree-optimization/55177
+ * match.pd ((type) X bitop CST): Also do this
+ transformation for nop conversions.
+
+2021-11-17 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/102759
+ * gimple-array-bounds.cc (build_printable_array_type): Move...
+ * gimple-ssa-warn-access.cc (build_printable_array_type): Avoid
+ pathological function redeclarations that remove a previously
+ declared prototype.
+ Improve formatting of function arguments in informational notes.
+ * pointer-query.cc (build_printable_array_type): ...to here.
+ * pointer-query.h (build_printable_array_type): Declared.
+
+2021-11-17 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/102952
+ * config/i386/i386-opts.h (harden_sls): New enum.
+ * config/i386/i386.c (output_indirect_thunk): Mitigate against
+ SLS for function return.
+ (ix86_output_function_return): Likewise.
+ (ix86_output_jmp_thunk_or_indirect): Mitigate against indirect
+ branch.
+ (ix86_output_indirect_jmp): Likewise.
+ (ix86_output_call_insn): Likewise.
+ * config/i386/i386.opt: Add -mharden-sls=.
+ * doc/invoke.texi: Document -mharden-sls=.
+
+2021-11-17 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/103307
+ * config/i386/i386.c (ix86_code_end): Remove "%!" before ret.
+ (ix86_output_function_return): Likewise.
+ * config/i386/i386.md (simple_return_pop_internal): Likewise.
+
+2021-11-17 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/103246
+ * ipa-modref.c (read_modref_records): Fix streaminig in of every_access
+ flag.
+
+2021-11-17 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (indirect_thunks_used): Redefine as HARD_REG_SET.
+ (ix86_code_end): Use TEST_HARD_REG_BIT on indirect_thunks_used.
+ (ix86_output_indirect_branch_via_reg): Use SET_HARD_REG_BIT
+ on indirect_thunks_used.
+ (ix86_output_indirect_function_return): Ditto.
+
+2021-11-17 Jan Hubicka <hubicka@ucw.cz>
+
+ * ipa-modref-tree.c: Include cgraph.h and tree-streamer.h.
+ (modref_access_node::stream_out): New member function.
+ (modref_access_node::stream_in): New member function.
+ * ipa-modref-tree.h (modref_access_node::stream_out,
+ modref_access_node::stream_in): Declare.
+ * ipa-modref.c (modref_summary_lto::useful_p): Free useless kills.
+ (modref_summary_lto::dump): Dump kills.
+ (analyze_store): Record kills for LTO
+ (analyze_stmt): Likewise.
+ (modref_summaries_lto::duplicate): Duplicate kills.
+ (write_modref_records): Use new stream_out member function.
+ (read_modref_records): Likewise.
+ (modref_write): Stream out kills.
+ (read_section): Stream in kills
+ (remap_kills): New function.
+ (update_signature): Use it.
+
+2021-11-17 Uroš Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.h (LEGACY_SSE_REGNO_P): New predicate.
+ (SSE_REGNO_P): Use LEGACY_SSE_REGNO_P predicate.
+ * config/i386/i386.c (zero_all_vector_registers):
+ Use LEGACY_SSE_REGNO_P predicate.
+ (ix86_register_priority): Use REX_INT_REGNO_P, REX_SSE_REGNO_P
+ and EXT_REG_SSE_REGNO_P predicates.
+ (ix86_hard_regno_call_part_clobbered): Use REX_SSE_REGNO_P
+ and LEGACY_SSE_REGNO_P predicates.
+
+2021-11-17 Jason Merrill <jason@redhat.com>
+
+ * doc/invoke.texi (C++ Dialect Options): Document
+ -fimplicit-constexpr.
+
+2021-11-17 Przemyslaw Wirkus <przemyslaw.wirkus@arm.com>
+
+ * config/aarch64/aarch64-modes.def (VECTOR_MODE): New V8DI mode.
+ * config/aarch64/aarch64.c (aarch64_hard_regno_mode_ok): Handle
+ V8DImode.
+ * config/aarch64/iterators.md (define_mode_attr nunits): Add entry
+ for V8DI.
+
+2021-11-17 Martin Uecker <uecker@gcc.gnu.org>
+
+ PR c/91038
+ PR c/29970
+ * gimplify.c (gimplify_var_or_parm_decl): Update comment.
+ (gimplify_compound_lval): Gimplify base expression first.
+ (gimplify_target_expr): Add comment.
+
+2021-11-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/103192
+ * tree-ssa-loop-im.c (move_computations_worker): Use
+ reset_flow_sensitive_info instead of manually clearing
+ SSA_NAME_RANGE_INFO and do it for all SSA_NAMEs, not just ones
+ with integral types.
+
+2021-11-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/103255
+ * gimple-range-fold.cc (fold_using_range::range_of_address): Return
+ range_nonzero rather than unadjusted base's range. Formatting fixes.
+
+2021-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * doc/md.texi (cond_fmin@var{mode}, cond_fmax@var{mode}): Document.
+ * optabs.def (cond_fmin_optab, cond_fmax_optab): New optabs.
+ * internal-fn.def (COND_FMIN, COND_FMAX): New functions.
+ * internal-fn.c (first_commutative_argument): Handle them.
+ (FOR_EACH_COND_FN_PAIR): Likewise.
+ * match.pd (UNCOND_BINARY, COND_BINARY): Likewise.
+ * config/aarch64/aarch64-sve.md (cond_<fmaxmin><mode>): New
+ pattern.
+
+2021-11-17 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/i386/i386.md (*add<dwi>3_doubleword, *addv<dwi>4_doubleword,
+ *addv<dwi>4_doubleword_1, *sub<dwi>3_doubleword,
+ *subv<dwi>4_doubleword, *subv<dwi>4_doubleword_1,
+ *add<dwi>3_doubleword_cc_overflow_1, *divmodsi4_const,
+ *neg<dwi>2_doubleword, *tls_dynamic_gnu2_combine_64_<mode>): Fix split
+ condition.
+
+2021-11-17 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103288
+ * tree-ssa-phiopt.c (value_replacement): Return early if middle
+ block has more than one pred.
+
+2021-11-17 Kewen Lin <linkw@linux.ibm.com>
+
+ * config/visium/visium.md (*add<mode>3_insn, *addsi3_insn, *addi3_insn,
+ *sub<mode>3_insn, *subsi3_insn, *subdi3_insn, *neg<mode>2_insn,
+ *negdi2_insn, *and<mode>3_insn, *ior<mode>3_insn, *xor<mode>3_insn,
+ *one_cmpl<mode>2_insn, *ashl<mode>3_insn, *ashr<mode>3_insn,
+ *lshr<mode>3_insn, *trunchiqi2_insn, *truncsihi2_insn,
+ *truncdisi2_insn, *extendqihi2_insn, *extendqisi2_insn,
+ *extendhisi2_insn, *extendsidi2_insn, *zero_extendqihi2_insn,
+ *zero_extendqisi2_insn, *zero_extendsidi2_insn): Fix split condition.
+
+2021-11-17 Marek Polacek <polacek@redhat.com>
+
+ PR preprocessor/103026
+ * doc/invoke.texi: Document -Wbidi-chars.
+
+2021-11-17 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/103246
+ * ipa-modref.c (ipa_merge_modref_summary_after_inlining): Fix clearing
+ of to_info_lto
+
+2021-11-16 Jan Hubicka <jh@suse.cz>
+
+ * ipa-modref.c (get_modref_function_summary): Declare.
+ * ipa-modref.h (get_modref_function_summary): New function.
+ * tree-ssa-dse.c (clear_live_bytes_for_ref): Break out from ...
+ (clear_bytes_written_by): ... here; also clear memory killed by
+ calls.
+
+2021-11-16 Iain Sandoe <iain@sandoe.co.uk>
+
+ * ggc-common.c (gt_pch_save): If we cannot find a suitable
+ memory segment for save, then error-out, do not try to
+ continue.
+ (gt_pch_restore): Save the existing line table, and when
+ the replacement is being read, use that when constructing
+ diagnostics.
+
+2021-11-16 Peter Bergner <bergner@linux.ibm.com>
+
+ PR target/102976
+ * config/rs6000/mma.md (*vsx_assemble_pair): Add early-clobber for
+ output operand.
+ (*mma_assemble_acc): Likewise.
+
+2021-11-16 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/102960
+ * gimple-fold.c (get_range_strlen): Take bitmap as an argument rather
+ than a pointer to it.
+ (get_range_strlen_tree): Same. Remove bitmap allocation. Use
+ an auto_bitmap.
+ (get_maxval_strlen): Use an auto_bitmap.
+ * tree-ssa-strlen.c (get_range_strlen_dynamic): Factor out PHI
+ handling...
+ (get_range_strlen_phi): ...into this function.
+ Avoid assuming maximum string length is constant
+ (printf_strlen_execute): Dump pointer query cache contents when
+ details are requisted.
+
+2021-11-16 Jason Merrill <jason@redhat.com>
+
+ * langhooks.h (struct lang_hooks): Adjust comment.
+ * print-tree.c (print_node): Also call print_xnode hook for
+ tcc_constant class.
+
+2021-11-16 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103218
+ * match.pd: New pattern for "((type)(a<0)) << SIGNBITOFA".
+
+2021-11-16 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.md (maddhisi4): Use a single move to accumulator.
+ (umaddhisi4): Likewise.
+ (machi): Update pattern.
+ (umachi): Likewise.
+
+2021-11-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102880
+ * tree-ssa-dce.c (sort_phi_args): New function.
+ (make_forwarders_with_degenerate_phis): Likewise.
+ (perform_tree_ssa_dce): Call
+ make_forwarders_with_degenerate_phis.
+
+2021-11-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102880
+ * tree-ssa-phiopt.c (tree_ssa_phiopt_worker): Push
+ single_pred (bb1) condition to places that really need it.
+ (match_simplify_replacement): Likewise.
+ (value_replacement): Likewise.
+ (replace_phi_edge_with_variable): Deal with extra edges
+ into the middle BB.
+
+2021-11-16 Martin Jambor <mjambor@suse.cz>
+
+ * cfgexpand.c (expand_gimple_basic_block): Use build_debug_expr_decl,
+ add a fixme note about the mode assignment perhaps being unnecessary.
+ * ipa-param-manipulation.c (ipa_param_adjustments::modify_call):
+ Likewise.
+ (ipa_param_body_adjustments::mark_dead_statements): Likewise.
+ (ipa_param_body_adjustments::reset_debug_stmts): Likewise.
+ * tree-inline.c (remap_ssa_name): Likewise.
+ (tree_function_versioning): Likewise.
+ * tree-into-ssa.c (rewrite_debug_stmt_uses): Likewise.
+ * tree-ssa-loop-ivopts.c (remove_unused_ivs): Likewise.
+ * tree-ssa.c (insert_debug_temp_for_var_def): Likewise.
+
+2021-11-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/103208
+ * omp-expand.c (expand_omp_build_cond): New function.
+ (expand_omp_for_init_counts, expand_omp_for_init_vars,
+ expand_omp_for_static_nochunk, expand_omp_for_static_chunk): Use it.
+
+2021-11-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102009
+ * gimple-ssa-warn-access.cc (pass_waccess::check_alloc_size_call):
+ Punt if any of alloc_size arguments is out of bounds vs. number of
+ call arguments.
+
+2021-11-16 Roger Sayle <roger@nextmovesoftware.com>
+
+ * config/i386/i386.md (*bmi2_rorx<mode3>_1): Make conditional
+ on !optimize_function_for_size_p.
+ (*<any_rotate><mode>3_1): Add preferred_for_size attribute.
+ (define_splits): Conditionalize on !optimize_function_for_size_p.
+ (*bmi2_rorxsi3_1_zext): Likewise.
+ (*<any_rotate>si2_1_zext): Add preferred_for_size attribute.
+ (define_splits): Conditionalize on !optimize_function_for_size_p.
+
+2021-11-16 Jan Hubicka <jh@suse.cz>
+
+ PR ipa/103262
+ * ipa-modref.c (merge_call_side_effects): Fix uninitialized
+ access.
+
+2021-11-16 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103245
+ * match.pd: Combine the abs pattern matching using multiplication.
+ Adding optional nop_convert too.
+
+2021-11-16 H.J. Lu <hjl.tools@gmail.com>
+
+ PR middle-end/103268
+ * tree-ssa-ccp.c (optimize_atomic_bit_test_and): Add a missing
+ return.
+
2021-11-15 Siddhesh Poyarekar <siddhesh@gotplt.org>
* gimple-fold.c (gimple_fold_builtin_strncat): Use ranges to
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 7090fb4..7e15177 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20211116
+20211122
diff --git a/gcc/analyzer/ChangeLog b/gcc/analyzer/ChangeLog
index 40678a1..34a112d 100644
--- a/gcc/analyzer/ChangeLog
+++ b/gcc/analyzer/ChangeLog
@@ -1,3 +1,60 @@
+2021-11-19 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/103217
+ * engine.cc (exploded_graph::get_or_create_node): Pass in
+ m_ext_state to program_state::can_merge_with_p.
+ (exploded_graph::process_worklist): Likewise.
+ (exploded_graph::maybe_process_run_of_before_supernode_enodes):
+ Likewise.
+ (exploded_graph::process_node): Add missing call to detect_leaks
+ when handling phi nodes.
+ * program-state.cc (program_state::can_merge_with_p): Add
+ "ext_state" param. Pass it and state ptrs to
+ region_model::can_merge_with_p.
+ (selftest::test_program_state_merging): Update for new ext_state
+ param of program_state::can_merge_with_p.
+ (selftest::test_program_state_merging_2): Likewise.
+ * program-state.h (program_state::can_purge_p): Make const.
+ (program_state::can_merge_with_p): Add "ext_state" param.
+ * region-model.cc: Include "analyzer/program-state.h".
+ (region_model::can_merge_with_p): Add params "ext_state",
+ "state_a", and "state_b", use them when creating model_merger
+ object.
+ (model_merger::mergeable_svalue_p): New.
+ * region-model.h (region_model::can_merge_with_p): Add params
+ "ext_state", "state_a", and "state_b".
+ (model_merger::model_merger) Likewise, initializing new fields.
+ (model_merger::mergeable_svalue_p): New decl.
+ (model_merger::m_ext_state): New field.
+ (model_merger::m_state_a): New field.
+ (model_merger::m_state_b): New field.
+ * svalue.cc (svalue::can_merge_p): Call
+ model_merger::mergeable_svalue_p on both states and reject the
+ merger accordingly.
+
+2021-11-17 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/102695
+ * region-model-impl-calls.cc (region_model::impl_call_strchr): New.
+ * region-model-manager.cc
+ (region_model_manager::maybe_fold_unaryop): Simplify cast to
+ pointer type of an existing pointer to a region.
+ * region-model.cc (region_model::on_call_pre): Handle
+ BUILT_IN_STRCHR and "strchr".
+ (write_to_const_diagnostic::emit): Add auto_diagnostic_group. Add
+ alternate wordings for functions and labels.
+ (write_to_const_diagnostic::describe_final_event): Add alternate
+ wordings for functions and labels.
+ (region_model::check_for_writable_region): Handle RK_FUNCTION and
+ RK_LABEL.
+ * region-model.h (region_model::impl_call_strchr): New decl.
+
+2021-11-16 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/102662
+ * constraint-manager.cc (bounded_range::operator==): Require the
+ types to be the same for equality.
+
2021-11-13 David Malcolm <dmalcolm@redhat.com>
* analyzer.opt (Wanalyzer-tainted-allocation-size): New.
diff --git a/gcc/analyzer/constraint-manager.cc b/gcc/analyzer/constraint-manager.cc
index 6df23fb..ea6b5dc 100644
--- a/gcc/analyzer/constraint-manager.cc
+++ b/gcc/analyzer/constraint-manager.cc
@@ -432,7 +432,9 @@ bounded_range::intersects_p (const bounded_range &other,
bool
bounded_range::operator== (const bounded_range &other) const
{
- return (tree_int_cst_equal (m_lower, other.m_lower)
+ return (TREE_TYPE (m_lower) == TREE_TYPE (other.m_lower)
+ && TREE_TYPE (m_upper) == TREE_TYPE (other.m_upper)
+ && tree_int_cst_equal (m_lower, other.m_lower)
&& tree_int_cst_equal (m_upper, other.m_upper));
}
diff --git a/gcc/analyzer/engine.cc b/gcc/analyzer/engine.cc
index 096e219..e8a7cca 100644
--- a/gcc/analyzer/engine.cc
+++ b/gcc/analyzer/engine.cc
@@ -2417,7 +2417,7 @@ exploded_graph::get_or_create_node (const program_point &point,
/* This merges successfully within the loop. */
program_state merged_state (m_ext_state);
- if (pruned_state.can_merge_with_p (existing_state, point,
+ if (pruned_state.can_merge_with_p (existing_state, m_ext_state, point,
&merged_state))
{
merged_state.validate (m_ext_state);
@@ -2717,7 +2717,8 @@ exploded_graph::process_worklist ()
gcc_assert (state != state_2);
program_state merged_state (m_ext_state);
- if (state.can_merge_with_p (state_2, point, &merged_state))
+ if (state.can_merge_with_p (state_2, m_ext_state,
+ point, &merged_state))
{
if (logger)
logger->log ("merging EN: %i and EN: %i",
@@ -2973,7 +2974,8 @@ maybe_process_run_of_before_supernode_enodes (exploded_node *enode)
{
merged_state->validate (m_ext_state);
program_state merge (m_ext_state);
- if (it_state.can_merge_with_p (*merged_state, next_point, &merge))
+ if (it_state.can_merge_with_p (*merged_state, m_ext_state,
+ next_point, &merge))
{
*merged_state = merge;
merged_state->validate (m_ext_state);
@@ -3305,6 +3307,8 @@ exploded_graph::process_node (exploded_node *node)
(node->get_supernode (),
last_cfg_superedge,
&ctxt);
+ program_state::detect_leaks (state, next_state, NULL,
+ get_ext_state (), &ctxt);
}
program_point next_point (point.get_next ());
diff --git a/gcc/analyzer/program-state.cc b/gcc/analyzer/program-state.cc
index 1c87af0..47e4eca 100644
--- a/gcc/analyzer/program-state.cc
+++ b/gcc/analyzer/program-state.cc
@@ -1197,6 +1197,7 @@ program_state::get_representative_tree (const svalue *sval) const
bool
program_state::can_merge_with_p (const program_state &other,
+ const extrinsic_state &ext_state,
const program_point &point,
program_state *out) const
{
@@ -1213,7 +1214,9 @@ program_state::can_merge_with_p (const program_state &other,
/* Attempt to merge the region_models. */
if (!m_region_model->can_merge_with_p (*other.m_region_model,
point,
- out->m_region_model))
+ out->m_region_model,
+ &ext_state,
+ this, &other))
return false;
/* Copy m_checker_states to OUT. */
@@ -1645,7 +1648,7 @@ test_program_state_merging ()
with the given sm-state.
They ought to be mergeable, preserving the sm-state. */
program_state merged (ext_state);
- ASSERT_TRUE (s0.can_merge_with_p (s1, point, &merged));
+ ASSERT_TRUE (s0.can_merge_with_p (s1, ext_state, point, &merged));
merged.validate (ext_state);
/* Verify that the merged state has the sm-state for "p". */
@@ -1703,7 +1706,7 @@ test_program_state_merging_2 ()
/* They ought to not be mergeable. */
program_state merged (ext_state);
- ASSERT_FALSE (s0.can_merge_with_p (s1, point, &merged));
+ ASSERT_FALSE (s0.can_merge_with_p (s1, ext_state, point, &merged));
}
/* Run all of the selftests within this file. */
diff --git a/gcc/analyzer/program-state.h b/gcc/analyzer/program-state.h
index eb49006..4579e2a 100644
--- a/gcc/analyzer/program-state.h
+++ b/gcc/analyzer/program-state.h
@@ -242,7 +242,7 @@ public:
tree get_representative_tree (const svalue *sval) const;
bool can_purge_p (const extrinsic_state &ext_state,
- const svalue *sval)
+ const svalue *sval) const
{
/* Don't purge vars that have non-purgeable sm state, to avoid
generating false "leak" complaints. */
@@ -258,6 +258,7 @@ public:
}
bool can_merge_with_p (const program_state &other,
+ const extrinsic_state &ext_state,
const program_point &point,
program_state *out) const;
diff --git a/gcc/analyzer/region-model-impl-calls.cc b/gcc/analyzer/region-model-impl-calls.cc
index 90d4cf9..ae50e69 100644
--- a/gcc/analyzer/region-model-impl-calls.cc
+++ b/gcc/analyzer/region-model-impl-calls.cc
@@ -678,6 +678,75 @@ region_model::impl_call_realloc (const call_details &cd)
}
}
+/* Handle the on_call_pre part of "strchr" and "__builtin_strchr". */
+
+void
+region_model::impl_call_strchr (const call_details &cd)
+{
+ class strchr_call_info : public call_info
+ {
+ public:
+ strchr_call_info (const call_details &cd, bool found)
+ : call_info (cd), m_found (found)
+ {
+ }
+
+ label_text get_desc (bool can_colorize) const FINAL OVERRIDE
+ {
+ if (m_found)
+ return make_label_text (can_colorize,
+ "when %qE returns non-NULL",
+ get_fndecl ());
+ else
+ return make_label_text (can_colorize,
+ "when %qE returns NULL",
+ get_fndecl ());
+ }
+
+ bool update_model (region_model *model,
+ const exploded_edge *,
+ region_model_context *ctxt) const FINAL OVERRIDE
+ {
+ const call_details cd (get_call_details (model, ctxt));
+ if (tree lhs_type = cd.get_lhs_type ())
+ {
+ region_model_manager *mgr = model->get_manager ();
+ const svalue *result;
+ if (m_found)
+ {
+ const svalue *str_sval = cd.get_arg_svalue (0);
+ const region *str_reg
+ = model->deref_rvalue (str_sval, cd.get_arg_tree (0),
+ cd.get_ctxt ());
+ /* We want str_sval + OFFSET for some unknown OFFSET.
+ Use a conjured_svalue to represent the offset,
+ using the str_reg as the id of the conjured_svalue. */
+ const svalue *offset
+ = mgr->get_or_create_conjured_svalue (size_type_node,
+ cd.get_call_stmt (),
+ str_reg);
+ result = mgr->get_or_create_binop (lhs_type, POINTER_PLUS_EXPR,
+ str_sval, offset);
+ }
+ else
+ result = mgr->get_or_create_int_cst (lhs_type, 0);
+ cd.maybe_set_lhs (result);
+ }
+ return true;
+ }
+ private:
+ bool m_found;
+ };
+
+ /* Bifurcate state, creating a "not found" out-edge. */
+ if (cd.get_ctxt ())
+ cd.get_ctxt ()->bifurcate (new strchr_call_info (cd, false));
+
+ /* The "unbifurcated" state is the "found" case. */
+ strchr_call_info found (cd, true);
+ found.update_model (this, NULL, cd.get_ctxt ());
+}
+
/* Handle the on_call_pre part of "strcpy" and "__builtin_strcpy_chk". */
void
diff --git a/gcc/analyzer/region-model-manager.cc b/gcc/analyzer/region-model-manager.cc
index 1cdec1b..fdf3212 100644
--- a/gcc/analyzer/region-model-manager.cc
+++ b/gcc/analyzer/region-model-manager.cc
@@ -380,6 +380,13 @@ region_model_manager::maybe_fold_unaryop (tree type, enum tree_code op,
== boolean_true_node))
return maybe_fold_unaryop (type, op, innermost_arg);
}
+ /* Avoid creating symbolic regions for pointer casts by
+ simplifying (T*)(&REGION) to ((T*)&REGION). */
+ if (const region_svalue *region_sval = arg->dyn_cast_region_svalue ())
+ if (POINTER_TYPE_P (type)
+ && region_sval->get_type ()
+ && POINTER_TYPE_P (region_sval->get_type ()))
+ return get_ptr_svalue (type, region_sval->get_pointee ());
}
break;
case TRUTH_NOT_EXPR:
diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc
index 416a5ac..dccf902 100644
--- a/gcc/analyzer/region-model.cc
+++ b/gcc/analyzer/region-model.cc
@@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see
#include "analyzer/pending-diagnostic.h"
#include "analyzer/region-model-reachability.h"
#include "analyzer/analyzer-selftests.h"
+#include "analyzer/program-state.h"
#include "stor-layout.h"
#include "attribs.h"
#include "tree-object-size.h"
@@ -1133,6 +1134,9 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt,
break;
case BUILT_IN_REALLOC:
return false;
+ case BUILT_IN_STRCHR:
+ impl_call_strchr (cd);
+ return false;
case BUILT_IN_STRCPY:
case BUILT_IN_STRCPY_CHK:
impl_call_strcpy (cd);
@@ -1225,6 +1229,12 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt,
impl_call_memset (cd);
return false;
}
+ else if (is_named_call_p (callee_fndecl, "strchr", call, 2)
+ && POINTER_TYPE_P (cd.get_arg_type (0)))
+ {
+ impl_call_strchr (cd);
+ return false;
+ }
else if (is_named_call_p (callee_fndecl, "strlen", call, 1)
&& POINTER_TYPE_P (cd.get_arg_type (0)))
{
@@ -2161,8 +2171,23 @@ public:
bool emit (rich_location *rich_loc) FINAL OVERRIDE
{
- bool warned = warning_at (rich_loc, OPT_Wanalyzer_write_to_const,
- "write to %<const%> object %qE", m_decl);
+ auto_diagnostic_group d;
+ bool warned;
+ switch (m_reg->get_kind ())
+ {
+ default:
+ warned = warning_at (rich_loc, OPT_Wanalyzer_write_to_const,
+ "write to %<const%> object %qE", m_decl);
+ break;
+ case RK_FUNCTION:
+ warned = warning_at (rich_loc, OPT_Wanalyzer_write_to_const,
+ "write to function %qE", m_decl);
+ break;
+ case RK_LABEL:
+ warned = warning_at (rich_loc, OPT_Wanalyzer_write_to_const,
+ "write to label %qE", m_decl);
+ break;
+ }
if (warned)
inform (DECL_SOURCE_LOCATION (m_decl), "declared here");
return warned;
@@ -2170,7 +2195,15 @@ public:
label_text describe_final_event (const evdesc::final_event &ev) FINAL OVERRIDE
{
- return ev.formatted_print ("write to %<const%> object %qE here", m_decl);
+ switch (m_reg->get_kind ())
+ {
+ default:
+ return ev.formatted_print ("write to %<const%> object %qE here", m_decl);
+ case RK_FUNCTION:
+ return ev.formatted_print ("write to function %qE here", m_decl);
+ case RK_LABEL:
+ return ev.formatted_print ("write to label %qE here", m_decl);
+ }
}
private:
@@ -2231,6 +2264,20 @@ region_model::check_for_writable_region (const region* dest_reg,
{
default:
break;
+ case RK_FUNCTION:
+ {
+ const function_region *func_reg = as_a <const function_region *> (base_reg);
+ tree fndecl = func_reg->get_fndecl ();
+ ctxt->warn (new write_to_const_diagnostic (func_reg, fndecl));
+ }
+ break;
+ case RK_LABEL:
+ {
+ const label_region *label_reg = as_a <const label_region *> (base_reg);
+ tree label = label_reg->get_label ();
+ ctxt->warn (new write_to_const_diagnostic (label_reg, label));
+ }
+ break;
case RK_DECL:
{
const decl_region *decl_reg = as_a <const decl_region *> (base_reg);
@@ -3637,7 +3684,10 @@ region_model::poison_any_pointers_to_descendents (const region *reg,
bool
region_model::can_merge_with_p (const region_model &other_model,
const program_point &point,
- region_model *out_model) const
+ region_model *out_model,
+ const extrinsic_state *ext_state,
+ const program_state *state_a,
+ const program_state *state_b) const
{
gcc_assert (out_model);
gcc_assert (m_mgr == other_model.m_mgr);
@@ -3647,7 +3697,8 @@ region_model::can_merge_with_p (const region_model &other_model,
return false;
out_model->m_current_frame = m_current_frame;
- model_merger m (this, &other_model, point, out_model);
+ model_merger m (this, &other_model, point, out_model,
+ ext_state, state_a, state_b);
if (!store::can_merge_p (&m_store, &other_model.m_store,
&out_model->m_store, m_mgr->get_store_manager (),
@@ -3851,6 +3902,30 @@ model_merger::dump (bool simple) const
dump (stderr, simple);
}
+/* Return true if it's OK to merge SVAL with other svalues. */
+
+bool
+model_merger::mergeable_svalue_p (const svalue *sval) const
+{
+ if (m_ext_state)
+ {
+ /* Reject merging svalues that have non-purgable sm-state,
+ to avoid falsely reporting memory leaks by merging them
+ with something else. For example, given a local var "p",
+ reject the merger of a:
+ store_a mapping "p" to a malloc-ed ptr
+ with:
+ store_b mapping "p" to a NULL ptr. */
+ if (m_state_a)
+ if (!m_state_a->can_purge_p (*m_ext_state, sval))
+ return false;
+ if (m_state_b)
+ if (!m_state_b->can_purge_p (*m_ext_state, sval))
+ return false;
+ }
+ return true;
+}
+
} // namespace ana
/* Dump RMODEL fully to stderr (i.e. without summarization). */
diff --git a/gcc/analyzer/region-model.h b/gcc/analyzer/region-model.h
index 13e8109..bffbdf2 100644
--- a/gcc/analyzer/region-model.h
+++ b/gcc/analyzer/region-model.h
@@ -586,6 +586,7 @@ class region_model
void impl_call_memcpy (const call_details &cd);
void impl_call_memset (const call_details &cd);
void impl_call_realloc (const call_details &cd);
+ void impl_call_strchr (const call_details &cd);
void impl_call_strcpy (const call_details &cd);
void impl_call_strlen (const call_details &cd);
void impl_call_operator_new (const call_details &cd);
@@ -720,7 +721,10 @@ class region_model
bool can_merge_with_p (const region_model &other_model,
const program_point &point,
- region_model *out_model) const;
+ region_model *out_model,
+ const extrinsic_state *ext_state = NULL,
+ const program_state *state_a = NULL,
+ const program_state *state_b = NULL) const;
tree get_fndecl_for_call (const gcall *call,
region_model_context *ctxt);
@@ -986,10 +990,15 @@ struct model_merger
model_merger (const region_model *model_a,
const region_model *model_b,
const program_point &point,
- region_model *merged_model)
+ region_model *merged_model,
+ const extrinsic_state *ext_state,
+ const program_state *state_a,
+ const program_state *state_b)
: m_model_a (model_a), m_model_b (model_b),
m_point (point),
- m_merged_model (merged_model)
+ m_merged_model (merged_model),
+ m_ext_state (ext_state),
+ m_state_a (state_a), m_state_b (state_b)
{
}
@@ -1002,10 +1011,16 @@ struct model_merger
return m_model_a->get_manager ();
}
+ bool mergeable_svalue_p (const svalue *) const;
+
const region_model *m_model_a;
const region_model *m_model_b;
const program_point &m_point;
region_model *m_merged_model;
+
+ const extrinsic_state *m_ext_state;
+ const program_state *m_state_a;
+ const program_state *m_state_b;
};
/* A record that can (optionally) be written out when
diff --git a/gcc/analyzer/svalue.cc b/gcc/analyzer/svalue.cc
index 5f2fe4c..7cbcf0c 100644
--- a/gcc/analyzer/svalue.cc
+++ b/gcc/analyzer/svalue.cc
@@ -193,6 +193,14 @@ svalue::can_merge_p (const svalue *other,
return NULL;
}
+ /* Reject merging svalues that have non-purgable sm-state,
+ to avoid falsely reporting memory leaks by merging them
+ with something else. */
+ if (!merger->mergeable_svalue_p (this))
+ return NULL;
+ if (!merger->mergeable_svalue_p (other))
+ return NULL;
+
/* Widening. */
/* Merge: (new_cst, existing_cst) -> widen (existing, new). */
if (maybe_get_constant () && other->maybe_get_constant ())
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 7ed0102..2e0b81d 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,44 @@
+2021-11-19 Martin Sebor <msebor@redhat.com>
+
+ PR c++/33925
+ PR c/102867
+ * c-common.c (decl_with_nonnull_addr_p): Call maybe_nonzero_address
+ and improve handling tof defined symbols.
+
+2021-11-19 Martin Liska <mliska@suse.cz>
+
+ Revert:
+ 2021-11-18 Martin Liska <mliska@suse.cz>
+
+ * c-gimplify.c (genericize_c_loop): Use option directly.
+
+2021-11-18 Matthias Kretz <m.kretz@gsi.de>
+
+ * c-common.c (c_common_reswords): Add __builtin_assoc_barrier.
+ * c-common.h (enum rid): Add RID_BUILTIN_ASSOC_BARRIER.
+
+2021-11-18 Martin Liska <mliska@suse.cz>
+
+ * c-gimplify.c (genericize_c_loop): Use option directly.
+
+2021-11-17 Martin Uecker <uecker@gcc.gnu.org>
+
+ PR c/91038
+ PR c/29970
+ * c-common.c (pointer_int_sum): Make sure pointer expressions
+ are evaluated first when the size expression depends on for
+ variably-modified types.
+
+2021-11-17 Marek Polacek <polacek@redhat.com>
+
+ PR preprocessor/103026
+ * c.opt (Wbidi-chars, Wbidi-chars=): New option.
+
+2021-11-16 Jason Merrill <jason@redhat.com>
+
+ * c-common.c (release_tree_vector): Only cache vecs smaller than
+ 16 elements.
+
2021-11-15 Jason Merrill <jason@redhat.com>
* c.opt: Add -fimplicit-constexpr.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 436df45..a25d59f 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -384,6 +384,7 @@ const struct c_common_resword c_common_reswords[] =
{ "__builtin_convertvector", RID_BUILTIN_CONVERTVECTOR, 0 },
{ "__builtin_has_attribute", RID_BUILTIN_HAS_ATTRIBUTE, 0 },
{ "__builtin_launder", RID_BUILTIN_LAUNDER, D_CXXONLY },
+ { "__builtin_assoc_barrier", RID_BUILTIN_ASSOC_BARRIER, 0 },
{ "__builtin_shuffle", RID_BUILTIN_SHUFFLE, 0 },
{ "__builtin_shufflevector", RID_BUILTIN_SHUFFLEVECTOR, 0 },
{ "__builtin_tgmath", RID_BUILTIN_TGMATH, D_CONLY },
@@ -3306,7 +3307,19 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
TREE_TYPE (result_type)))
size_exp = integer_one_node;
else
- size_exp = size_in_bytes_loc (loc, TREE_TYPE (result_type));
+ {
+ size_exp = size_in_bytes_loc (loc, TREE_TYPE (result_type));
+ /* Wrap the pointer expression in a SAVE_EXPR to make sure it
+ is evaluated first when the size expression may depend
+ on it for VM types. */
+ if (TREE_SIDE_EFFECTS (size_exp)
+ && TREE_SIDE_EFFECTS (ptrop)
+ && variably_modified_type_p (TREE_TYPE (ptrop), NULL))
+ {
+ ptrop = save_expr (ptrop);
+ size_exp = build2 (COMPOUND_EXPR, TREE_TYPE (intop), ptrop, size_exp);
+ }
+ }
/* We are manipulating pointer values, so we don't need to warn
about relying on undefined signed overflow. We disable the
@@ -3400,16 +3413,43 @@ c_wrap_maybe_const (tree expr, bool non_const)
/* Return whether EXPR is a declaration whose address can never be NULL.
The address of the first struct member could be NULL only if it were
- accessed through a NULL pointer, and such an access would be invalid. */
+ accessed through a NULL pointer, and such an access would be invalid.
+ The address of a weak symbol may be null unless it has a definition. */
bool
decl_with_nonnull_addr_p (const_tree expr)
{
- return (DECL_P (expr)
- && (TREE_CODE (expr) == FIELD_DECL
- || TREE_CODE (expr) == PARM_DECL
- || TREE_CODE (expr) == LABEL_DECL
- || !DECL_WEAK (expr)));
+ if (!DECL_P (expr))
+ return false;
+
+ if (TREE_CODE (expr) == FIELD_DECL
+ || TREE_CODE (expr) == PARM_DECL
+ || TREE_CODE (expr) == LABEL_DECL)
+ return true;
+
+ if (!VAR_OR_FUNCTION_DECL_P (expr))
+ return false;
+
+ if (!DECL_WEAK (expr))
+ /* Ordinary (non-weak) symbols have nonnull addresses. */
+ return true;
+
+ if (DECL_INITIAL (expr) && DECL_INITIAL (expr) != error_mark_node)
+ /* Initialized weak symbols have nonnull addresses. */
+ return true;
+
+ if (DECL_EXTERNAL (expr) || !TREE_STATIC (expr))
+ /* Uninitialized extern weak symbols and weak symbols with no
+ allocated storage might have a null address. */
+ return false;
+
+ tree attribs = DECL_ATTRIBUTES (expr);
+ if (lookup_attribute ("weakref", attribs))
+ /* Weakref symbols might have a null address unless their referent
+ is known not to. Don't bother following weakref targets here. */
+ return false;
+
+ return true;
}
/* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
@@ -8213,8 +8253,16 @@ release_tree_vector (vec<tree, va_gc> *vec)
{
if (vec != NULL)
{
- vec->truncate (0);
- vec_safe_push (tree_vector_cache, vec);
+ if (vec->allocated () >= 16)
+ /* Don't cache vecs that have expanded more than once. On a p64
+ target, vecs double in alloc size with each power of 2 elements, e.g
+ at 16 elements the alloc increases from 128 to 256 bytes. */
+ vec_free (vec);
+ else
+ {
+ vec->truncate (0);
+ vec_safe_push (tree_vector_cache, vec);
+ }
}
}
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index d5dad99..c089fda 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -108,7 +108,7 @@ enum rid
RID_EXTENSION, RID_IMAGPART, RID_REALPART, RID_LABEL, RID_CHOOSE_EXPR,
RID_TYPES_COMPATIBLE_P, RID_BUILTIN_COMPLEX, RID_BUILTIN_SHUFFLE,
RID_BUILTIN_SHUFFLEVECTOR, RID_BUILTIN_CONVERTVECTOR, RID_BUILTIN_TGMATH,
- RID_BUILTIN_HAS_ATTRIBUTE,
+ RID_BUILTIN_HAS_ATTRIBUTE, RID_BUILTIN_ASSOC_BARRIER,
RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128,
/* TS 18661-3 keywords, in the same sequence as the TI_* values. */
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 8a4cd63..3976fc3 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -374,6 +374,30 @@ Wbad-function-cast
C ObjC Var(warn_bad_function_cast) Warning
Warn about casting functions to incompatible types.
+Wbidi-chars
+C ObjC C++ ObjC++ Warning Alias(Wbidi-chars=,any,none)
+;
+
+Wbidi-chars=
+C ObjC C++ ObjC++ RejectNegative Joined Warning CPP(cpp_warn_bidirectional) CppReason(CPP_W_BIDIRECTIONAL) Var(warn_bidirectional) Init(bidirectional_unpaired) Enum(cpp_bidirectional_level)
+-Wbidi-chars=[none|unpaired|any] Warn about UTF-8 bidirectional control characters.
+
+; Required for these enum values.
+SourceInclude
+cpplib.h
+
+Enum
+Name(cpp_bidirectional_level) Type(int) UnknownError(argument %qs to %<-Wbidi-chars%> not recognized)
+
+EnumValue
+Enum(cpp_bidirectional_level) String(none) Value(bidirectional_none)
+
+EnumValue
+Enum(cpp_bidirectional_level) String(unpaired) Value(bidirectional_unpaired)
+
+EnumValue
+Enum(cpp_bidirectional_level) String(any) Value(bidirectional_any)
+
Wbool-compare
C ObjC C++ ObjC++ Var(warn_bool_compare) Warning LangEnabledBy(C ObjC C++ ObjC++,Wall)
Warn about boolean expression compared with an integer value different from true/false.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 3ce48f1..d42244d 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,32 @@
+2021-11-19 Martin Sebor <msebor@redhat.com>
+
+ PR c++/33925
+ PR c/102867
+ * c-typeck.c (maybe_warn_for_null_address): Suppress warnings for
+ code resulting from macro expansion.
+
+2021-11-19 Martin Liska <mliska@suse.cz>
+
+ Revert:
+ 2021-11-19 Martin Liska <mliska@suse.cz>
+
+ * c-parser.c (add_debug_begin_stmt): Use option directly.
+
+2021-11-18 Matthias Kretz <m.kretz@gsi.de>
+
+ * c-decl.c (names_builtin_p): Handle RID_BUILTIN_ASSOC_BARRIER.
+ * c-parser.c (c_parser_postfix_expression): Likewise.
+
+2021-11-18 Martin Liska <mliska@suse.cz>
+
+ * c-parser.c (add_debug_begin_stmt): Use option directly.
+
+2021-11-17 Martin Sebor <msebor@redhat.com>
+
+ PR c/101702
+ * c-decl.c (get_parm_array_spec): Strip casts earlier and fold array
+ bounds before deciding if they're constant.
+
2021-11-15 Jakub Jelinek <jakub@redhat.com>
* c-parser.c (OMP_TARGET_CLAUSE_MASK): Add
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 186fa16..3e28a03 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -5866,6 +5866,12 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs)
if (pd->u.array.static_p)
spec += 's';
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (nelts)))
+ /* Avoid invalid NELTS. */
+ return attrs;
+
+ STRIP_NOPS (nelts);
+ nelts = c_fully_fold (nelts, false, nullptr);
if (TREE_CODE (nelts) == INTEGER_CST)
{
/* Skip all constant bounds except the most significant one.
@@ -5883,13 +5889,9 @@ get_parm_array_spec (const struct c_parm *parm, tree attrs)
spec += buf;
break;
}
- else if (!INTEGRAL_TYPE_P (TREE_TYPE (nelts)))
- /* Avoid invalid NELTS. */
- return attrs;
/* Each variable VLA bound is represented by a dollar sign. */
spec += "$";
- STRIP_NOPS (nelts);
vbchain = tree_cons (NULL_TREE, nelts, vbchain);
}
@@ -10619,6 +10621,7 @@ names_builtin_p (const char *name)
case RID_BUILTIN_HAS_ATTRIBUTE:
case RID_BUILTIN_SHUFFLE:
case RID_BUILTIN_SHUFFLEVECTOR:
+ case RID_BUILTIN_ASSOC_BARRIER:
case RID_CHOOSE_EXPR:
case RID_OFFSETOF:
case RID_TYPES_COMPATIBLE_P:
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 83e837c..f312630 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -8962,6 +8962,7 @@ c_parser_predefined_identifier (c_parser *parser)
assignment-expression ,
assignment-expression, )
__builtin_convertvector ( assignment-expression , type-name )
+ __builtin_assoc_barrier ( assignment-expression )
offsetof-member-designator:
identifier
@@ -10107,6 +10108,25 @@ c_parser_postfix_expression (c_parser *parser)
}
}
break;
+ case RID_BUILTIN_ASSOC_BARRIER:
+ {
+ location_t start_loc = loc;
+ c_parser_consume_token (parser);
+ matching_parens parens;
+ if (!parens.require_open (parser))
+ {
+ expr.set_error ();
+ break;
+ }
+ e1 = c_parser_expr_no_commas (parser, NULL);
+ mark_exp_read (e1.value);
+ location_t end_loc = c_parser_peek_token (parser)->get_finish ();
+ parens.skip_until_found_close (parser);
+ expr.value = build1_loc (loc, PAREN_EXPR, TREE_TYPE (e1.value),
+ e1.value);
+ set_c_expr_source_range (&expr, start_loc, end_loc);
+ }
+ break;
case RID_AT_SELECTOR:
{
gcc_assert (c_dialect_objc ());
diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c
index 782414f..50d7010 100644
--- a/gcc/c/c-typeck.c
+++ b/gcc/c/c-typeck.c
@@ -11588,7 +11588,10 @@ build_vec_cmp (tree_code code, tree type,
static void
maybe_warn_for_null_address (location_t loc, tree op, tree_code code)
{
- if (!warn_address || warning_suppressed_p (op, OPT_Waddress))
+ /* Prevent warnings issued for macro expansion. */
+ if (!warn_address
+ || warning_suppressed_p (op, OPT_Waddress)
+ || from_macro_expansion_at (loc))
return;
if (TREE_CODE (op) == NOP_EXPR)
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 466b66d..8e7c126 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -2390,7 +2390,8 @@ cgraph_node::get_availability (symtab_node *ref)
to code cp_cannot_inline_tree_fn and probably shall be shared and
the inlinability hooks completely eliminated). */
- else if (decl_replaceable_p (decl) && !DECL_EXTERNAL (decl))
+ else if (decl_replaceable_p (decl, semantic_interposition)
+ && !DECL_EXTERNAL (decl))
avail = AVAIL_INTERPOSABLE;
else avail = AVAIL_AVAILABLE;
@@ -3486,6 +3487,13 @@ cgraph_node::verify_node (void)
"returns a pointer");
error_found = true;
}
+ if (definition && externally_visible
+ && semantic_interposition
+ != opt_for_fn (decl, flag_semantic_interposition))
+ {
+ error ("semantic interposition mismatch");
+ error_found = true;
+ }
for (e = indirect_calls; e; e = e->next_callee)
{
if (e->aux)
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index e42e305..dafdfd2 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -117,6 +117,7 @@ public:
refuse_visibility_changes (false), externally_visible (false),
no_reorder (false), force_output (false), forced_by_abi (false),
unique_name (false), implicit_section (false), body_removed (false),
+ semantic_interposition (flag_semantic_interposition),
used_from_other_partition (false), in_other_partition (false),
address_taken (false), in_init_priority_hash (false),
need_lto_streaming (false), offloadable (false), ifunc_resolver (false),
@@ -557,6 +558,8 @@ public:
/* True when body and other characteristics have been removed by
symtab_remove_unreachable_nodes. */
unsigned body_removed : 1;
+ /* True when symbol should comply to -fsemantic-interposition flag. */
+ unsigned semantic_interposition : 1;
/*** WHOPR Partitioning flags.
These flags are used at ltrans stage when only part of the callgraph is
diff --git a/gcc/cgraphclones.c b/gcc/cgraphclones.c
index ae91dcc..c997b82 100644
--- a/gcc/cgraphclones.c
+++ b/gcc/cgraphclones.c
@@ -172,6 +172,7 @@ set_new_clone_decl_and_node_flags (cgraph_node *new_node)
new_node->externally_visible = 0;
new_node->local = 1;
new_node->lowered = true;
+ new_node->semantic_interposition = 0;
}
/* Duplicate thunk THUNK if necessary but make it to refer to NODE.
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 55cb034..1e58ffd 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -452,6 +452,7 @@ cgraph_node::finalize_function (tree decl, bool no_collect)
node->definition = true;
notice_global_symbol (decl);
node->lowered = DECL_STRUCT_FUNCTION (decl)->cfg != NULL;
+ node->semantic_interposition = opt_for_fn (decl, flag_semantic_interposition);
if (!flag_toplevel_reorder)
node->no_reorder = true;
@@ -554,6 +555,8 @@ cgraph_node::add_new_function (tree fndecl, bool lowered)
node = cgraph_node::get_create (fndecl);
node->local = false;
node->definition = true;
+ node->semantic_interposition = opt_for_fn (fndecl,
+ flag_semantic_interposition);
node->force_output = true;
if (TREE_PUBLIC (fndecl))
node->externally_visible = true;
@@ -581,6 +584,8 @@ cgraph_node::add_new_function (tree fndecl, bool lowered)
if (lowered)
node->lowered = true;
node->definition = true;
+ node->semantic_interposition = opt_for_fn (fndecl,
+ flag_semantic_interposition);
node->analyze ();
push_cfun (DECL_STRUCT_FUNCTION (fndecl));
gimple_register_cfg_hooks ();
@@ -954,6 +959,7 @@ varpool_node::finalize_decl (tree decl)
/* Set definition first before calling notice_global_symbol so that
it is available to notice_global_symbol. */
node->definition = true;
+ node->semantic_interposition = flag_semantic_interposition;
notice_global_symbol (decl);
if (!flag_toplevel_reorder)
node->no_reorder = true;
@@ -2576,6 +2582,7 @@ cgraph_node::create_wrapper (cgraph_node *target)
/* Turn alias into thunk and expand it into GIMPLE representation. */
definition = true;
+ semantic_interposition = opt_for_fn (decl, flag_semantic_interposition);
/* Create empty thunk, but be sure we did not keep former thunk around.
In that case we would need to preserve the info. */
diff --git a/gcc/common.opt b/gcc/common.opt
index de9b848..db6010e 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -2539,7 +2539,7 @@ Common Var(flag_sel_sched_reschedule_pipelined) Init(0) Optimization
Reschedule pipelined regions without pipelining.
fsemantic-interposition
-Common Var(flag_semantic_interposition) Init(1)
+Common Var(flag_semantic_interposition) Init(1) Optimization
Allow interposing function (or variables) by ones with different semantics (or initializer) respectively by dynamic linker.
; sched_stalled_insns means that insns can be moved prematurely from the queue
diff --git a/gcc/config/aarch64/aarch64-modes.def b/gcc/config/aarch64/aarch64-modes.def
index ac97d22..f0265bd 100644
--- a/gcc/config/aarch64/aarch64-modes.def
+++ b/gcc/config/aarch64/aarch64-modes.def
@@ -81,6 +81,11 @@ INT_MODE (OI, 32);
INT_MODE (CI, 48);
INT_MODE (XI, 64);
+/* V8DI mode. */
+VECTOR_MODE_WITH_PREFIX (V, INT, DI, 8, 5);
+
+ADJUST_ALIGNMENT (V8DI, 8);
+
/* Define Advanced SIMD modes for structures of 2, 3 and 4 d-registers. */
#define ADV_SIMD_D_REG_STRUCT_MODES(NVECS, VB, VH, VS, VD) \
VECTOR_MODES_WITH_PREFIX (V##NVECS##x, INT, 8, 3); \
diff --git a/gcc/config/aarch64/aarch64-sve.md b/gcc/config/aarch64/aarch64-sve.md
index 5de479e..0f5bf5e 100644
--- a/gcc/config/aarch64/aarch64-sve.md
+++ b/gcc/config/aarch64/aarch64-sve.md
@@ -6287,7 +6287,7 @@
;; -------------------------------------------------------------------------
;; Unpredicated fmax/fmin (the libm functions). The optabs for the
-;; smin/smax rtx codes are handled in the generic section above.
+;; smax/smin rtx codes are handled in the generic section above.
(define_expand "<fmaxmin><mode>3"
[(set (match_operand:SVE_FULL_F 0 "register_operand")
(unspec:SVE_FULL_F
@@ -6302,6 +6302,23 @@
}
)
+;; Predicated fmax/fmin (the libm functions). The optabs for the
+;; smax/smin rtx codes are handled in the generic section above.
+(define_expand "cond_<fmaxmin><mode>"
+ [(set (match_operand:SVE_FULL_F 0 "register_operand")
+ (unspec:SVE_FULL_F
+ [(match_operand:<VPRED> 1 "register_operand")
+ (unspec:SVE_FULL_F
+ [(match_dup 1)
+ (const_int SVE_RELAXED_GP)
+ (match_operand:SVE_FULL_F 2 "register_operand")
+ (match_operand:SVE_FULL_F 3 "aarch64_sve_float_maxmin_operand")]
+ SVE_COND_FP_MAXMIN_PUBLIC)
+ (match_operand:SVE_FULL_F 4 "aarch64_simd_reg_or_zero")]
+ UNSPEC_SEL))]
+ "TARGET_SVE"
+)
+
;; Predicated floating-point maximum/minimum.
(define_insn "@aarch64_pred_<optab><mode>"
[(set (match_operand:SVE_FULL_F 0 "register_operand" "=w, w, ?&w, ?&w")
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index d8410fc..7389b59 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -3394,6 +3394,10 @@ aarch64_hard_regno_nregs (unsigned regno, machine_mode mode)
static bool
aarch64_hard_regno_mode_ok (unsigned regno, machine_mode mode)
{
+ if (mode == V8DImode)
+ return IN_RANGE (regno, R0_REGNUM, R23_REGNUM)
+ && multiple_p (regno - R0_REGNUM, 2);
+
if (GET_MODE_CLASS (mode) == MODE_CC)
return regno == CC_REGNUM;
diff --git a/gcc/config/aarch64/iterators.md b/gcc/config/aarch64/iterators.md
index a9842b3..2c58d55 100644
--- a/gcc/config/aarch64/iterators.md
+++ b/gcc/config/aarch64/iterators.md
@@ -1062,7 +1062,7 @@
(define_mode_attr nunits [(V8QI "8") (V16QI "16")
(V4HI "4") (V8HI "8")
(V2SI "2") (V4SI "4")
- (V2DI "2")
+ (V2DI "2") (V8DI "8")
(V4HF "4") (V8HF "8")
(V4BF "4") (V8BF "8")
(V2SF "2") (V4SF "4")
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index fd65f4d..10a19aa 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -1959,7 +1959,8 @@
(plus:SI (match_dup 0)
(const_int -1)))
(unspec [(const_int 0)] UNSPEC_LSETUP_END)
- (clobber (match_dup 2))])] ; match_scratch
+ (clobber (match_dup 2))
+ (clobber (reg:BI REG_CC))])] ; match_scratch
""
{
/* The loop optimizer doesn't check the predicates... */
@@ -1979,7 +1980,8 @@
(plus (match_dup 2)
(const_int -1)))
(unspec [(const_int 0)] UNSPEC_LSETUP_END)
- (clobber (match_scratch:SI 3 "=X,&r,&r"))]
+ (clobber (match_scratch:SI 3 "=X,&r,&r"))
+ (clobber (reg:BI REG_CC))]
""
"@
/* loop end %0 %l1 */
@@ -1997,7 +1999,8 @@
(plus (match_dup 0)
(const_int -1)))
(unspec [(const_int 0)] UNSPEC_LSETUP_END)
- (clobber (match_scratch:SI 2))]
+ (clobber (match_scratch:SI 2))
+ (clobber (reg:BI REG_CC))]
"memory_operand (operands[0], SImode) || splitting_loops"
[(set (match_dup 2) (match_dup 0))
(set (match_dup 2) (plus:SI (match_dup 2) (const_int -1)))
diff --git a/gcc/config/darwin-driver.c b/gcc/config/darwin-driver.c
index 4f0c6ba..7fa80ab 100644
--- a/gcc/config/darwin-driver.c
+++ b/gcc/config/darwin-driver.c
@@ -281,6 +281,7 @@ darwin_driver_init (unsigned int *decoded_options_count,
const char *vers_string = NULL;
bool seen_version_min = false;
bool seen_sysroot_p = false;
+ bool noexport_p = true;
for (i = 1; i < *decoded_options_count; i++)
{
@@ -349,6 +350,13 @@ darwin_driver_init (unsigned int *decoded_options_count,
seen_sysroot_p = true;
break;
+ case OPT_Xlinker:
+ case OPT_Wl_:
+ gcc_checking_assert ((*decoded_options)[i].arg);
+ if (startswith ((*decoded_options)[i].arg, "-exported_symbol"))
+ noexport_p = false;
+ break;
+
default:
break;
}
@@ -474,4 +482,14 @@ darwin_driver_init (unsigned int *decoded_options_count,
&(*decoded_options)[*decoded_options_count - 1]);
}
}
+
+ if (noexport_p)
+ {
+ ++*decoded_options_count;
+ *decoded_options = XRESIZEVEC (struct cl_decoded_option,
+ *decoded_options,
+ *decoded_options_count);
+ generate_option (OPT_nodefaultexport, NULL, 1, CL_DRIVER,
+ &(*decoded_options)[*decoded_options_count - 1]);
+ }
}
diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c
index 204114c..c5ba792 100644
--- a/gcc/config/darwin.c
+++ b/gcc/config/darwin.c
@@ -3637,30 +3637,6 @@ darwin_fold_builtin (tree fndecl, int n_args, tree *argp,
void
darwin_rename_builtins (void)
{
- /* The system ___divdc3 routine in libSystem on darwin10 is not
- accurate to 1ulp, ours is, so we avoid ever using the system name
- for this routine and instead install a non-conflicting name that
- is accurate.
-
- When -ffast-math or -funsafe-math-optimizations is given, we can
- use the faster version. */
- if (!flag_unsafe_math_optimizations)
- {
- enum built_in_function dcode
- = (enum built_in_function)(BUILT_IN_COMPLEX_DIV_MIN
- + DCmode - MIN_MODE_COMPLEX_FLOAT);
- tree fn = builtin_decl_explicit (dcode);
- /* Fortran and c call TARGET_INIT_BUILTINS and
- TARGET_INIT_LIBFUNCS at different times, so we have to put a
- call into each to ensure that at least one of them is called
- after build_common_builtin_nodes. A better fix is to add a
- new hook to run after build_common_builtin_nodes runs. */
- if (fn)
- set_user_assembler_name (fn, "___ieee_divdc3");
- fn = builtin_decl_implicit (dcode);
- if (fn)
- set_user_assembler_name (fn, "___ieee_divdc3");
- }
}
/* Implementation for the TARGET_LIBC_HAS_FUNCTION hook. */
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 7ed01ef..8d8d402 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -378,6 +378,16 @@ extern GTY(()) int darwin_ms_struct;
%(link_ssp) \
%:version-compare(>< 10.6 10.7 mmacosx-version-min= -ld10-uwfef) \
%(link_gcc_c_sequence) \
+ %{!nodefaultexport:%{dylib|dynamiclib|bundle: \
+ %:version-compare(>= 10.11 asm_macosx_version_min= -U) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= ___emutls_get_address) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= -exported_symbol) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= ___emutls_get_address) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= -U) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= ___emutls_register_common) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= -exported_symbol) \
+ %:version-compare(>= 10.11 asm_macosx_version_min= ___emutls_register_common) \
+ }} \
}}}\
%{!r:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} %{F*} "\
DARWIN_PIE_SPEC \
@@ -404,14 +414,11 @@ extern GTY(()) int darwin_ms_struct;
/* Tell collect2 to run dsymutil for us as necessary. */
#define COLLECT_RUN_DSYMUTIL 1
-/* Fix PR47558 by linking against libSystem ahead of libgcc. See also
- PR 80556 and the fallout from this. */
-
+/* We only want one instance of %G, since libSystem (Darwin's -lc) does not
+ depend on libgcc. */
#undef LINK_GCC_C_SEQUENCE_SPEC
#define LINK_GCC_C_SEQUENCE_SPEC \
-"%{!static:%{!static-libgcc: \
- %:version-compare(>= 10.6 mmacosx-version-min= -lSystem) } } \
- %G %{!nolibc:%L}"
+ "%G %{!nolibc:%L} "
/* ld64 supports a sysroot, it just has a different name and there's no easy
way to check for it at config time. */
@@ -456,37 +463,62 @@ extern GTY(()) int darwin_ms_struct;
#define LIB_SPEC "%{!static:-lSystem}"
-/* Support -mmacosx-version-min by supplying different (stub) libgcc_s.dylib
- libraries to link against, and by not linking against libgcc_s on
- earlier-than-10.3.9. If we need exceptions, prior to 10.3.9, then we have
- to link the static eh lib, since there's no shared version on the system.
-
- Note that by default, except as above, -lgcc_eh is not linked against.
+/*
+ Note that by default, -lgcc_eh is not linked against.
This is because,in general, we need to unwind through system libraries that
are linked with the shared unwinder in libunwind (or libgcc_s for 10.4/5).
- The static version of the current libgcc unwinder (which differs from the
- implementation in libunwind.dylib on systems Darwin10 [10.6]+) can be used
- by specifying -static-libgcc.
-
- If libgcc_eh is linked against, it has to be before -lgcc, because it might
- need symbols from -lgcc. */
-
+ For -static-libgcc: < 10.6, use the unwinder in libgcc_eh (and find
+ the emultls impl. there too).
+
+ For -static-libgcc: >= 10.6, the unwinder *still* comes from libSystem and
+ we find the emutls impl from lemutls_w. In either case, the builtins etc.
+ are linked from -lgcc.
+
+ When we have specified shared-libgcc or any case that might require
+ exceptions, we pull the libgcc content (including emulated tls) from
+ -lgcc_s.1 in GCC and the unwinder from /usr/lib/libgcc_s.1 for < 10.6 and
+ libSystem for >= 10.6 respectively.
+ Otherwise, we just link the emutls/builtins from convenience libs.
+
+ If we need exceptions, prior to 10.3.9, then we have to link the static
+ eh lib, since there's no shared version on the system.
+
+ In all cases, libgcc_s.1 will be installed with the compiler, or any app
+ built using it, so we can link the builtins and emutls shared on all.
+
+ We have to work around that DYLD_XXXX are disabled in macOS 10.11+ which
+ means that any bootstrap trying to use a shared libgcc with a bumped SO-
+ name will fail. This means that we do not accept shared libgcc for these
+ versions.
+
+ For -static-libgcc: >= 10.6, the unwinder *still* comes from libSystem and
+ we find the emutls impl from lemutls_w. In either case, the builtins etc.
+ are linked from -lgcc.
+>
+ Otherwise, we just link the shared version of gcc_s.1.1 and pick up
+ exceptions:
+ * Prior to 10.3.9, then we have to link the static eh lib, since there
+ is no shared version on the system.
+ * from 10.3.9 to 10.5, from /usr/lib/libgcc_s.1.dylib
+ * from 10.6 onwards, from libSystem.dylib
+
+ In all cases, libgcc_s.1.1 will be installed with the compiler, or any app
+ built using it, so we can link the builtins and emutls shared on all.
+*/
#undef REAL_LIBGCC_SPEC
-#define REAL_LIBGCC_SPEC \
- "%{static-libgcc|static: -lgcc_eh -lgcc; \
- shared-libgcc|fexceptions|fobjc-exceptions|fgnu-runtime: \
- %:version-compare(!> 10.3.9 mmacosx-version-min= -lgcc_eh) \
- %:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \
- %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \
- %:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_ext.10.4) \
- %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \
- -lgcc ; \
- :%:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \
- %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \
- %:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_ext.10.4) \
- %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \
- -lgcc }"
+#define REAL_LIBGCC_SPEC \
+"%{static-libgcc|static: \
+ %:version-compare(!> 10.6 mmacosx-version-min= -lgcc_eh) \
+ %:version-compare(>= 10.6 mmacosx-version-min= -lemutls_w); \
+ shared-libgcc|fexceptions|fobjc-exceptions|fgnu-runtime: \
+ %:version-compare(!> 10.11 mmacosx-version-min= -lgcc_s.1.1) \
+ %:version-compare(>= 10.11 mmacosx-version-min= -lemutls_w) \
+ %:version-compare(!> 10.3.9 mmacosx-version-min= -lgcc_eh) \
+ %:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \
+ %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5); \
+ : -lemutls_w \
+ } -lgcc "
/* We specify crt0.o as -lcrt0.o so that ld will search the library path. */
diff --git a/gcc/config/darwin.opt b/gcc/config/darwin.opt
index d1d1f81..48d3aa9 100644
--- a/gcc/config/darwin.opt
+++ b/gcc/config/darwin.opt
@@ -233,6 +233,10 @@ no_dead_strip_inits_and_terms
Driver RejectNegative
(Obsolete) Current linkers never dead-strip these items, so the option is not needed.
+nodefaultexport
+Driver RejectNegative
+Do not add a default symbol exports to modules or dynamic libraries.
+
nofixprebinding
Driver RejectNegative
(Obsolete after 10.3.9) Set MH_NOPREFIXBINDING, in an executable.
diff --git a/gcc/config/i386/avx512fp16intrin.h b/gcc/config/i386/avx512fp16intrin.h
index 44c5e24..fe73e69 100644
--- a/gcc/config/i386/avx512fp16intrin.h
+++ b/gcc/config/i386/avx512fp16intrin.h
@@ -7162,6 +7162,45 @@ _mm512_set1_pch (_Float16 _Complex __A)
return (__m512h) _mm512_set1_ps (u.b);
}
+// intrinsics below are alias for f*mul_*ch
+#define _mm512_mul_pch(A, B) _mm512_fmul_pch ((A), (B))
+#define _mm512_mask_mul_pch(W, U, A, B) \
+ _mm512_mask_fmul_pch ((W), (U), (A), (B))
+#define _mm512_maskz_mul_pch(U, A, B) _mm512_maskz_fmul_pch ((U), (A), (B))
+#define _mm512_mul_round_pch(A, B, R) _mm512_fmul_round_pch ((A), (B), (R))
+#define _mm512_mask_mul_round_pch(W, U, A, B, R) \
+ _mm512_mask_fmul_round_pch ((W), (U), (A), (B), (R))
+#define _mm512_maskz_mul_round_pch(U, A, B, R) \
+ _mm512_maskz_fmul_round_pch ((U), (A), (B), (R))
+
+#define _mm512_cmul_pch(A, B) _mm512_fcmul_pch ((A), (B))
+#define _mm512_mask_cmul_pch(W, U, A, B) \
+ _mm512_mask_fcmul_pch ((W), (U), (A), (B))
+#define _mm512_maskz_cmul_pch(U, A, B) _mm512_maskz_fcmul_pch ((U), (A), (B))
+#define _mm512_cmul_round_pch(A, B, R) _mm512_fcmul_round_pch ((A), (B), (R))
+#define _mm512_mask_cmul_round_pch(W, U, A, B, R) \
+ _mm512_mask_fcmul_round_pch ((W), (U), (A), (B), (R))
+#define _mm512_maskz_cmul_round_pch(U, A, B, R) \
+ _mm512_maskz_fcmul_round_pch ((U), (A), (B), (R))
+
+#define _mm_mul_sch(A, B) _mm_fmul_sch ((A), (B))
+#define _mm_mask_mul_sch(W, U, A, B) _mm_mask_fmul_sch ((W), (U), (A), (B))
+#define _mm_maskz_mul_sch(U, A, B) _mm_maskz_fmul_sch ((U), (A), (B))
+#define _mm_mul_round_sch(A, B, R) _mm_fmul_round_sch ((A), (B), (R))
+#define _mm_mask_mul_round_sch(W, U, A, B, R) \
+ _mm_mask_fmul_round_sch ((W), (U), (A), (B), (R))
+#define _mm_maskz_mul_round_sch(U, A, B, R) \
+ _mm_maskz_fmul_round_sch ((U), (A), (B), (R))
+
+#define _mm_cmul_sch(A, B) _mm_fcmul_sch ((A), (B))
+#define _mm_mask_cmul_sch(W, U, A, B) _mm_mask_fcmul_sch ((W), (U), (A), (B))
+#define _mm_maskz_cmul_sch(U, A, B) _mm_maskz_fcmul_sch ((U), (A), (B))
+#define _mm_cmul_round_sch(A, B, R) _mm_fcmul_round_sch ((A), (B), (R))
+#define _mm_mask_cmul_round_sch(W, U, A, B, R) \
+ _mm_mask_fcmul_round_sch ((W), (U), (A), (B), (R))
+#define _mm_maskz_cmul_round_sch(U, A, B, R) \
+ _mm_maskz_fcmul_round_sch ((U), (A), (B), (R))
+
#ifdef __DISABLE_AVX512FP16__
#undef __DISABLE_AVX512FP16__
#pragma GCC pop_options
diff --git a/gcc/config/i386/avx512fp16vlintrin.h b/gcc/config/i386/avx512fp16vlintrin.h
index 11f34bb..fb6f692 100644
--- a/gcc/config/i386/avx512fp16vlintrin.h
+++ b/gcc/config/i386/avx512fp16vlintrin.h
@@ -3337,6 +3337,23 @@ _mm_set1_pch (_Float16 _Complex __A)
return (__m128h) _mm_set1_ps (u.b);
}
+// intrinsics below are alias for f*mul_*ch
+#define _mm_mul_pch(A, B) _mm_fmul_pch ((A), (B))
+#define _mm_mask_mul_pch(W, U, A, B) _mm_mask_fmul_pch ((W), (U), (A), (B))
+#define _mm_maskz_mul_pch(U, A, B) _mm_maskz_fmul_pch ((U), (A), (B))
+#define _mm256_mul_pch(A, B) _mm256_fmul_pch ((A), (B))
+#define _mm256_mask_mul_pch(W, U, A, B) \
+ _mm256_mask_fmul_pch ((W), (U), (A), (B))
+#define _mm256_maskz_mul_pch(U, A, B) _mm256_maskz_fmul_pch ((U), (A), (B))
+
+#define _mm_cmul_pch(A, B) _mm_fcmul_pch ((A), (B))
+#define _mm_mask_cmul_pch(W, U, A, B) _mm_mask_fcmul_pch ((W), (U), (A), (B))
+#define _mm_maskz_cmul_pch(U, A, B) _mm_maskz_fcmul_pch ((U), (A), (B))
+#define _mm256_cmul_pch(A, B) _mm256_fcmul_pch ((A), (B))
+#define _mm256_mask_cmul_pch(W, U, A, B) \
+ _mm256_mask_fcmul_pch ((W), (U), (A), (B))
+#define _mm256_maskz_cmul_pch(U, A, B) _mm256_maskz_fcmul_pch((U), (A), (B))
+
#ifdef __DISABLE_AVX512FP16VL__
#undef __DISABLE_AVX512FP16VL__
#pragma GCC pop_options
diff --git a/gcc/config/i386/constraints.md b/gcc/config/i386/constraints.md
index 87cceac..6b291a0 100644
--- a/gcc/config/i386/constraints.md
+++ b/gcc/config/i386/constraints.md
@@ -186,6 +186,11 @@
(and (match_operand 0 "memory_operand")
(match_test "constant_address_p (XEXP (op, 0))")))
+(define_memory_constraint "Bk"
+ "@internal TLS address that allows insn using non-integer registers."
+ (and (match_operand 0 "memory_operand")
+ (not (match_test "ix86_gpr_tls_address_pattern_p (op)"))))
+
(define_special_memory_constraint "Bn"
"@internal Memory operand without REX prefix."
(match_operand 0 "norex_memory_operand"))
diff --git a/gcc/config/i386/darwin.h b/gcc/config/i386/darwin.h
index 741f29a..e946a8b 100644
--- a/gcc/config/i386/darwin.h
+++ b/gcc/config/i386/darwin.h
@@ -25,37 +25,6 @@ along with GCC; see the file COPYING3. If not see
#undef DARWIN_X86
#define DARWIN_X86 1
-/* WORKAROUND pr80556:
- For x86_64 Darwin10 and later, the unwinder is in libunwind (redirected
- from libSystem). This doesn't use the keymgr (see keymgr.c) and therefore
- the calls that libgcc makes to obtain the KEYMGR_GCC3_DW2_OBJ_LIST are not
- updated to include new images, and might not even be valid for a single
- image.
- Therefore, for 64b exes at least, we must use the libunwind implementation,
- even when static-libgcc is specified. We put libSystem first so that
- unwinder symbols are satisfied from there.
- We default to 64b for single-arch builds, so apply this unconditionally. */
-#ifndef PR80556_WORKAROUND
-#define PR80556_WORKAROUND \
-" %:version-compare(>= 10.6 mmacosx-version-min= -lSystem) "
-#endif
-#undef REAL_LIBGCC_SPEC
-#define REAL_LIBGCC_SPEC \
- "%{static-libgcc|static: " \
- PR80556_WORKAROUND \
- " -lgcc_eh -lgcc; \
- shared-libgcc|fexceptions|fgnu-runtime: \
- %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_s.10.4) \
- %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \
- %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4) \
- %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \
- -lgcc ; \
- :%:version-compare(>< 10.3.9 10.5 mmacosx-version-min= -lgcc_s.10.4) \
- %:version-compare(>< 10.5 10.6 mmacosx-version-min= -lgcc_s.10.5) \
- %:version-compare(!> 10.5 mmacosx-version-min= -lgcc_ext.10.4) \
- %:version-compare(>= 10.5 mmacosx-version-min= -lgcc_ext.10.5) \
- -lgcc }"
-
/* Size of the Obj-C jump buffer. */
#define OBJC_JBLEN ((TARGET_64BIT) ? ((9 * 2) + 3 + 16) : (18))
diff --git a/gcc/config/i386/darwin32-biarch.h b/gcc/config/i386/darwin32-biarch.h
index 5470edf..ee15082 100644
--- a/gcc/config/i386/darwin32-biarch.h
+++ b/gcc/config/i386/darwin32-biarch.h
@@ -24,19 +24,6 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_64BIT_DEFAULT 0
#define TARGET_BI_ARCH 1
-/* WORKAROUND pr80556:
- For x86_64 Darwin10 and later, the unwinder is in libunwind (redirected
- from libSystem). This doesn't use the keymgr (see keymgr.c) and therefore
- the calls that libgcc makes to obtain the KEYMGR_GCC3_DW2_OBJ_LIST are not
- updated to include new images, and might not even be valid for a single
- image.
- Therefore, for 64b exes at least, we must use the libunwind implementation,
- even when static-libgcc is specified. We put libSystem first so that
- unwinder symbols are satisfied from there. */
-#undef PR80556_WORKAROUND
-#define PR80556_WORKAROUND \
-" %{m64:%:version-compare(>= 10.6 mmacosx-version-min= -lSystem)} "
-
#undef DARWIN_SUBARCH_SPEC
#define DARWIN_SUBARCH_SPEC DARWIN_ARCH_SPEC
diff --git a/gcc/config/i386/darwin64-biarch.h b/gcc/config/i386/darwin64-biarch.h
index f5bc3d6..d02f7fc 100644
--- a/gcc/config/i386/darwin64-biarch.h
+++ b/gcc/config/i386/darwin64-biarch.h
@@ -25,19 +25,6 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_64BIT_DEFAULT (OPTION_MASK_ISA_64BIT | OPTION_MASK_ABI_64)
#define TARGET_BI_ARCH 1
-/* WORKAROUND pr80556:
- For x86_64 Darwin10 and later, the unwinder is in libunwind (redirected
- from libSystem). This doesn't use the keymgr (see keymgr.c) and therefore
- the calls that libgcc makes to obtain the KEYMGR_GCC3_DW2_OBJ_LIST are not
- updated to include new images, and might not even be valid for a single
- image.
- Therefore, for 64b exes at least, we must use the libunwind implementation,
- even when static-libgcc is specified. We put libSystem first so that
- unwinder symbols are satisfied from there. */
-#undef PR80556_WORKAROUND
-#define PR80556_WORKAROUND \
-" %{!m32:%:version-compare(>= 10.6 mmacosx-version-min= -lSystem)} "
-
#undef DARWIN_SUBARCH_SPEC
#define DARWIN_SUBARCH_SPEC DARWIN_ARCH_SPEC
diff --git a/gcc/config/i386/i386-expand.c b/gcc/config/i386/i386-expand.c
index 3e4de64..0d5d1a0 100644
--- a/gcc/config/i386/i386-expand.c
+++ b/gcc/config/i386/i386-expand.c
@@ -23143,13 +23143,14 @@ void ix86_expand_atomic_fetch_op_loop (rtx target, rtx mem, rtx val,
bool doubleword)
{
rtx old_reg, new_reg, old_mem, success, oldval, new_mem;
- rtx_code_label *loop_label, *pause_label;
+ rtx_code_label *loop_label, *pause_label, *done_label;
machine_mode mode = GET_MODE (target);
old_reg = gen_reg_rtx (mode);
new_reg = old_reg;
loop_label = gen_label_rtx ();
pause_label = gen_label_rtx ();
+ done_label = gen_label_rtx ();
old_mem = copy_to_reg (mem);
emit_label (loop_label);
emit_move_insn (old_reg, old_mem);
@@ -23207,11 +23208,15 @@ void ix86_expand_atomic_fetch_op_loop (rtx target, rtx mem, rtx val,
GET_MODE (success), 1, loop_label,
profile_probability::guessed_never ());
+ emit_jump_insn (gen_jump (done_label));
+ emit_barrier ();
+
/* If mem is not expected, pause and loop back. */
emit_label (pause_label);
emit_insn (gen_pause ());
emit_jump_insn (gen_jump (loop_label));
emit_barrier ();
+ emit_label (done_label);
}
#include "gt-i386-expand.h"
diff --git a/gcc/config/i386/i386-options.c b/gcc/config/i386/i386-options.c
index feff258..a4da833 100644
--- a/gcc/config/i386/i386-options.c
+++ b/gcc/config/i386/i386-options.c
@@ -1443,8 +1443,11 @@ ix86_valid_target_attribute_p (tree fndecl,
/* Initialize func_options to the default before its target options can
be set. */
+ tree old_target = DECL_FUNCTION_SPECIFIC_TARGET (fndecl);
+ if (old_target == NULL_TREE)
+ old_target = target_option_default_node;
cl_target_option_restore (&func_options, &func_options_set,
- TREE_TARGET_OPTION (target_option_default_node));
+ TREE_TARGET_OPTION (old_target));
/* FLAGS == 1 is used for target_clones attribute. */
new_target
diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
index 04e4ad6..171d310 100644
--- a/gcc/config/i386/i386-opts.h
+++ b/gcc/config/i386/i386-opts.h
@@ -121,4 +121,11 @@ enum instrument_return {
instrument_return_nop5
};
+enum harden_sls {
+ harden_sls_none = 0,
+ harden_sls_return = 1 << 0,
+ harden_sls_indirect_branch = 1 << 1,
+ harden_sls_all = harden_sls_return | harden_sls_indirect_branch
+};
+
#endif
diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h
index 7e05510..1cd2197 100644
--- a/gcc/config/i386/i386-protos.h
+++ b/gcc/config/i386/i386-protos.h
@@ -243,6 +243,7 @@ extern unsigned int ix86_get_callcvt (const_tree);
#endif
extern rtx ix86_tls_module_base (void);
+extern bool ix86_gpr_tls_address_pattern_p (rtx);
extern bool ix86_tls_address_pattern_p (rtx);
extern rtx ix86_rewrite_tls_address (rtx);
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 73c4d51..10bfa0e 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -3665,7 +3665,7 @@ zero_all_vector_registers (HARD_REG_SET need_zeroed_hardregs)
return NULL;
for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if ((IN_RANGE (regno, FIRST_SSE_REG, LAST_SSE_REG)
+ if ((LEGACY_SSE_REGNO_P (regno)
|| (TARGET_64BIT
&& (REX_SSE_REGNO_P (regno)
|| (TARGET_AVX512F && EXT_REX_SSE_REGNO_P (regno)))))
@@ -5733,7 +5733,7 @@ static bool indirect_thunk_needed = false;
/* Bit masks of integer registers, which contain branch target, used
by call thunk functions. */
-static int indirect_thunks_used;
+static HARD_REG_SET indirect_thunks_used;
/* True if return thunk function is needed. */
static bool indirect_return_needed = false;
@@ -5914,6 +5914,8 @@ output_indirect_thunk (unsigned int regno)
}
fputs ("\tret\n", asm_out_file);
+ if ((ix86_harden_sls & harden_sls_return))
+ fputs ("\tint3\n", asm_out_file);
}
/* Output a funtion with a call and return thunk for indirect branch.
@@ -6030,8 +6032,7 @@ ix86_code_end (void)
for (regno = FIRST_REX_INT_REG; regno <= LAST_REX_INT_REG; regno++)
{
- unsigned int i = regno - FIRST_REX_INT_REG + LAST_INT_REG + 1;
- if ((indirect_thunks_used & (1 << i)))
+ if (TEST_HARD_REG_BIT (indirect_thunks_used, regno))
output_indirect_thunk_function (indirect_thunk_prefix_none,
regno, false);
}
@@ -6041,7 +6042,7 @@ ix86_code_end (void)
char name[32];
tree decl;
- if ((indirect_thunks_used & (1 << regno)))
+ if (TEST_HARD_REG_BIT (indirect_thunks_used, regno))
output_indirect_thunk_function (indirect_thunk_prefix_none,
regno, false);
@@ -6116,7 +6117,7 @@ ix86_code_end (void)
xops[0] = gen_rtx_REG (Pmode, regno);
xops[1] = gen_rtx_MEM (Pmode, stack_pointer_rtx);
output_asm_insn ("mov%z0\t{%1, %0|%0, %1}", xops);
- output_asm_insn ("%!ret", NULL);
+ fputs ("\tret\n", asm_out_file);
final_end_function ();
init_insn_lengths ();
free_after_compilation (cfun);
@@ -11627,6 +11628,36 @@ legitimize_tls_address (rtx x, enum tls_model model, bool for_mov)
return dest;
}
+/* Return true if the TLS address requires insn using integer registers.
+ It's used to prevent KMOV/VMOV in TLS code sequences which require integer
+ MOV instructions, refer to PR103275. */
+bool
+ix86_gpr_tls_address_pattern_p (rtx mem)
+{
+ gcc_assert (MEM_P (mem));
+
+ rtx addr = XEXP (mem, 0);
+ subrtx_var_iterator::array_type array;
+ FOR_EACH_SUBRTX_VAR (iter, array, addr, ALL)
+ {
+ rtx op = *iter;
+ if (GET_CODE (op) == UNSPEC)
+ switch (XINT (op, 1))
+ {
+ case UNSPEC_GOTNTPOFF:
+ return true;
+ case UNSPEC_TPOFF:
+ if (!TARGET_64BIT)
+ return true;
+ break;
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
+
/* Return true if OP refers to a TLS address. */
bool
ix86_tls_address_pattern_p (rtx op)
@@ -15981,9 +16012,14 @@ ix86_output_jmp_thunk_or_indirect (const char *thunk_name, const int regno)
{
if (thunk_name != NULL)
{
+ if (REX_INT_REGNO_P (regno)
+ && ix86_indirect_branch_cs_prefix)
+ fprintf (asm_out_file, "\tcs\n");
fprintf (asm_out_file, "\tjmp\t");
assemble_name (asm_out_file, thunk_name);
putc ('\n', asm_out_file);
+ if ((ix86_harden_sls & harden_sls_indirect_branch))
+ fputs ("\tint3\n", asm_out_file);
}
else
output_indirect_thunk (regno);
@@ -16014,12 +16050,8 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
!= indirect_branch_thunk_inline)
{
if (cfun->machine->indirect_branch_type == indirect_branch_thunk)
- {
- int i = regno;
- if (i >= FIRST_REX_INT_REG)
- i -= (FIRST_REX_INT_REG - LAST_INT_REG - 1);
- indirect_thunks_used |= 1 << i;
- }
+ SET_HARD_REG_BIT (indirect_thunks_used, regno);
+
indirect_thunk_name (thunk_name_buf, regno, need_prefix, false);
thunk_name = thunk_name_buf;
}
@@ -16032,6 +16064,9 @@ ix86_output_indirect_branch_via_reg (rtx call_op, bool sibcall_p)
{
if (thunk_name != NULL)
{
+ if (REX_INT_REGNO_P (regno)
+ && ix86_indirect_branch_cs_prefix)
+ fprintf (asm_out_file, "\tcs\n");
fprintf (asm_out_file, "\tcall\t");
assemble_name (asm_out_file, thunk_name);
putc ('\n', asm_out_file);
@@ -16206,10 +16241,10 @@ ix86_output_indirect_jmp (rtx call_op)
gcc_unreachable ();
ix86_output_indirect_branch (call_op, "%0", true);
- return "";
}
else
- return "%!jmp\t%A0";
+ output_asm_insn ("%!jmp\t%A0", &call_op);
+ return (ix86_harden_sls & harden_sls_indirect_branch) ? "int3" : "";
}
/* Output return instrumentation for current function if needed. */
@@ -16277,10 +16312,8 @@ ix86_output_function_return (bool long_p)
return "";
}
- if (!long_p)
- return "%!ret";
-
- return "rep%; ret";
+ output_asm_insn (long_p ? "rep%; ret" : "ret", nullptr);
+ return (ix86_harden_sls & harden_sls_return) ? "int3" : "";
}
/* Output indirect function return. RET_OP is the function return
@@ -16307,7 +16340,7 @@ ix86_output_indirect_function_return (rtx ret_op)
if (need_thunk)
{
indirect_return_via_cx = true;
- indirect_thunks_used |= 1 << CX_REG;
+ SET_HARD_REG_BIT (indirect_thunks_used, CX_REG);
}
fprintf (asm_out_file, "\tjmp\t");
assemble_name (asm_out_file, thunk_name);
@@ -16375,7 +16408,12 @@ ix86_output_call_insn (rtx_insn *insn, rtx call_op)
if (output_indirect_p && !direct_p)
ix86_output_indirect_branch (call_op, xasm, true);
else
- output_asm_insn (xasm, &call_op);
+ {
+ output_asm_insn (xasm, &call_op);
+ if (!direct_p
+ && (ix86_harden_sls & harden_sls_indirect_branch))
+ return "int3";
+ }
return "";
}
@@ -19089,15 +19127,13 @@ ix86_register_priority (int hard_regno)
return 0;
if (hard_regno == BP_REG)
return 1;
- /* New x86-64 int registers result in bigger code size. Discourage
- them. */
- if (IN_RANGE (hard_regno, FIRST_REX_INT_REG, LAST_REX_INT_REG))
+ /* New x86-64 int registers result in bigger code size. Discourage them. */
+ if (REX_INT_REGNO_P (hard_regno))
return 2;
- /* New x86-64 SSE registers result in bigger code size. Discourage
- them. */
- if (IN_RANGE (hard_regno, FIRST_REX_SSE_REG, LAST_REX_SSE_REG))
+ /* New x86-64 SSE registers result in bigger code size. Discourage them. */
+ if (REX_SSE_REGNO_P (hard_regno))
return 2;
- if (IN_RANGE (hard_regno, FIRST_EXT_REX_SSE_REG, LAST_EXT_REX_SSE_REG))
+ if (EXT_REX_SSE_REGNO_P (hard_regno))
return 1;
/* Usage of AX register results in smaller code. Prefer it. */
if (hard_regno == AX_REG)
@@ -19974,9 +20010,8 @@ ix86_hard_regno_call_part_clobbered (unsigned int abi_id, unsigned int regno,
/* Special ABI for vzeroupper which only clobber higher part of sse regs. */
if (abi_id == ABI_VZEROUPPER)
return (GET_MODE_SIZE (mode) > 16
- && ((TARGET_64BIT
- && (IN_RANGE (regno, FIRST_REX_SSE_REG, LAST_REX_SSE_REG)))
- || (IN_RANGE (regno, FIRST_SSE_REG, LAST_SSE_REG))));
+ && ((TARGET_64BIT && REX_SSE_REGNO_P (regno))
+ || LEGACY_SSE_REGNO_P (regno)));
return SSE_REGNO_P (regno) && GET_MODE_SIZE (mode) > 16;
}
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index e35c79c..2fda1e0 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -1409,10 +1409,13 @@ enum reg_class
#define SSE_REG_P(X) (REG_P (X) && SSE_REGNO_P (REGNO (X)))
#define SSE_REGNO_P(N) \
- (IN_RANGE ((N), FIRST_SSE_REG, LAST_SSE_REG) \
+ (LEGACY_SSE_REGNO_P (N) \
|| REX_SSE_REGNO_P (N) \
|| EXT_REX_SSE_REGNO_P (N))
+#define LEGACY_SSE_REGNO_P(N) \
+ IN_RANGE ((N), FIRST_SSE_REG, LAST_SSE_REG)
+
#define REX_SSE_REGNO_P(N) \
IN_RANGE ((N), FIRST_REX_SSE_REG, LAST_REX_SSE_REG)
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 7394906..03d401e 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -2164,9 +2164,9 @@
(define_insn "*movdi_internal"
[(set (match_operand:DI 0 "nonimmediate_operand"
- "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k ,*r,*m,*k")
+ "=r ,o ,r,r ,r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,m,?r ,?*Yd,?r,?*v,?*y,?*x,*k,*k ,*r,*m,*k")
(match_operand:DI 1 "general_operand"
- "riFo,riF,Z,rem,i,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*km,*k,*k,CBC"))]
+ "riFo,riF,Z,rem,i,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,v,*Yd,r ,*v,r ,*x ,*y ,*r,*kBk,*k,*k,CBC"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& ix86_hardreg_mov_ok (operands[0], operands[1])"
{
@@ -2385,9 +2385,9 @@
(define_insn "*movsi_internal"
[(set (match_operand:SI 0 "nonimmediate_operand"
- "=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*rm,*k")
+ "=r,m ,*y,*y,?*y,?m,?r,?*y,*v,*v,*v,m ,?r,?*v,*k,*k ,*rm,*k")
(match_operand:SI 1 "general_operand"
- "g ,re,C ,*y,m ,*y,*y,r ,C ,*v,m ,*v,*v,r ,*r,*km,*k ,CBC"))]
+ "g ,re,C ,*y,Bk ,*y,*y,r ,C ,*v,Bk,*v,*v,r ,*r,*kBk,*k ,CBC"))]
"!(MEM_P (operands[0]) && MEM_P (operands[1]))
&& ix86_hardreg_mov_ok (operands[0], operands[1])"
{
@@ -5491,7 +5491,7 @@
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (PLUS, <DWI>mode, operands)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CCC FLAGS_REG)
(compare:CCC
(plus:DWIH (match_dup 1) (match_dup 2))
@@ -6300,7 +6300,7 @@
(plus:<DWI> (match_dup 1) (match_dup 2)))]
"ix86_binary_operator_ok (PLUS, <DWI>mode, operands)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CCC FLAGS_REG)
(compare:CCC
(plus:DWIH (match_dup 1) (match_dup 2))
@@ -6347,7 +6347,7 @@
&& CONST_SCALAR_INT_P (operands[2])
&& rtx_equal_p (operands[2], operands[3])"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CCC FLAGS_REG)
(compare:CCC
(plus:DWIH (match_dup 1) (match_dup 2))
@@ -6641,7 +6641,7 @@
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CC FLAGS_REG)
(compare:CC (match_dup 1) (match_dup 2)))
(set (match_dup 0)
@@ -6817,7 +6817,7 @@
(minus:<DWI> (match_dup 1) (match_dup 2)))]
"ix86_binary_operator_ok (MINUS, <MODE>mode, operands)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CC FLAGS_REG)
(compare:CC (match_dup 1) (match_dup 2)))
(set (match_dup 0)
@@ -6862,7 +6862,7 @@
&& CONST_SCALAR_INT_P (operands[2])
&& rtx_equal_p (operands[2], operands[3])"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CC FLAGS_REG)
(compare:CC (match_dup 1) (match_dup 2)))
(set (match_dup 0)
@@ -7542,7 +7542,7 @@
(plus:<DWI> (match_dup 1) (match_dup 2)))]
"ix86_binary_operator_ok (PLUS, <DWI>mode, operands)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (reg:CCC FLAGS_REG)
(compare:CCC
(plus:DWIH (match_dup 1) (match_dup 2))
@@ -9000,7 +9000,7 @@
(clobber (reg:CC FLAGS_REG))]
"!optimize_function_for_size_p (cfun)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 1) (match_dup 4))
(parallel [(set (match_dup 0)
@@ -10515,7 +10515,7 @@
(clobber (reg:CC FLAGS_REG))]
"ix86_unary_operator_ok (NEG, <DWI>mode, operands)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel
[(set (reg:CCC FLAGS_REG)
(ne:CCC (match_dup 1) (const_int 0)))
@@ -14705,7 +14705,7 @@
[(simple_return)
(use (match_operand:SI 0 "const_int_operand"))]
"reload_completed"
- "%!ret\t%0"
+ "ret\t%0"
"&& cfun->machine->function_return_type != indirect_branch_keep"
[(const_int 0)]
"ix86_split_simple_return_pop_internal (operands[0]); DONE;"
@@ -16908,7 +16908,7 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && TARGET_GNU2_TLS"
"#"
- ""
+ "&& 1"
[(set (match_dup 0) (match_dup 4))]
{
operands[4] = can_create_pseudo_p () ? gen_reg_rtx (ptr_mode) : operands[0];
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 46fad3c..3e67c53 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -1076,6 +1076,10 @@ Enum(indirect_branch) String(thunk-inline) Value(indirect_branch_thunk_inline)
EnumValue
Enum(indirect_branch) String(thunk-extern) Value(indirect_branch_thunk_extern)
+mindirect-branch-cs-prefix
+Target Var(ix86_indirect_branch_cs_prefix) Init(0)
+Add CS prefix to call and jmp to indirect thunk with branch target in r8-r15 registers.
+
mindirect-branch-register
Target Var(ix86_indirect_branch_register) Init(0)
Force indirect call and jump via register.
@@ -1117,6 +1121,26 @@ mrecord-return
Target Var(ix86_flag_record_return) Init(0)
Generate a __return_loc section pointing to all return instrumentation code.
+mharden-sls=
+Target RejectNegative Joined Enum(harden_sls) Var(ix86_harden_sls) Init(harden_sls_none)
+Generate code to mitigate against straight line speculation.
+
+Enum
+Name(harden_sls) Type(enum harden_sls)
+Known choices for mitigation against straight line speculation with -mharden-sls=:
+
+EnumValue
+Enum(harden_sls) String(none) Value(harden_sls_none)
+
+EnumValue
+Enum(harden_sls) String(return) Value(harden_sls_return)
+
+EnumValue
+Enum(harden_sls) String(indirect-branch) Value(harden_sls_indirect_branch)
+
+EnumValue
+Enum(harden_sls) String(all) Value(harden_sls_all)
+
mavx512bf16
Target Mask(ISA2_AVX512BF16) Var(ix86_isa_flags2) Save
Support MMX, SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AVX, AVX2, AVX512F and
diff --git a/gcc/config/i386/x86-tune-costs.h b/gcc/config/i386/x86-tune-costs.h
index dd5563d..60d50c9 100644
--- a/gcc/config/i386/x86-tune-costs.h
+++ b/gcc/config/i386/x86-tune-costs.h
@@ -1903,7 +1903,7 @@ struct processor_costs skylake_cost = {
{6, 6, 6}, /* cost of storing integer registers */
{6, 6, 6, 10, 20}, /* cost of loading SSE register
in 32bit, 64bit, 128bit, 256bit and 512bit */
- {8, 8, 8, 12, 24}, /* cost of storing SSE register
+ {8, 8, 8, 8, 16}, /* cost of storing SSE register
in 32bit, 64bit, 128bit, 256bit and 512bit */
{6, 6, 6, 10, 20}, /* cost of unaligned loads. */
{8, 8, 8, 8, 16}, /* cost of unaligned stores. */
@@ -2029,7 +2029,7 @@ struct processor_costs icelake_cost = {
{6, 6, 6}, /* cost of storing integer registers */
{6, 6, 6, 10, 20}, /* cost of loading SSE register
in 32bit, 64bit, 128bit, 256bit and 512bit */
- {8, 8, 8, 12, 24}, /* cost of storing SSE register
+ {8, 8, 8, 8, 16}, /* cost of storing SSE register
in 32bit, 64bit, 128bit, 256bit and 512bit */
{6, 6, 6, 10, 20}, /* cost of unaligned loads. */
{8, 8, 8, 8, 16}, /* cost of unaligned stores. */
diff --git a/gcc/config/rs6000/driver-rs6000.c b/gcc/config/rs6000/driver-rs6000.c
index e23c445..4de373d 100644
--- a/gcc/config/rs6000/driver-rs6000.c
+++ b/gcc/config/rs6000/driver-rs6000.c
@@ -418,6 +418,9 @@ detect_processor_aix (void)
case 0x20000:
return "power9";
+ case 0x40000:
+ return "power10";
+
default:
return "powerpc";
}
diff --git a/gcc/config/rs6000/emmintrin.h b/gcc/config/rs6000/emmintrin.h
index 32ad72b..4125b12 100644
--- a/gcc/config/rs6000/emmintrin.h
+++ b/gcc/config/rs6000/emmintrin.h
@@ -2189,27 +2189,37 @@ extern __inline __m128i __attribute__((__gnu_inline__, __always_inline__, __arti
_mm_sad_epu8 (__m128i __A, __m128i __B)
{
__v16qu a, b;
- __v16qu vmin, vmax, vabsdiff;
+ __v16qu vabsdiff;
__v4si vsum;
const __v4su zero = { 0, 0, 0, 0 };
__v4si result;
a = (__v16qu) __A;
b = (__v16qu) __B;
- vmin = vec_min (a, b);
- vmax = vec_max (a, b);
+#ifndef _ARCH_PWR9
+ __v16qu vmin = vec_min (a, b);
+ __v16qu vmax = vec_max (a, b);
vabsdiff = vec_sub (vmax, vmin);
+#else
+ vabsdiff = vec_absd (a, b);
+#endif
/* Sum four groups of bytes into integers. */
vsum = (__vector signed int) vec_sum4s (vabsdiff, zero);
+#ifdef __LITTLE_ENDIAN__
+ /* Sum across four integers with two integer results. */
+ asm ("vsum2sws %0,%1,%2" : "=v" (result) : "v" (vsum), "v" (zero));
+ /* Note: vec_sum2s could be used here, but on little-endian, vector
+ shifts are added that are not needed for this use-case.
+ A vector shift to correctly position the 32-bit integer results
+ (currently at [0] and [2]) to [1] and [3] would then need to be
+ swapped back again since the desired results are two 64-bit
+ integers ([1]|[0] and [3]|[2]). Thus, no shift is performed. */
+#else
/* Sum across four integers with two integer results. */
result = vec_sum2s (vsum, (__vector signed int) zero);
/* Rotate the sums into the correct position. */
-#ifdef __LITTLE_ENDIAN__
- result = vec_sld (result, result, 4);
-#else
result = vec_sld (result, result, 6);
#endif
- /* Rotate the sums into the correct position. */
return (__m128i) result;
}
diff --git a/gcc/config/rs6000/mma.md b/gcc/config/rs6000/mma.md
index 1990a21..fa08160 100644
--- a/gcc/config/rs6000/mma.md
+++ b/gcc/config/rs6000/mma.md
@@ -338,8 +338,11 @@
DONE;
})
+;; We cannot update the two output registers atomically, so mark the output
+;; as an early clobber so we don't accidentally clobber the input operands. */
+
(define_insn_and_split "*vsx_assemble_pair"
- [(set (match_operand:OO 0 "vsx_register_operand" "=wa")
+ [(set (match_operand:OO 0 "vsx_register_operand" "=&wa")
(unspec:OO [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
(match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")]
UNSPEC_MMA_ASSEMBLE))]
@@ -404,8 +407,11 @@
DONE;
})
+;; We cannot update the four output registers atomically, so mark the output
+;; as an early clobber so we don't accidentally clobber the input operands. */
+
(define_insn_and_split "*mma_assemble_acc"
- [(set (match_operand:XO 0 "fpr_reg_operand" "=d")
+ [(set (match_operand:XO 0 "fpr_reg_operand" "=&d")
(unspec:XO [(match_operand:V16QI 1 "mma_assemble_input_operand" "mwa")
(match_operand:V16QI 2 "mma_assemble_input_operand" "mwa")
(match_operand:V16QI 3 "mma_assemble_input_operand" "mwa")
diff --git a/gcc/config/rs6000/predicates.md b/gcc/config/rs6000/predicates.md
index 956e42b..f216ffd 100644
--- a/gcc/config/rs6000/predicates.md
+++ b/gcc/config/rs6000/predicates.md
@@ -1086,7 +1086,9 @@
(match_test "(DEFAULT_ABI != ABI_AIX || SYMBOL_REF_FUNCTION_P (op))
&& (SYMBOL_REF_LOCAL_P (op)
|| (op == XEXP (DECL_RTL (current_function_decl), 0)
- && !decl_replaceable_p (current_function_decl)))
+ && !decl_replaceable_p (current_function_decl,
+ opt_for_fn (current_function_decl,
+ flag_semantic_interposition))))
&& !((DEFAULT_ABI == ABI_AIX
|| DEFAULT_ABI == ABI_ELFv2)
&& (SYMBOL_REF_EXTERNAL_P (op)
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 4debdcd..c4f92bd 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -1003,7 +1003,7 @@
(match_operand:GPR 2 "memory_operand"))
(set (reg CC_REGNUM)
(compare (match_dup 0) (match_operand:GPR 1 "const0_operand")))]
- "s390_match_ccmode(insn, CCSmode) && TARGET_EXTIMM
+ "s390_match_ccmode (peep2_next_insn (1), CCSmode) && TARGET_EXTIMM
&& GENERAL_REG_P (operands[0])
&& satisfies_constraint_T (operands[2])
&& !contains_constant_pool_address_p (operands[2])"
diff --git a/gcc/config/visium/visium.md b/gcc/config/visium/visium.md
index 83ccf08..ca2234b 100644
--- a/gcc/config/visium/visium.md
+++ b/gcc/config/visium/visium.md
@@ -792,7 +792,7 @@
(match_operand:QHI 2 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, <MODE>mode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(plus:QHI (match_dup 1) (match_dup 2)))
(clobber (reg:CC R_FLAGS))])]
@@ -850,7 +850,7 @@
(match_operand:SI 2 "add_operand" " L,r,J")))]
"ok_for_simple_arith_logic_operands (operands, SImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(plus:SI (match_dup 1) (match_dup 2)))
(clobber (reg:CC R_FLAGS))])]
@@ -912,7 +912,7 @@
(match_operand:DI 2 "add_operand" " L,J, r")))]
"ok_for_simple_arith_logic_operands (operands, DImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(const_int 0)]
{
visium_split_double_add (PLUS, operands[0], operands[1], operands[2]);
@@ -1007,7 +1007,7 @@
(match_operand:QHI 2 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, <MODE>mode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(minus:QHI (match_dup 1) (match_dup 2)))
(clobber (reg:CC R_FLAGS))])]
@@ -1064,7 +1064,7 @@
(match_operand:SI 2 "add_operand" " L,r, J")))]
"ok_for_simple_arith_logic_operands (operands, SImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(minus:SI (match_dup 1) (match_dup 2)))
(clobber (reg:CC R_FLAGS))])]
@@ -1125,7 +1125,7 @@
(match_operand:DI 2 "add_operand" " L,J, r")))]
"ok_for_simple_arith_logic_operands (operands, DImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(const_int 0)]
{
visium_split_double_add (MINUS, operands[0], operands[1], operands[2]);
@@ -1209,7 +1209,7 @@
(neg:I (match_operand:I 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, <MODE>mode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0) (neg:I (match_dup 1)))
(clobber (reg:CC R_FLAGS))])]
""
@@ -1253,7 +1253,7 @@
(neg:DI (match_operand:DI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, DImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(const_int 0)]
{
visium_split_double_add (MINUS, operands[0], const0_rtx, operands[1]);
@@ -1415,7 +1415,7 @@
(match_operand:I 2 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, <MODE>mode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(and:I (match_dup 1) (match_dup 2)))
(clobber (reg:CC R_FLAGS))])]
@@ -1453,7 +1453,7 @@
(match_operand:I 2 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, <MODE>mode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(ior:I (match_dup 1) (match_dup 2)))
(clobber (reg:CC R_FLAGS))])]
@@ -1491,7 +1491,7 @@
(match_operand:I 2 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, <MODE>mode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(xor:I (match_dup 1) (match_dup 2)))
(clobber (reg:CC R_FLAGS))])]
@@ -1527,7 +1527,7 @@
(not:I (match_operand:I 1 "reg_or_0_operand" "rO")))]
"ok_for_simple_arith_logic_operands (operands, <MODE>mode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0) (not:I (match_dup 1)))
(clobber (reg:CC R_FLAGS))])]
""
@@ -1563,7 +1563,7 @@
(match_operand:QI 2 "reg_or_shift_operand" "r,K")))]
"ok_for_simple_arith_logic_operands (operands, <MODE>mode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(ashift:I (match_dup 1) (match_dup 2)))
(clobber (reg:CC R_FLAGS))])]
@@ -1622,7 +1622,7 @@
(match_operand:QI 2 "reg_or_shift_operand" "r,K")))]
"ok_for_simple_arith_logic_operands (operands, <MODE>mode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(ashiftrt:I (match_dup 1) (match_dup 2)))
(clobber (reg:CC R_FLAGS))])]
@@ -1683,7 +1683,7 @@
(match_operand:QI 2 "reg_or_shift_operand" "r,K")))]
"ok_for_simple_arith_logic_operands (operands, <MODE>mode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(lshiftrt:I (match_dup 1) (match_dup 2)))
(clobber (reg:CC R_FLAGS))])]
@@ -1740,7 +1740,7 @@
(truncate:QI (match_operand:HI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, QImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0) (truncate:QI (match_dup 1)))
(clobber (reg:CC R_FLAGS))])]
""
@@ -1764,7 +1764,7 @@
(truncate:HI (match_operand:SI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, HImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0) (truncate:HI (match_dup 1)))
(clobber (reg:CC R_FLAGS))])]
""
@@ -1788,7 +1788,7 @@
(truncate:SI (match_operand:DI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, SImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0) (truncate:SI (match_dup 1)))
(clobber (reg:CC R_FLAGS))])]
""
@@ -1822,7 +1822,7 @@
(sign_extend:HI (match_operand:QI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, HImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0) (sign_extend:HI (match_dup 1)))
(clobber (reg:CC R_FLAGS))])]
""
@@ -1846,7 +1846,7 @@
(sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, SImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
(clobber (reg:CC R_FLAGS))])]
""
@@ -1870,7 +1870,7 @@
(sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, SImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_operand:SI 0 "register_operand" "")
(sign_extend:SI (match_operand:HI 1 "register_operand" "")))
(clobber (reg:CC R_FLAGS))])]
@@ -1895,7 +1895,7 @@
(sign_extend:DI (match_operand:SI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, DImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 3) (match_dup 1))
(clobber (reg:CC R_FLAGS))])
(parallel [(set (match_dup 2)
@@ -1931,7 +1931,7 @@
(zero_extend:HI (match_operand:QI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, HImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(ashift:HI (match_dup 2) (const_int 8)))
(clobber (reg:CC R_FLAGS))])
@@ -1953,7 +1953,7 @@
(zero_extend:SI (match_operand:QI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, SImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 0)
(ashift:SI (match_dup 2) (const_int 24)))
(clobber (reg:CC R_FLAGS))])
@@ -1982,7 +1982,7 @@
(zero_extend:DI (match_operand:SI 1 "register_operand" "r")))]
"ok_for_simple_arith_logic_operands (operands, DImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(parallel [(set (match_dup 3) (match_dup 1))
(clobber (reg:CC R_FLAGS))])
(set (match_dup 2) (const_int 0))]
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index cdf22f1..e0bf720 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -779,7 +779,7 @@
"register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 1) (match_dup 3))]
{
@@ -1053,7 +1053,7 @@
"register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode)"
"#"
- "reload_completed"
+ "&& reload_completed"
[(set (match_dup 0) (match_dup 2))
(set (match_dup 1) (match_dup 3))]
{
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 61ce629..205416f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,131 @@
+2021-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/101180
+ * pt.c (apply_late_template_attributes): Temporarily override
+ current_optimize_pragma, optimization_current_node,
+ current_target_pragma and scope_chain->omp_declare_target_attribute,
+ so that cplus_decl_attributes doesn't add implicit attributes.
+
+2021-11-19 Martin Sebor <msebor@redhat.com>
+
+ PR c++/33925
+ PR c/102867
+ * typeck.c (warn_for_null_address): Suppress warnings for code
+ resulting from macro expansion.
+
+2021-11-19 Martin Liska <mliska@suse.cz>
+
+ Revert:
+ 2021-11-19 Martin Liska <mliska@suse.cz>
+
+ * parser.c (add_debug_begin_stmt): Use option directly.
+
+2021-11-19 Patrick Palka <ppalka@redhat.com>
+
+ * tree.c (cp_walk_subtrees) <case *_CAST_EXPR>: Don't explicitly
+ walk the operands.
+
+2021-11-19 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/94376
+ * lambda.c (lambda_capture_field_type): Simplify by handling the
+ is_this case first. When capturing by-value a capture proxy,
+ consider the type of the corresponding field instead.
+
+2021-11-19 Richard Biener <rguenther@suse.de>
+
+ PR c++/103326
+ * pt.c (tsubst_copy): Handle VECTOR_CST.
+
+2021-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70796
+ * cp-gimplify.c (cp_gimplify_arg): New function.
+ (cp_gimplify_expr): Use cp_gimplify_arg instead of gimplify_arg,
+ pass true as last argument to it if there are any following
+ arguments in strong evaluation order with side-effects.
+
+2021-11-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/19808
+ PR c++/96121
+ * init.c (perform_member_init): Remove a forward declaration.
+ Walk the initializer using find_uninit_fields_r. New parameter
+ to track uninitialized fields. If a member is initialized,
+ remove it from the hash set.
+ (perform_target_ctor): Return the initializer.
+ (struct find_uninit_data): New class.
+ (find_uninit_fields_r): New function.
+ (find_uninit_fields): New function.
+ (emit_mem_initializers): Keep and initialize a set holding fields
+ that are not initialized. When handling delegating constructors,
+ walk the constructor tree using find_uninit_fields_r. Also when
+ initializing base clases. Pass uninitialized down to
+ perform_member_init.
+
+2021-11-19 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/103198
+ * pt.c (any_template_parm_r): Walk the TREE_TYPE of a dummy
+ object.
+
+2021-11-18 Marek Polacek <polacek@redhat.com>
+
+ PR c++/103049
+ * semantics.c (finish_compound_literal): Accept C++23 auto{x}.
+ * typeck2.c (build_functional_cast_1): Accept C++23 auto(x).
+
+2021-11-18 Patrick Palka <ppalka@redhat.com>
+
+ * pt.c (tsubst_copy_and_build) <case CALL_EXPR>: Disable the
+ -fpermissive fallback for C++20 template-id ADL, but keep the
+ diagnostic.
+
+2021-11-18 Jan Hubicka <hubicka@ucw.cz>
+
+ * decl.c (finish_function): Update use of decl_replaceable_p.
+
+2021-11-18 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/99911
+ * pt.c (tsubst_copy_and_build) <case CALL_EXPR>: Don't diagnose
+ name lookup failure if the arguments to an unresolved template
+ name are still dependent.
+
+2021-11-18 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102670
+ * pt.c (tsubst_copy_and_build) <case CALL_EXPR>: When looking
+ for an identifier callee in the koenig_p case, also look through
+ TEMPLATE_ID_EXPR. Use tsubst_copy to substitute through the
+ template arguments of the template-id.
+
+2021-11-18 Matthias Kretz <m.kretz@gsi.de>
+
+ * constexpr.c (cxx_eval_constant_expression): Handle PAREN_EXPR
+ via cxx_eval_constant_expression.
+ * cp-objcp-common.c (names_builtin_p): Handle
+ RID_BUILTIN_ASSOC_BARRIER.
+ * cp-tree.h: Adjust TREE_LANG_FLAG documentation to include
+ PAREN_EXPR in REF_PARENTHESIZED_P.
+ (REF_PARENTHESIZED_P): Add PAREN_EXPR.
+ * parser.c (cp_parser_postfix_expression): Handle
+ RID_BUILTIN_ASSOC_BARRIER.
+ * pt.c (tsubst_copy_and_build): If the PAREN_EXPR is not a
+ parenthesized initializer, build a new PAREN_EXPR.
+ * semantics.c (force_paren_expr): Simplify conditionals. Set
+ REF_PARENTHESIZED_P on PAREN_EXPR.
+ (maybe_undo_parenthesized_ref): Test PAREN_EXPR for
+ REF_PARENTHESIZED_P.
+
+2021-11-18 Martin Liska <mliska@suse.cz>
+
+ * parser.c (add_debug_begin_stmt): Use option directly.
+
+2021-11-16 Jason Merrill <jason@redhat.com>
+
+ * ptree.c (cxx_print_xnode): Handle PTRMEM_CST.
+
2021-11-15 Jason Merrill <jason@redhat.com>
* cp-tree.h (struct lang_decl_fn): Add implicit_constexpr.
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 69d9d3d..d66a565 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -6901,6 +6901,14 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t,
non_constant_p, overflow_p);
break;
+ case PAREN_EXPR:
+ gcc_assert (!REF_PARENTHESIZED_P (t));
+ /* A PAREN_EXPR resulting from __builtin_assoc_barrier has no effect in
+ constant expressions since it's unaffected by -fassociative-math. */
+ r = cxx_eval_constant_expression (ctx, TREE_OPERAND (t, 0), lval,
+ non_constant_p, overflow_p);
+ break;
+
case NOP_EXPR:
if (REINTERPRET_CAST_P (t))
{
@@ -8678,6 +8686,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
case OMP_SINGLE:
case OMP_SECTION:
case OMP_MASTER:
+ case OMP_MASKED:
case OMP_TASKGROUP:
case OMP_TARGET_UPDATE:
case OMP_TARGET_ENTER_DATA:
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index c86a5fe..c1691c3 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -398,6 +398,47 @@ gimplify_to_rvalue (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
return t;
}
+/* Like gimplify_arg, but if ORDERED is set (which should be set if
+ any of the arguments this argument is sequenced before has
+ TREE_SIDE_EFFECTS set, make sure expressions with is_gimple_reg_type type
+ are gimplified into SSA_NAME or a fresh temporary and for
+ non-is_gimple_reg_type we don't optimize away TARGET_EXPRs. */
+
+static enum gimplify_status
+cp_gimplify_arg (tree *arg_p, gimple_seq *pre_p, location_t call_location,
+ bool ordered)
+{
+ enum gimplify_status t;
+ if (ordered
+ && !is_gimple_reg_type (TREE_TYPE (*arg_p))
+ && TREE_CODE (*arg_p) == TARGET_EXPR)
+ {
+ /* gimplify_arg would strip away the TARGET_EXPR, but
+ that can mean we don't copy the argument and some following
+ argument with side-effect could modify it. */
+ protected_set_expr_location (*arg_p, call_location);
+ return gimplify_expr (arg_p, pre_p, NULL, is_gimple_lvalue, fb_either);
+ }
+ else
+ {
+ t = gimplify_arg (arg_p, pre_p, call_location);
+ if (t == GS_ERROR)
+ return GS_ERROR;
+ else if (ordered
+ && is_gimple_reg_type (TREE_TYPE (*arg_p))
+ && is_gimple_variable (*arg_p)
+ && TREE_CODE (*arg_p) != SSA_NAME
+ /* No need to force references into register, references
+ can't be modified. */
+ && !TYPE_REF_P (TREE_TYPE (*arg_p))
+ /* And this can't be modified either. */
+ && *arg_p != current_class_ptr)
+ *arg_p = get_initialized_tmp_var (*arg_p, pre_p);
+ return t;
+ }
+
+}
+
/* Do C++-specific gimplification. Args are as for gimplify_expr. */
int
@@ -613,7 +654,8 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
gcc_assert (call_expr_nargs (*expr_p) == 2);
gcc_assert (!CALL_EXPR_ORDERED_ARGS (*expr_p));
enum gimplify_status t
- = gimplify_arg (&CALL_EXPR_ARG (*expr_p, 1), pre_p, loc);
+ = cp_gimplify_arg (&CALL_EXPR_ARG (*expr_p, 1), pre_p, loc,
+ TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, 0)));
if (t == GS_ERROR)
ret = GS_ERROR;
}
@@ -622,10 +664,18 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
/* Leave the last argument for gimplify_call_expr, to avoid problems
with __builtin_va_arg_pack(). */
int nargs = call_expr_nargs (*expr_p) - 1;
+ int last_side_effects_arg = -1;
+ for (int i = nargs; i > 0; --i)
+ if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
+ {
+ last_side_effects_arg = i;
+ break;
+ }
for (int i = 0; i < nargs; ++i)
{
enum gimplify_status t
- = gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p, loc);
+ = cp_gimplify_arg (&CALL_EXPR_ARG (*expr_p, i), pre_p, loc,
+ i < last_side_effects_arg);
if (t == GS_ERROR)
ret = GS_ERROR;
}
@@ -639,8 +689,17 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
fntype = TREE_TYPE (fntype);
if (TREE_CODE (fntype) == METHOD_TYPE)
{
+ int nargs = call_expr_nargs (*expr_p);
+ bool side_effects = false;
+ for (int i = 1; i < nargs; ++i)
+ if (TREE_SIDE_EFFECTS (CALL_EXPR_ARG (*expr_p, i)))
+ {
+ side_effects = true;
+ break;
+ }
enum gimplify_status t
- = gimplify_arg (&CALL_EXPR_ARG (*expr_p, 0), pre_p, loc);
+ = cp_gimplify_arg (&CALL_EXPR_ARG (*expr_p, 0), pre_p, loc,
+ side_effects);
if (t == GS_ERROR)
ret = GS_ERROR;
}
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 28f2d7b..38eae88 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -404,6 +404,7 @@ names_builtin_p (const char *name)
case RID_BUILTIN_SHUFFLE:
case RID_BUILTIN_SHUFFLEVECTOR:
case RID_BUILTIN_LAUNDER:
+ case RID_BUILTIN_ASSOC_BARRIER:
case RID_BUILTIN_BIT_CAST:
case RID_OFFSETOF:
case RID_HAS_NOTHROW_ASSIGN:
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index acc98c9..3f56cb9 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -473,7 +473,8 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR)
FNDECL_USED_AUTO (in FUNCTION_DECL)
DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE)
- REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR)
+ REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF, SCOPE_REF,
+ VIEW_CONVERT_EXPR, PAREN_EXPR)
AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR)
CONSTRUCTOR_MUTABLE_POISON (in CONSTRUCTOR)
OVL_HIDDEN_P (in OVERLOAD)
@@ -4041,12 +4042,13 @@ struct GTY(()) lang_decl {
#define PAREN_STRING_LITERAL_P(NODE) \
TREE_LANG_FLAG_0 (STRING_CST_CHECK (NODE))
-/* Indicates whether a COMPONENT_REF or a SCOPE_REF has been parenthesized, or
- an INDIRECT_REF comes from parenthesizing a _DECL. Currently only set some
- of the time in C++14 mode. */
+/* Indicates whether a COMPONENT_REF or a SCOPE_REF has been parenthesized, an
+ INDIRECT_REF comes from parenthesizing a _DECL, or a PAREN_EXPR identifies a
+ parenthesized initializer relevant for decltype(auto). Currently only set
+ some of the time in C++14 mode. */
#define REF_PARENTHESIZED_P(NODE) \
- TREE_LANG_FLAG_2 (TREE_CHECK4 ((NODE), COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR))
+ TREE_LANG_FLAG_2 (TREE_CHECK5 ((NODE), COMPONENT_REF, INDIRECT_REF, SCOPE_REF, VIEW_CONVERT_EXPR, PAREN_EXPR))
/* Nonzero if this AGGR_INIT_EXPR provides for initialization via a
constructor call, rather than an ordinary function call. */
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 2ddf0e4..9f68d1a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -17609,7 +17609,8 @@ finish_function (bool inline_p)
if (!processing_template_decl
&& !cp_function_chain->can_throw
&& !flag_non_call_exceptions
- && !decl_replaceable_p (fndecl))
+ && !decl_replaceable_p (fndecl,
+ opt_for_fn (fndecl, flag_semantic_interposition)))
TREE_NOTHROW (fndecl) = 1;
/* This must come after expand_function_end because cleanups might
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 3ba2e3b..975f2ed 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -41,7 +41,6 @@ static tree finish_init_stmts (bool, tree, tree);
static void construct_virtual_base (tree, tree);
static bool expand_aggr_init_1 (tree, tree, tree, tree, int, tsubst_flags_t);
static bool expand_default_init (tree, tree, tree, tree, int, tsubst_flags_t);
-static void perform_member_init (tree, tree);
static int member_init_ok_or_else (tree, tree, tree);
static void expand_virtual_init (tree, tree);
static tree sort_mem_initializers (tree, tree);
@@ -525,19 +524,19 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
return build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
}
-/* Initialize current class with INIT, a TREE_LIST of
- arguments for a target constructor. If TREE_LIST is void_type_node,
- an empty initializer list was given. */
+/* Initialize current class with INIT, a TREE_LIST of arguments for
+ a target constructor. If TREE_LIST is void_type_node, an empty
+ initializer list was given. Return the target constructor. */
-static void
+static tree
perform_target_ctor (tree init)
{
tree decl = current_class_ref;
tree type = current_class_type;
- finish_expr_stmt (build_aggr_init (decl, init,
- LOOKUP_NORMAL|LOOKUP_DELEGATING_CONS,
- tf_warning_or_error));
+ init = build_aggr_init (decl, init, LOOKUP_NORMAL|LOOKUP_DELEGATING_CONS,
+ tf_warning_or_error);
+ finish_expr_stmt (init);
if (type_build_dtor_call (type))
{
tree expr = build_delete (input_location,
@@ -550,6 +549,7 @@ perform_target_ctor (tree init)
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
finish_eh_cleanup (expr);
}
+ return init;
}
/* Return the non-static data initializer for FIELD_DECL MEMBER. */
@@ -775,12 +775,148 @@ maybe_warn_list_ctor (tree member, tree init)
"of the underlying array", member, begin);
}
+/* Data structure for find_uninit_fields_r, below. */
+
+struct find_uninit_data {
+ /* The set tracking the yet-uninitialized members. */
+ hash_set<tree> *uninitialized;
+ /* The data member we are currently initializing. It can be either
+ a type (initializing a base class/delegating constructors), or
+ a COMPONENT_REF. */
+ tree member;
+};
+
+/* walk_tree callback that warns about using uninitialized data in
+ a member-initializer-list. */
+
+static tree
+find_uninit_fields_r (tree *tp, int *walk_subtrees, void *data)
+{
+ find_uninit_data *d = static_cast<find_uninit_data *>(data);
+ hash_set<tree> *uninitialized = d->uninitialized;
+ tree init = *tp;
+ const tree_code code = TREE_CODE (init);
+
+ /* No need to look into types or unevaluated operands. */
+ if (TYPE_P (init) || unevaluated_p (code))
+ {
+ *walk_subtrees = false;
+ return NULL_TREE;
+ }
+
+ switch (code)
+ {
+ /* We'd need data flow info to avoid false positives. */
+ case COND_EXPR:
+ case VEC_COND_EXPR:
+ case BIND_EXPR:
+ /* We might see a MODIFY_EXPR in cases like S() : a((b = 42)), c(b) { }
+ where the initializer for 'a' surreptitiously initializes 'b'. Let's
+ not bother with these complicated scenarios in the front end. */
+ case MODIFY_EXPR:
+ /* Don't attempt to handle statement-expressions, either. */
+ case STATEMENT_LIST:
+ uninitialized->empty ();
+ gcc_fallthrough ();
+ /* If we're just taking the address of an object, it doesn't matter
+ whether it's been initialized. */
+ case ADDR_EXPR:
+ *walk_subtrees = false;
+ return NULL_TREE;
+ default:
+ break;
+ }
+
+ /* We'd need data flow info to avoid false positives. */
+ if (truth_value_p (code))
+ goto give_up;
+ /* Attempt to handle a simple a{b}, but no more. */
+ else if (BRACE_ENCLOSED_INITIALIZER_P (init))
+ {
+ if (CONSTRUCTOR_NELTS (init) == 1
+ && !BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (init, 0)->value))
+ init = CONSTRUCTOR_ELT (init, 0)->value;
+ else
+ goto give_up;
+ }
+ /* Warn about uninitialized 'this'. */
+ else if (code == CALL_EXPR)
+ {
+ tree fn = get_callee_fndecl (init);
+ if (fn && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn))
+ {
+ tree op = CALL_EXPR_ARG (init, 0);
+ if (TREE_CODE (op) == ADDR_EXPR)
+ op = TREE_OPERAND (op, 0);
+ temp_override<tree> ovr (d->member, DECL_ARGUMENTS (fn));
+ cp_walk_tree_without_duplicates (&op, find_uninit_fields_r, data);
+ }
+ /* Functions (whether static or nonstatic member) may have side effects
+ and initialize other members; it's not the front end's job to try to
+ figure it out. But don't give up for constructors: we still want to
+ warn when initializing base classes:
+
+ struct D : public B {
+ int x;
+ D() : B(x) {}
+ };
+
+ so carry on to detect that 'x' is used uninitialized. */
+ if (!fn || !DECL_CONSTRUCTOR_P (fn))
+ goto give_up;
+ }
+
+ /* If we find FIELD in the uninitialized set, we warn. */
+ if (code == COMPONENT_REF)
+ {
+ tree field = TREE_OPERAND (init, 1);
+ tree type = TYPE_P (d->member) ? d->member : TREE_TYPE (d->member);
+
+ /* We're initializing a reference member with itself. */
+ if (TYPE_REF_P (type) && cp_tree_equal (d->member, init))
+ warning_at (EXPR_LOCATION (init), OPT_Winit_self,
+ "%qD is initialized with itself", field);
+ else if (cp_tree_equal (TREE_OPERAND (init, 0), current_class_ref)
+ && uninitialized->contains (field))
+ {
+ if (TYPE_REF_P (TREE_TYPE (field)))
+ warning_at (EXPR_LOCATION (init), OPT_Wuninitialized,
+ "reference %qD is not yet bound to a value when used "
+ "here", field);
+ else if (!INDIRECT_TYPE_P (type) || is_this_parameter (d->member))
+ warning_at (EXPR_LOCATION (init), OPT_Wuninitialized,
+ "member %qD is used uninitialized", field);
+ *walk_subtrees = false;
+ }
+ }
+
+ return NULL_TREE;
+
+give_up:
+ *walk_subtrees = false;
+ uninitialized->empty ();
+ return integer_zero_node;
+}
+
+/* Wrapper around find_uninit_fields_r above. */
+
+static void
+find_uninit_fields (tree *t, hash_set<tree> *uninitialized, tree member)
+{
+ if (!uninitialized->is_empty ())
+ {
+ find_uninit_data data = { uninitialized, member };
+ cp_walk_tree_without_duplicates (t, find_uninit_fields_r, &data);
+ }
+}
+
/* Initialize MEMBER, a FIELD_DECL, with INIT, a TREE_LIST of
arguments. If TREE_LIST is void_type_node, an empty initializer
- list was given; if NULL_TREE no initializer was given. */
+ list was given; if NULL_TREE no initializer was given. UNINITIALIZED
+ is the hash set that tracks uninitialized fields. */
static void
-perform_member_init (tree member, tree init)
+perform_member_init (tree member, tree init, hash_set<tree> &uninitialized)
{
tree decl;
tree type = TREE_TYPE (member);
@@ -808,7 +944,9 @@ perform_member_init (tree member, tree init)
if (decl == error_mark_node)
return;
- if (warn_init_self && init && TREE_CODE (init) == TREE_LIST
+ if ((warn_init_self || warn_uninitialized)
+ && init
+ && TREE_CODE (init) == TREE_LIST
&& TREE_CHAIN (init) == NULL_TREE)
{
tree val = TREE_VALUE (init);
@@ -820,6 +958,8 @@ perform_member_init (tree member, tree init)
warning_at (DECL_SOURCE_LOCATION (current_function_decl),
OPT_Winit_self, "%qD is initialized with itself",
member);
+ else
+ find_uninit_fields (&val, &uninitialized, decl);
}
if (array_of_unknown_bound_p (type))
@@ -848,6 +988,9 @@ perform_member_init (tree member, tree init)
do aggregate-initialization. */
}
+ /* Assume we are initializing the member. */
+ bool member_initialized_p = true;
+
if (init == void_type_node)
{
/* mem() means value-initialization. */
@@ -988,6 +1131,9 @@ perform_member_init (tree member, tree init)
diagnose_uninitialized_cst_or_ref_member (core_type,
/*using_new=*/false,
/*complain=*/true);
+
+ /* We left the member uninitialized. */
+ member_initialized_p = false;
}
maybe_warn_list_ctor (member, init);
@@ -998,6 +1144,11 @@ perform_member_init (tree member, tree init)
tf_warning_or_error));
}
+ if (member_initialized_p && warn_uninitialized)
+ /* This member is now initialized, remove it from the uninitialized
+ set. */
+ uninitialized.remove (member);
+
if (type_build_dtor_call (type))
{
tree expr;
@@ -1311,13 +1462,25 @@ emit_mem_initializers (tree mem_inits)
if (!COMPLETE_TYPE_P (current_class_type))
return;
+ /* Keep a set holding fields that are not initialized. */
+ hash_set<tree> uninitialized;
+
+ /* Initially that is all of them. */
+ if (warn_uninitialized)
+ for (tree f = next_initializable_field (TYPE_FIELDS (current_class_type));
+ f != NULL_TREE;
+ f = next_initializable_field (DECL_CHAIN (f)))
+ if (!DECL_ARTIFICIAL (f))
+ uninitialized.add (f);
+
if (mem_inits
&& TYPE_P (TREE_PURPOSE (mem_inits))
&& same_type_p (TREE_PURPOSE (mem_inits), current_class_type))
{
/* Delegating constructor. */
gcc_assert (TREE_CHAIN (mem_inits) == NULL_TREE);
- perform_target_ctor (TREE_VALUE (mem_inits));
+ tree ctor = perform_target_ctor (TREE_VALUE (mem_inits));
+ find_uninit_fields (&ctor, &uninitialized, current_class_type);
return;
}
@@ -1378,6 +1541,9 @@ emit_mem_initializers (tree mem_inits)
flags,
tf_warning_or_error);
expand_cleanup_for_base (subobject, NULL_TREE);
+ if (STATEMENT_LIST_TAIL (cur_stmt_list))
+ find_uninit_fields (&STATEMENT_LIST_TAIL (cur_stmt_list)->stmt,
+ &uninitialized, BINFO_TYPE (subobject));
}
else if (!ABSTRACT_CLASS_TYPE_P (current_class_type))
/* C++14 DR1658 Means we do not have to construct vbases of
@@ -1405,7 +1571,9 @@ emit_mem_initializers (tree mem_inits)
iloc_sentinel ils (EXPR_LOCATION (TREE_TYPE (mem_inits)));
perform_member_init (TREE_PURPOSE (mem_inits),
- TREE_VALUE (mem_inits));
+ TREE_VALUE (mem_inits),
+ uninitialized);
+
mem_inits = TREE_CHAIN (mem_inits);
}
}
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index f68c68c..c39a2bc 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -195,7 +195,9 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
tree type;
bool is_this = is_this_parameter (tree_strip_nop_conversions (expr));
- if (!is_this && explicit_init_p)
+ if (is_this)
+ type = TREE_TYPE (expr);
+ else if (explicit_init_p)
{
tree auto_node = make_auto ();
@@ -209,7 +211,7 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
else
type = do_auto_deduction (type, expr, auto_node);
}
- else if (!is_this && type_dependent_expression_p (expr))
+ else if (type_dependent_expression_p (expr))
{
type = cxx_make_type (DECLTYPE_TYPE);
DECLTYPE_TYPE_EXPR (type) = expr;
@@ -219,10 +221,19 @@ lambda_capture_field_type (tree expr, bool explicit_init_p,
}
else
{
+ if (!by_reference_p && is_capture_proxy (expr))
+ {
+ /* When capturing by-value another capture proxy from an enclosing
+ lambda, consider the type of the corresponding field instead,
+ as the proxy may be additionally const-qualifed if the enclosing
+ lambda is non-mutable (PR94376). */
+ gcc_assert (TREE_CODE (DECL_VALUE_EXPR (expr)) == COMPONENT_REF);
+ expr = TREE_OPERAND (DECL_VALUE_EXPR (expr), 1);
+ }
+
type = non_reference (unlowered_expr_type (expr));
- if (!is_this
- && (by_reference_p || TREE_CODE (type) == FUNCTION_TYPE))
+ if (by_reference_p || TREE_CODE (type) == FUNCTION_TYPE)
type = build_reference_type (type);
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index e86e2b5..aa7f0e4 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -7354,6 +7354,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
case RID_BUILTIN_SHUFFLE:
case RID_BUILTIN_SHUFFLEVECTOR:
case RID_BUILTIN_LAUNDER:
+ case RID_BUILTIN_ASSOC_BARRIER:
{
vec<tree, va_gc> *vec;
@@ -7396,6 +7397,19 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
}
break;
+ case RID_BUILTIN_ASSOC_BARRIER:
+ if (vec->length () == 1)
+ postfix_expression = build1_loc (loc, PAREN_EXPR,
+ TREE_TYPE ((*vec)[0]),
+ (*vec)[0]);
+ else
+ {
+ error_at (loc, "wrong number of arguments to "
+ "%<__builtin_assoc_barrier%>");
+ postfix_expression = error_mark_node;
+ }
+ break;
+
case RID_BUILTIN_SHUFFLE:
if (vec->length () == 2)
postfix_expression
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 82bf7dc..c73e035 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -10766,6 +10766,11 @@ any_template_parm_r (tree t, void *data)
WALK_SUBTREE (TREE_TYPE (t));
break;
+ case CONVERT_EXPR:
+ if (is_dummy_object (t))
+ WALK_SUBTREE (TREE_TYPE (t));
+ break;
+
default:
break;
}
@@ -11722,6 +11727,17 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
q = &TREE_CHAIN (*q);
}
+ /* cplus_decl_attributes can add some attributes implicitly. For templates,
+ those attributes should have been added already when those templates were
+ parsed, and shouldn't be added based on from which context they are
+ first time instantiated. */
+ auto o1 = make_temp_override (current_optimize_pragma, NULL_TREE);
+ auto o2 = make_temp_override (optimization_current_node,
+ optimization_default_node);
+ auto o3 = make_temp_override (current_target_pragma, NULL_TREE);
+ auto o4 = make_temp_override (scope_chain->omp_declare_target_attribute,
+ NULL);
+
cplus_decl_attributes (decl_p, late_attrs, attr_flags);
return true;
@@ -17249,6 +17265,7 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
case INTEGER_CST:
case REAL_CST:
case COMPLEX_CST:
+ case VECTOR_CST:
{
/* Instantiate any typedefs in the type. */
tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
@@ -20267,7 +20284,10 @@ tsubst_copy_and_build (tree t,
/*done=*/false,
/*address_p=*/false);
}
- else if (koenig_p && identifier_p (function))
+ else if (koenig_p
+ && (identifier_p (function)
+ || (TREE_CODE (function) == TEMPLATE_ID_EXPR
+ && identifier_p (TREE_OPERAND (function, 0)))))
{
/* Do nothing; calling tsubst_copy_and_build on an identifier
would incorrectly perform unqualified lookup again.
@@ -20280,6 +20300,12 @@ tsubst_copy_and_build (tree t,
FIXME but doing that causes c++/15272, so we need to stop
using IDENTIFIER_NODE in that situation. */
qualified_p = false;
+
+ if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
+ /* Use tsubst_copy to substitute through the template arguments
+ of the template-id without performing unqualified lookup of
+ the template name. */
+ function = tsubst_copy (function, args, complain, in_decl);
}
else
{
@@ -20425,10 +20451,13 @@ tsubst_copy_and_build (tree t,
if (function != NULL_TREE
&& (identifier_p (function)
|| (TREE_CODE (function) == TEMPLATE_ID_EXPR
- && identifier_p (TREE_OPERAND (function, 0))))
+ && identifier_p (TREE_OPERAND (function, 0))
+ && !any_dependent_template_arguments_p (TREE_OPERAND
+ (function, 1))))
&& !any_type_dependent_arguments_p (call_args))
{
- if (TREE_CODE (function) == TEMPLATE_ID_EXPR)
+ bool template_id_p = (TREE_CODE (function) == TEMPLATE_ID_EXPR);
+ if (template_id_p)
function = TREE_OPERAND (function, 0);
if (koenig_p && (complain & tf_warning_or_error))
{
@@ -20443,20 +20472,21 @@ tsubst_copy_and_build (tree t,
if (unq != function)
{
- /* In a lambda fn, we have to be careful to not
- introduce new this captures. Legacy code can't
- be using lambdas anyway, so it's ok to be
- stricter. */
- bool in_lambda = (current_class_type
- && LAMBDA_TYPE_P (current_class_type));
char const *const msg
= G_("%qD was not declared in this scope, "
"and no declarations were found by "
"argument-dependent lookup at the point "
"of instantiation");
+ bool in_lambda = (current_class_type
+ && LAMBDA_TYPE_P (current_class_type));
+ /* In a lambda fn, we have to be careful to not
+ introduce new this captures. Legacy code can't
+ be using lambdas anyway, so it's ok to be
+ stricter. Be strict with C++20 template-id ADL too. */
+ bool strict = in_lambda || template_id_p;
bool diag = true;
- if (in_lambda)
+ if (strict)
error_at (cp_expr_loc_or_input_loc (t),
msg, function);
else
@@ -20492,7 +20522,7 @@ tsubst_copy_and_build (tree t,
inform (DECL_SOURCE_LOCATION (fn),
"%qD declared here, later in the "
"translation unit", fn);
- if (in_lambda)
+ if (strict)
RETURN (error_mark_node);
}
@@ -21010,7 +21040,15 @@ tsubst_copy_and_build (tree t,
integral_constant_expression_p));
case PAREN_EXPR:
- RETURN (finish_parenthesized_expr (RECUR (TREE_OPERAND (t, 0))));
+ if (REF_PARENTHESIZED_P (t))
+ RETURN (finish_parenthesized_expr (RECUR (TREE_OPERAND (t, 0))));
+ else
+ /* Recreate the PAREN_EXPR from __builtin_assoc_barrier. */
+ {
+ tree op0 = RECUR (TREE_OPERAND (t, 0));
+ RETURN (build1_loc (input_location, PAREN_EXPR,
+ TREE_TYPE (op0), op0));
+ }
case VEC_PERM_EXPR:
{
diff --git a/gcc/cp/ptree.c b/gcc/cp/ptree.c
index ca7884d..d514aa2 100644
--- a/gcc/cp/ptree.c
+++ b/gcc/cp/ptree.c
@@ -379,6 +379,9 @@ cxx_print_xnode (FILE *file, tree node, int indent)
if (tree message = STATIC_ASSERT_MESSAGE (node))
print_node (file, "message", message, indent+4);
break;
+ case PTRMEM_CST:
+ print_node (file, "member", PTRMEM_CST_MEMBER (node), indent+4);
+ break;
default:
break;
}
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1540442..d962b29 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -2048,24 +2048,17 @@ force_paren_expr (tree expr, bool even_uneval)
if (cp_unevaluated_operand && !even_uneval)
return expr;
- if (!DECL_P (tree_strip_any_location_wrapper (expr))
- && TREE_CODE (expr) != COMPONENT_REF
- && TREE_CODE (expr) != SCOPE_REF)
- return expr;
-
- location_t loc = cp_expr_location (expr);
-
if (TREE_CODE (expr) == COMPONENT_REF
|| TREE_CODE (expr) == SCOPE_REF)
REF_PARENTHESIZED_P (expr) = true;
- else if (processing_template_decl)
- expr = build1_loc (loc, PAREN_EXPR, TREE_TYPE (expr), expr);
- else
+ else if (DECL_P (tree_strip_any_location_wrapper (expr)))
{
- expr = build1_loc (loc, VIEW_CONVERT_EXPR, TREE_TYPE (expr), expr);
+ location_t loc = cp_expr_location (expr);
+ const tree_code code = processing_template_decl ? PAREN_EXPR
+ : VIEW_CONVERT_EXPR;
+ expr = build1_loc (loc, code, TREE_TYPE (expr), expr);
REF_PARENTHESIZED_P (expr) = true;
}
-
return expr;
}
@@ -2090,10 +2083,8 @@ maybe_undo_parenthesized_ref (tree t)
|| TREE_CODE (t) == STATIC_CAST_EXPR);
t = TREE_OPERAND (t, 0);
}
- else if (TREE_CODE (t) == PAREN_EXPR)
- t = TREE_OPERAND (t, 0);
- else if (TREE_CODE (t) == VIEW_CONVERT_EXPR
- && REF_PARENTHESIZED_P (t))
+ else if ((TREE_CODE (t) == PAREN_EXPR || TREE_CODE (t) == VIEW_CONVERT_EXPR)
+ && REF_PARENTHESIZED_P (t))
t = TREE_OPERAND (t, 0);
return t;
@@ -3143,6 +3134,20 @@ finish_compound_literal (tree type, tree compound_literal,
if (type == error_mark_node)
return error_mark_node;
}
+ /* C++23 auto{x}. */
+ else if (is_auto (type)
+ && !AUTO_IS_DECLTYPE (type)
+ && CONSTRUCTOR_NELTS (compound_literal) == 1)
+ {
+ if (cxx_dialect < cxx23)
+ pedwarn (input_location, OPT_Wc__23_extensions,
+ "%<auto{x}%> only available with "
+ "%<-std=c++2b%> or %<-std=gnu++2b%>");
+ type = do_auto_deduction (type, compound_literal, type, complain,
+ adc_variable_type);
+ if (type == error_mark_node)
+ return error_mark_node;
+ }
/* Used to hold a copy of the compound literal in a template. */
tree orig_cl = NULL_TREE;
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 32ddf83..7050a53 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -5352,13 +5352,6 @@ cp_walk_subtrees (tree *tp, int *walk_subtrees_p, walk_tree_fn func,
case BIT_CAST_EXPR:
if (TREE_TYPE (*tp))
WALK_SUBTREE (TREE_TYPE (*tp));
-
- {
- int i;
- for (i = 0; i < TREE_CODE_LENGTH (TREE_CODE (*tp)); ++i)
- WALK_SUBTREE (TREE_OPERAND (*tp, i));
- }
- *walk_subtrees_p = 0;
break;
case CONSTRUCTOR:
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index cb20329..58919aa 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -4594,9 +4594,11 @@ build_vec_cmp (tree_code code, tree type,
static void
warn_for_null_address (location_t location, tree op, tsubst_flags_t complain)
{
+ /* Prevent warnings issued for macro expansion. */
if (!warn_address
|| (complain & tf_warning) == 0
|| c_inhibit_evaluation_warnings != 0
+ || from_macro_expansion_at (location)
|| warning_suppressed_p (op, OPT_Waddress))
return;
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index e98fbf7..3fb651a 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -2201,19 +2201,29 @@ build_functional_cast_1 (location_t loc, tree exp, tree parms,
if (tree anode = type_uses_auto (type))
{
- if (!CLASS_PLACEHOLDER_TEMPLATE (anode))
+ tree init;
+ if (CLASS_PLACEHOLDER_TEMPLATE (anode))
+ init = parms;
+ /* C++23 auto(x). */
+ else if (!AUTO_IS_DECLTYPE (anode)
+ && list_length (parms) == 1)
{
- if (complain & tf_error)
- error_at (loc, "invalid use of %qT", anode);
- return error_mark_node;
+ init = TREE_VALUE (parms);
+ if (cxx_dialect < cxx23)
+ pedwarn (loc, OPT_Wc__23_extensions,
+ "%<auto(x)%> only available with "
+ "%<-std=c++2b%> or %<-std=gnu++2b%>");
}
else
{
- type = do_auto_deduction (type, parms, anode, complain,
- adc_variable_type);
- if (type == error_mark_node)
- return error_mark_node;
+ if (complain & tf_error)
+ error_at (loc, "invalid use of %qT", anode);
+ return error_mark_node;
}
+ type = do_auto_deduction (type, init, anode, complain,
+ adc_variable_type);
+ if (type == error_mark_node)
+ return error_mark_node;
}
if (processing_template_decl)
diff --git a/gcc/d/ChangeLog b/gcc/d/ChangeLog
index b752dd9..d04102a 100644
--- a/gcc/d/ChangeLog
+++ b/gcc/d/ChangeLog
@@ -1,3 +1,8 @@
+2021-11-18 Iain Buclaw <ibuclaw@gdcproject.org>
+
+ * decl.cc (d_finish_decl): Use HOST_WIDE_INT for type size
+ temporaries.
+
2021-10-22 Eric Gallager <egallager@gcc.gnu.org>
PR other/102663
diff --git a/gcc/d/decl.cc b/gcc/d/decl.cc
index 0d46ee1..9c9205f 100644
--- a/gcc/d/decl.cc
+++ b/gcc/d/decl.cc
@@ -1544,8 +1544,9 @@ d_finish_decl (tree decl)
if (flag_checking && DECL_INITIAL (decl))
{
/* Initializer must never be bigger than symbol size. */
- dinteger_t tsize = int_size_in_bytes (TREE_TYPE (decl));
- dinteger_t dtsize = int_size_in_bytes (TREE_TYPE (DECL_INITIAL (decl)));
+ HOST_WIDE_INT tsize = int_size_in_bytes (TREE_TYPE (decl));
+ HOST_WIDE_INT dtsize =
+ int_size_in_bytes (TREE_TYPE (DECL_INITIAL (decl)));
if (tsize < dtsize)
{
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index 8434533..035a2c8 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -14038,6 +14038,24 @@ int g (int c)
@end deftypefn
+@deftypefn {Built-in Function} @var{type} __builtin_assoc_barrier (@var{type} @var{expr})
+This built-in inhibits re-association of the floating-point expression
+@var{expr} with expressions consuming the return value of the built-in. The
+expression @var{expr} itself can be reordered, and the whole expression
+@var{expr} can be reordered with operands after the barrier. The barrier is
+only relevant when @code{-fassociative-math} is active, since otherwise
+floating-point is not treated as associative.
+
+@smallexample
+float x0 = a + b - b;
+float x1 = __builtin_assoc_barrier(a + b) - b;
+@end smallexample
+
+@noindent
+means that, with @code{-fassociative-math}, @code{x0} can be optimized to
+@code{x0 = a} but @code{x1} cannot.
+@end deftypefn
+
@deftypefn {Built-in Function} {void *} __builtin_assume_aligned (const void *@var{exp}, size_t @var{align}, ...)
This function returns its first argument, and allows the compiler
to assume that the returned pointer is at least @var{align} bytes
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 3ae66ac..714a415 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -290,7 +290,9 @@ Objective-C and Objective-C++ Dialects}.
-Warith-conversion @gol
-Warray-bounds -Warray-bounds=@var{n} -Warray-compare @gol
-Wno-attributes -Wattribute-alias=@var{n} -Wno-attribute-alias @gol
--Wno-attribute-warning -Wbool-compare -Wbool-operation @gol
+-Wno-attribute-warning @gol
+-Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]} @gol
+-Wbool-compare -Wbool-operation @gol
-Wno-builtin-declaration-mismatch @gol
-Wno-builtin-macro-redefined -Wc90-c99-compat -Wc99-c11-compat @gol
-Wc11-c2x-compat @gol
@@ -1388,7 +1390,8 @@ See RS/6000 and PowerPC Options.
-mstack-protector-guard-symbol=@var{symbol} @gol
-mgeneral-regs-only -mcall-ms2sysv-xlogues -mrelax-cmpxchg-loop @gol
-mindirect-branch=@var{choice} -mfunction-return=@var{choice} @gol
--mindirect-branch-register -mneeded}
+-mindirect-branch-register -mharden-sls=@var{choice} @gol
+-mindirect-branch-cs-prefix -mneeded}
@emph{x86 Windows Options}
@gccoptlist{-mconsole -mcygwin -mno-cygwin -mdll @gol
@@ -1840,7 +1843,8 @@ named @file{dir/bar.*}, combining the given @var{dumppfx} with the
default @var{dumpbase} derived from the primary output name. Dump
outputs also take the input name suffix: @file{dir/bar.c.*}.
-It defaults to the location of the output file; options
+It defaults to the location of the output file, unless the output
+file is a special file like @code{/dev/null}. Options
@option{-save-temps=cwd} and @option{-save-temps=obj} override this
default, just like an explicit @option{-dumpdir} option. In case
multiple such options are given, the last one prevails:
@@ -3067,6 +3071,13 @@ word as an identifier. You can use the keyword @code{__typeof__} instead.
This option is implied by the strict ISO C++ dialects: @option{-ansi},
@option{-std=c++98}, @option{-std=c++11}, etc.
+@item -fimplicit-constexpr
+@opindex fimplicit-constexpr
+Make inline functions implicitly constexpr, if they satisfy the
+requirements for a constexpr function. This option can be used in
+C++14 mode or later. This can result in initialization changing from
+dynamic to static and other optimizations.
+
@item -fno-implicit-templates
@opindex fno-implicit-templates
@opindex fimplicit-templates
@@ -6949,6 +6960,18 @@ to compute a value that itself is never used, because such
computations may be deleted by data flow analysis before the warnings
are printed.
+In C++, this warning also warns about using uninitialized objects in
+member-initializer-lists. For example, GCC warns about @code{b} being
+uninitialized in the following snippet:
+
+@smallexample
+struct A @{
+ int a;
+ int b;
+ A() : a(b) @{ @}
+@};
+@end smallexample
+
@item -Wno-invalid-memory-model
@opindex Winvalid-memory-model
@opindex Wno-invalid-memory-model
@@ -7641,6 +7664,23 @@ Attributes considered include @code{alloc_align}, @code{alloc_size},
This is the default. You can disable these warnings with either
@option{-Wno-attribute-alias} or @option{-Wattribute-alias=0}.
+@item -Wbidi-chars=@r{[}none@r{|}unpaired@r{|}any@r{]}
+@opindex Wbidi-chars=
+@opindex Wbidi-chars
+@opindex Wno-bidi-chars
+Warn about possibly misleading UTF-8 bidirectional control characters in
+comments, string literals, character constants, and identifiers. Such
+characters can change left-to-right writing direction into right-to-left
+(and vice versa), which can cause confusion between the logical order and
+visual order. This may be dangerous; for instance, it may seem that a piece
+of code is not commented out, whereas it in fact is.
+
+There are three levels of warning supported by GCC@. The default is
+@option{-Wbidi-chars=unpaired}, which warns about improperly terminated
+bidi contexts. @option{-Wbidi-chars=none} turns the warning off.
+@option{-Wbidi-chars=any} warns about any use of bidirectional control
+characters.
+
@item -Wbool-compare
@opindex Wno-bool-compare
@opindex Wbool-compare
@@ -8612,6 +8652,8 @@ suppressed by casting the pointer operand to an integer type such
as @code{inptr_t} or @code{uinptr_t}.
Comparisons against string literals result in unspecified behavior
and are not portable, and suggest the intent was to call @code{strcmp}.
+The warning is suppressed if the suspicious expression is the result
+of macro expansion.
@option{-Waddress} warning is enabled by @option{-Wall}.
@item -Wno-address-of-packed-member
@@ -10598,6 +10640,7 @@ valid for all standard-compliant programs.
It turns on @option{-ffast-math}, @option{-fallow-store-data-races}
and the Fortran-specific @option{-fstack-arrays}, unless
@option{-fmax-stack-var-size} is specified, and @option{-fno-protect-parens}.
+It turns off @option{-fsemantic-interposition}.
@item -Og
@opindex Og
@@ -32341,6 +32384,21 @@ not be reachable in the large code model.
@opindex mindirect-branch-register
Force indirect call and jump via register.
+@item -mharden-sls=@var{choice}
+@opindex mharden-sls
+Generate code to mitigate against straight line speculation (SLS) with
+@var{choice}. The default is @samp{none} which disables all SLS
+hardening. @samp{return} enables SLS hardening for function return.
+@samp{indirect-branch} enables SLS hardening for indirect branch.
+@samp{all} enables all SLS hardening.
+
+@item -mindirect-branch-cs-prefix
+@opindex mindirect-branch-cs-prefix
+Add CS prefix to call and jmp to indirect thunk with branch target in
+r8-r15 registers so that the call and jmp instruction length is 6 bytes
+to allow them to be replaced with @samp{lfence; call *%r8-r15} or
+@samp{lfence; jmp *%r8-r15} at run-time.
+
@end table
These @samp{-m} switches are supported in addition to the above
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 41f1850..589f841 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -6930,6 +6930,8 @@ operand 0, otherwise (operand 2 + operand 3) is moved.
@cindex @code{cond_smax@var{mode}} instruction pattern
@cindex @code{cond_umin@var{mode}} instruction pattern
@cindex @code{cond_umax@var{mode}} instruction pattern
+@cindex @code{cond_fmin@var{mode}} instruction pattern
+@cindex @code{cond_fmax@var{mode}} instruction pattern
@cindex @code{cond_ashl@var{mode}} instruction pattern
@cindex @code{cond_ashr@var{mode}} instruction pattern
@cindex @code{cond_lshr@var{mode}} instruction pattern
@@ -6947,6 +6949,8 @@ operand 0, otherwise (operand 2 + operand 3) is moved.
@itemx @samp{cond_smax@var{mode}}
@itemx @samp{cond_umin@var{mode}}
@itemx @samp{cond_umax@var{mode}}
+@itemx @samp{cond_fmin@var{mode}}
+@itemx @samp{cond_fmax@var{mode}}
@itemx @samp{cond_ashl@var{mode}}
@itemx @samp{cond_ashr@var{mode}}
@itemx @samp{cond_lshr@var{mode}}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 10dfca4..f3c885c 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,87 @@
+2021-11-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR debug/103315
+ * trans-types.c (gfc_get_array_descr_info): Use DW_OP_deref_size 1
+ instead of DW_OP_deref for DW_AT_rank.
+
+2021-11-21 Harald Anlauf <anlauf@gmx.de>
+ Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/99061
+ * trans-intrinsic.c (gfc_lookup_intrinsic): Helper function for
+ looking up gfortran builtin intrinsics.
+ (gfc_conv_intrinsic_atrigd): Use it.
+ (gfc_conv_intrinsic_cotan): Likewise.
+ (gfc_conv_intrinsic_cotand): Likewise.
+ (gfc_conv_intrinsic_atan2d): Likewise.
+
+2021-11-18 Harald Anlauf <anlauf@gmx.de>
+ Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/101329
+ * check.c (is_c_interoperable): Reject NULL() as it is not
+ interoperable.
+
+2021-11-16 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103286
+ * resolve.c (resolve_select): Choose appropriate range limit to
+ avoid NULL pointer dereference when generating error message.
+
+2021-11-16 Mikael Morin <mikael@gcc.gnu.org>
+
+ * interface.c (gfc_dummy_arg_get_name): New function.
+ * gfortran.h (gfc_dummy_arg_get_name): Declare it.
+ * trans-array.c (arg_evaluated_for_scalarization): Pass a dummy
+ argument wrapper as argument instead of an actual argument
+ and an index number. Check it’s non-NULL. Use its name
+ to identify it.
+ (gfc_walk_elemental_function_args): Update call to
+ arg_evaluated for scalarization. Remove argument counting.
+
+2021-11-16 Mikael Morin <mikael@gcc.gnu.org>
+
+ * gfortran.h (gfc_actual_arglist::missing_arg_type): Remove.
+ * interface.c (gfc_compare_actual_formal): Remove
+ missing_arg_type initialization.
+ * intrinsic.c (sort_actual): Ditto.
+ * trans-expr.c (gfc_conv_procedure_call): Use associated_dummy
+ and gfc_dummy_arg_get_typespec to get the dummy argument type.
+
+2021-11-16 Mikael Morin <mikael@gcc.gnu.org>
+
+ * interface.c (gfc_dummy_arg_get_typespec,
+ gfc_dummy_arg_is_optional): New functions.
+ * gfortran.h (gfc_dummy_arg_get_typespec,
+ gfc_dummy_arg_is_optional): Declare them.
+ * trans.h (gfc_ss_info::dummy_arg): Use the wrapper type
+ as declaration type.
+ * trans-array.c (gfc_scalar_elemental_arg_saved_as_reference):
+ use gfc_dummy_arg_get_typespec function to get the type.
+ (gfc_walk_elemental_function_args): Remove proc_ifc argument.
+ Get info about the dummy arg using the associated_dummy field.
+ * trans-array.h (gfc_walk_elemental_function_args): Update declaration.
+ * trans-intrinsic.c (gfc_walk_intrinsic_function):
+ Update call to gfc_walk_elemental_function_args.
+ * trans-stmt.c (gfc_trans_call): Ditto.
+ (get_proc_ifc_for_call): Remove.
+
+2021-11-16 Mikael Morin <mikael@gcc.gnu.org>
+
+ * gfortran.h (gfc_dummy_arg_kind, gfc_dummy_arg): New.
+ (gfc_actual_arglist): New field associated_dummy.
+ (gfc_intrinsic_arg): Remove field actual.
+ * interface.c (get_nonintrinsic_dummy_arg): New.
+ (gfc_compare_actual): Initialize associated_dummy.
+ * intrinsic.c (get_intrinsic_dummy_arg): New.
+ (sort_actual):  Add argument vectors.
+ Use loops with indices on argument vectors.
+ Initialize associated_dummy.
+
+2021-11-16 Mikael Morin <mikael@gcc.gnu.org>
+
+ * intrinsic.c (sort_actual): initialise variable and use it earlier.
+
2021-11-15 Tobias Burnus <tobias@codesourcery.com>
* openmp.c (OMP_TARGET_CLAUSES): Add thread_limit.
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index ffa07b5..5a5aca1 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -5223,6 +5223,12 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr)
{
*msg = NULL;
+ if (expr->expr_type == EXPR_NULL)
+ {
+ *msg = "NULL() is not interoperable";
+ return false;
+ }
+
if (expr->ts.type == BT_CLASS)
{
*msg = "Expression is polymorphic";
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 1ad2f0d..1846ee4 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1199,6 +1199,9 @@ gfc_formal_arglist;
#define gfc_get_formal_arglist() XCNEW (gfc_formal_arglist)
+struct gfc_dummy_arg;
+
+
/* The gfc_actual_arglist structure is for actual arguments and
for type parameter specification lists. */
typedef struct gfc_actual_arglist
@@ -1207,14 +1210,14 @@ typedef struct gfc_actual_arglist
/* Alternate return label when the expr member is null. */
struct gfc_st_label *label;
- /* This is set to the type of an eventual omitted optional
- argument. This is used to determine if a hidden string length
- argument has to be added to a function call. */
- bt missing_arg_type;
-
gfc_param_spec_type spec_type;
struct gfc_expr *expr;
+
+ /* The dummy arg this actual arg is associated with, if the interface
+ is explicit. NULL otherwise. */
+ gfc_dummy_arg *associated_dummy;
+
struct gfc_actual_arglist *next;
}
gfc_actual_arglist;
@@ -2299,14 +2302,38 @@ typedef struct gfc_intrinsic_arg
gfc_typespec ts;
unsigned optional:1, value:1;
ENUM_BITFIELD (sym_intent) intent:2;
- gfc_actual_arglist *actual;
struct gfc_intrinsic_arg *next;
-
}
gfc_intrinsic_arg;
+typedef enum {
+ GFC_UNDEFINED_DUMMY_ARG = 0,
+ GFC_INTRINSIC_DUMMY_ARG,
+ GFC_NON_INTRINSIC_DUMMY_ARG
+}
+gfc_dummy_arg_intrinsicness;
+
+/* dummy arg of either an intrinsic or a user-defined procedure. */
+struct gfc_dummy_arg
+{
+ gfc_dummy_arg_intrinsicness intrinsicness;
+
+ union {
+ gfc_intrinsic_arg *intrinsic;
+ gfc_formal_arglist *non_intrinsic;
+ } u;
+};
+
+#define gfc_get_dummy_arg() XCNEW (gfc_dummy_arg)
+
+
+const char * gfc_dummy_arg_get_name (gfc_dummy_arg &);
+const gfc_typespec & gfc_dummy_arg_get_typespec (gfc_dummy_arg &);
+bool gfc_dummy_arg_is_optional (gfc_dummy_arg &);
+
+
/* Specifies the various kinds of check functions used to verify the
argument lists of intrinsic functions. fX with X an integer refer
to check functions of intrinsics with X arguments. f1m is used for
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index 30c99ef..8571709 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -3043,6 +3043,18 @@ lookup_arg_fuzzy (const char *arg, gfc_formal_arglist *arguments)
}
+static gfc_dummy_arg *
+get_nonintrinsic_dummy_arg (gfc_formal_arglist *formal)
+{
+ gfc_dummy_arg * const dummy_arg = gfc_get_dummy_arg ();
+
+ dummy_arg->intrinsicness = GFC_NON_INTRINSIC_DUMMY_ARG;
+ dummy_arg->u.non_intrinsic = formal;
+
+ return dummy_arg;
+}
+
+
/* Given formal and actual argument lists, see if they are compatible.
If they are compatible, the actual argument list is sorted to
correspond with the formal list, and elements for missing optional
@@ -3151,6 +3163,8 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
"call at %L", where);
return false;
}
+ else
+ a->associated_dummy = get_nonintrinsic_dummy_arg (f);
if (a->expr == NULL)
{
@@ -3680,9 +3694,12 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
/* The argument lists are compatible. We now relink a new actual
argument list with null arguments in the right places. The head
of the list remains the head. */
- for (i = 0; i < n; i++)
+ for (f = formal, i = 0; f; f = f->next, i++)
if (new_arg[i] == NULL)
- new_arg[i] = gfc_get_actual_arglist ();
+ {
+ new_arg[i] = gfc_get_actual_arglist ();
+ new_arg[i]->associated_dummy = get_nonintrinsic_dummy_arg (f);
+ }
if (na != 0)
{
@@ -3698,11 +3715,6 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
if (*ap == NULL && n > 0)
*ap = new_arg[0];
- /* Note the types of omitted optional arguments. */
- for (a = *ap, f = formal; a; a = a->next, f = f->next)
- if (a->expr == NULL && a->label == NULL)
- a->missing_arg_type = f->sym->ts.type;
-
return true;
}
@@ -5520,3 +5532,54 @@ gfc_get_formal_from_actual_arglist (gfc_symbol *sym,
f = &((*f)->next);
}
}
+
+
+const char *
+gfc_dummy_arg_get_name (gfc_dummy_arg & dummy_arg)
+{
+ switch (dummy_arg.intrinsicness)
+ {
+ case GFC_INTRINSIC_DUMMY_ARG:
+ return dummy_arg.u.intrinsic->name;
+
+ case GFC_NON_INTRINSIC_DUMMY_ARG:
+ return dummy_arg.u.non_intrinsic->sym->name;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+
+const gfc_typespec &
+gfc_dummy_arg_get_typespec (gfc_dummy_arg & dummy_arg)
+{
+ switch (dummy_arg.intrinsicness)
+ {
+ case GFC_INTRINSIC_DUMMY_ARG:
+ return dummy_arg.u.intrinsic->ts;
+
+ case GFC_NON_INTRINSIC_DUMMY_ARG:
+ return dummy_arg.u.non_intrinsic->sym->ts;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+
+bool
+gfc_dummy_arg_is_optional (gfc_dummy_arg & dummy_arg)
+{
+ switch (dummy_arg.intrinsicness)
+ {
+ case GFC_INTRINSIC_DUMMY_ARG:
+ return dummy_arg.u.intrinsic->optional;
+
+ case GFC_NON_INTRINSIC_DUMMY_ARG:
+ return dummy_arg.u.non_intrinsic->sym->attr.optional;
+
+ default:
+ gcc_unreachable ();
+ }
+}
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index 2d7d246..3682f9a 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -4237,6 +4237,18 @@ remove_nullargs (gfc_actual_arglist **ap)
}
+static gfc_dummy_arg *
+get_intrinsic_dummy_arg (gfc_intrinsic_arg *intrinsic)
+{
+ gfc_dummy_arg * const dummy_arg = gfc_get_dummy_arg ();
+
+ dummy_arg->intrinsicness = GFC_INTRINSIC_DUMMY_ARG;
+ dummy_arg->u.intrinsic = intrinsic;
+
+ return dummy_arg;
+}
+
+
/* Given an actual arglist and a formal arglist, sort the actual
arglist so that its arguments are in a one-to-one correspondence
with the format arglist. Arguments that are not present are given
@@ -4254,8 +4266,14 @@ sort_actual (const char *name, gfc_actual_arglist **ap,
remove_nullargs (ap);
actual = *ap;
+ auto_vec<gfc_intrinsic_arg *> dummy_args;
+ auto_vec<gfc_actual_arglist *> ordered_actual_args;
+
for (f = formal; f; f = f->next)
- f->actual = NULL;
+ dummy_args.safe_push (f);
+
+ ordered_actual_args.safe_grow_cleared (dummy_args.length (),
+ /* exact = */true);
f = formal;
a = actual;
@@ -4307,7 +4325,7 @@ sort_actual (const char *name, gfc_actual_arglist **ap,
}
}
- for (;;)
+ for (int i = 0;; i++)
{ /* Put the nonkeyword arguments in a 1:1 correspondence */
if (f == NULL)
break;
@@ -4317,7 +4335,7 @@ sort_actual (const char *name, gfc_actual_arglist **ap,
if (a->name != NULL)
goto keywords;
- f->actual = a;
+ ordered_actual_args[i] = a;
f = f->next;
a = a->next;
@@ -4335,7 +4353,8 @@ keywords:
to be keyword arguments. */
for (; a; a = a->next)
{
- for (f = formal; f; f = f->next)
+ int idx;
+ FOR_EACH_VEC_ELT (dummy_args, idx, f)
if (strcmp (a->name, f->name) == 0)
break;
@@ -4350,21 +4369,21 @@ keywords:
return false;
}
- if (f->actual != NULL)
+ if (ordered_actual_args[idx] != NULL)
{
gfc_error ("Argument %qs appears twice in call to %qs at %L",
f->name, name, where);
return false;
}
-
- f->actual = a;
+ ordered_actual_args[idx] = a;
}
optional:
/* At this point, all unmatched formal args must be optional. */
- for (f = formal; f; f = f->next)
+ int idx;
+ FOR_EACH_VEC_ELT (dummy_args, idx, f)
{
- if (f->actual == NULL && f->optional == 0)
+ if (ordered_actual_args[idx] == NULL && f->optional == 0)
{
gfc_error ("Missing actual argument %qs in call to %qs at %L",
f->name, name, where);
@@ -4377,21 +4396,19 @@ do_sort:
together in a way that corresponds with the formal list. */
actual = NULL;
- for (f = formal; f; f = f->next)
+ FOR_EACH_VEC_ELT (dummy_args, idx, f)
{
- if (f->actual && f->actual->label != NULL && f->ts.type)
+ a = ordered_actual_args[idx];
+ if (a && a->label != NULL && f->ts.type)
{
gfc_error ("ALTERNATE RETURN not permitted at %L", where);
return false;
}
- if (f->actual == NULL)
- {
- a = gfc_get_actual_arglist ();
- a->missing_arg_type = f->ts.type;
- }
- else
- a = f->actual;
+ if (a == NULL)
+ a = gfc_get_actual_arglist ();
+
+ a->associated_dummy = get_intrinsic_dummy_arg (f);
if (actual == NULL)
*ap = a;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index 705d232..f074a0a 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -8846,7 +8846,8 @@ resolve_select (gfc_code *code, bool select_type)
|| cp->low != cp->high))
{
gfc_error ("Logical range in CASE statement at %L is not "
- "allowed", &cp->low->where);
+ "allowed",
+ cp->low ? &cp->low->where : &cp->high->where);
t = false;
break;
}
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 7932185..2090adf 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -3010,7 +3010,8 @@ gfc_scalar_elemental_arg_saved_as_reference (gfc_ss_info * ss_info)
/* If the expression is of polymorphic type, it's actual size is not known,
so we avoid copying it anywhere. */
if (ss_info->data.scalar.dummy_arg
- && ss_info->data.scalar.dummy_arg->ts.type == BT_CLASS
+ && gfc_dummy_arg_get_typespec (*ss_info->data.scalar.dummy_arg).type
+ == BT_CLASS
&& ss_info->expr->ts.type == BT_CLASS)
return true;
@@ -11491,16 +11492,14 @@ gfc_get_intrinsic_for_expr (gfc_expr *call)
static bool
arg_evaluated_for_scalarization (gfc_intrinsic_sym *function,
- gfc_actual_arglist &actual_arg, int arg_num)
+ gfc_dummy_arg *dummy_arg)
{
- if (function != NULL)
+ if (function != NULL && dummy_arg != NULL)
{
switch (function->id)
{
case GFC_ISYM_INDEX:
- if ((actual_arg.name == NULL && arg_num == 3)
- || (actual_arg.name != NULL
- && strcmp ("kind", actual_arg.name) == 0))
+ if (strcmp ("kind", gfc_dummy_arg_get_name (*dummy_arg)) == 0)
return false;
/* Fallthrough. */
@@ -11521,9 +11520,8 @@ arg_evaluated_for_scalarization (gfc_intrinsic_sym *function,
gfc_ss *
gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
gfc_intrinsic_sym *intrinsic_sym,
- gfc_symbol *proc_ifc, gfc_ss_type type)
+ gfc_ss_type type)
{
- gfc_formal_arglist *dummy_arg;
int scalar;
gfc_ss *head;
gfc_ss *tail;
@@ -11532,19 +11530,14 @@ gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
head = gfc_ss_terminator;
tail = NULL;
- if (proc_ifc)
- dummy_arg = gfc_sym_get_dummy_args (proc_ifc);
- else
- dummy_arg = NULL;
-
- int arg_num = 0;
scalar = 1;
for (; arg; arg = arg->next)
{
+ gfc_dummy_arg * const dummy_arg = arg->associated_dummy;
if (!arg->expr
|| arg->expr->expr_type == EXPR_NULL
- || !arg_evaluated_for_scalarization (intrinsic_sym, *arg, arg_num))
- goto loop_continue;
+ || !arg_evaluated_for_scalarization (intrinsic_sym, dummy_arg))
+ continue;
newss = gfc_walk_subexpr (head, arg->expr);
if (newss == head)
@@ -11554,13 +11547,13 @@ gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
newss = gfc_get_scalar_ss (head, arg->expr);
newss->info->type = type;
if (dummy_arg)
- newss->info->data.scalar.dummy_arg = dummy_arg->sym;
+ newss->info->data.scalar.dummy_arg = dummy_arg;
}
else
scalar = 0;
if (dummy_arg != NULL
- && dummy_arg->sym->attr.optional
+ && gfc_dummy_arg_is_optional (*dummy_arg)
&& arg->expr->expr_type == EXPR_VARIABLE
&& (gfc_expr_attr (arg->expr).optional
|| gfc_expr_attr (arg->expr).allocatable
@@ -11574,11 +11567,6 @@ gfc_walk_elemental_function_args (gfc_ss * ss, gfc_actual_arglist *arg,
while (tail->next != gfc_ss_terminator)
tail = tail->next;
}
-
-loop_continue:
- arg_num++;
- if (dummy_arg != NULL)
- dummy_arg = dummy_arg->next;
}
if (scalar)
@@ -11638,7 +11626,6 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
ss = gfc_walk_elemental_function_args (old_ss,
expr->value.function.actual,
gfc_get_intrinsic_for_expr (expr),
- gfc_get_proc_ifc_for_expr (expr),
GFC_SS_REFERENCE);
if (ss != old_ss
&& (comp
diff --git a/gcc/fortran/trans-array.h b/gcc/fortran/trans-array.h
index 8f806c3..9c4bd06 100644
--- a/gcc/fortran/trans-array.h
+++ b/gcc/fortran/trans-array.h
@@ -87,7 +87,7 @@ gfc_ss *gfc_walk_array_ref (gfc_ss *, gfc_expr *, gfc_ref * ref);
/* Walk the arguments of an elemental function. */
gfc_ss *gfc_walk_elemental_function_args (gfc_ss *, gfc_actual_arglist *,
gfc_intrinsic_sym *,
- gfc_symbol *, gfc_ss_type);
+ gfc_ss_type);
/* Walk an intrinsic function. */
gfc_ss *gfc_walk_intrinsic_function (gfc_ss *, gfc_expr *,
gfc_intrinsic_sym *);
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index e7aec38..bc502c0 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -6157,7 +6157,10 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
{
/* Pass a NULL pointer for an absent arg. */
parmse.expr = null_pointer_node;
- if (arg->missing_arg_type == BT_CHARACTER)
+ gfc_dummy_arg * const dummy_arg = arg->associated_dummy;
+ if (dummy_arg
+ && gfc_dummy_arg_get_typespec (*dummy_arg).type
+ == BT_CHARACTER)
parmse.string_length = build_int_cst (gfc_charlen_type_node,
0);
}
@@ -6174,7 +6177,9 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
|| !CLASS_DATA (fsym)->attr.allocatable));
gfc_init_se (&parmse, NULL);
parmse.expr = null_pointer_node;
- if (arg->missing_arg_type == BT_CHARACTER)
+ if (arg->associated_dummy
+ && gfc_dummy_arg_get_typespec (*arg->associated_dummy).type
+ == BT_CHARACTER)
parmse.string_length = build_int_cst (gfc_charlen_type_node, 0);
}
else if (fsym && fsym->ts.type == BT_CLASS
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 3f86791..909821d 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -4555,6 +4555,18 @@ rad2deg (int kind)
}
+static gfc_intrinsic_map_t *
+gfc_lookup_intrinsic (gfc_isym_id id)
+{
+ gfc_intrinsic_map_t *m = gfc_intrinsic_map;
+ for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
+ if (id == m->id)
+ break;
+ gcc_assert (id == m->id);
+ return m;
+}
+
+
/* ACOSD(x) is translated into ACOS(x) * 180 / pi.
ASIND(x) is translated into ASIN(x) * 180 / pi.
ATAND(x) is translated into ATAN(x) * 180 / pi. */
@@ -4565,20 +4577,27 @@ gfc_conv_intrinsic_atrigd (gfc_se * se, gfc_expr * expr, gfc_isym_id id)
tree arg;
tree atrigd;
tree type;
+ gfc_intrinsic_map_t *m;
type = gfc_typenode_for_spec (&expr->ts);
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
- if (id == GFC_ISYM_ACOSD)
- atrigd = gfc_builtin_decl_for_float_kind (BUILT_IN_ACOS, expr->ts.kind);
- else if (id == GFC_ISYM_ASIND)
- atrigd = gfc_builtin_decl_for_float_kind (BUILT_IN_ASIN, expr->ts.kind);
- else if (id == GFC_ISYM_ATAND)
- atrigd = gfc_builtin_decl_for_float_kind (BUILT_IN_ATAN, expr->ts.kind);
- else
- gcc_unreachable ();
-
+ switch (id)
+ {
+ case GFC_ISYM_ACOSD:
+ m = gfc_lookup_intrinsic (GFC_ISYM_ACOS);
+ break;
+ case GFC_ISYM_ASIND:
+ m = gfc_lookup_intrinsic (GFC_ISYM_ASIN);
+ break;
+ case GFC_ISYM_ATAND:
+ m = gfc_lookup_intrinsic (GFC_ISYM_ATAN);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ atrigd = gfc_get_intrinsic_lib_fndecl (m, expr);
atrigd = build_call_expr_loc (input_location, atrigd, 1, arg);
se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atrigd,
@@ -4614,13 +4633,9 @@ gfc_conv_intrinsic_cotan (gfc_se *se, gfc_expr *expr)
mpfr_clear (pio2);
/* Find tan builtin function. */
- m = gfc_intrinsic_map;
- for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
- if (GFC_ISYM_TAN == m->id)
- break;
-
- tmp = fold_build2_loc (input_location, PLUS_EXPR, type, arg, tmp);
+ m = gfc_lookup_intrinsic (GFC_ISYM_TAN);
tan = gfc_get_intrinsic_lib_fndecl (m, expr);
+ tmp = fold_build2_loc (input_location, PLUS_EXPR, type, arg, tmp);
tan = build_call_expr_loc (input_location, tan, 1, tmp);
se->expr = fold_build1_loc (input_location, NEGATE_EXPR, type, tan);
}
@@ -4630,20 +4645,12 @@ gfc_conv_intrinsic_cotan (gfc_se *se, gfc_expr *expr)
tree cos;
/* Find cos builtin function. */
- m = gfc_intrinsic_map;
- for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
- if (GFC_ISYM_COS == m->id)
- break;
-
+ m = gfc_lookup_intrinsic (GFC_ISYM_COS);
cos = gfc_get_intrinsic_lib_fndecl (m, expr);
cos = build_call_expr_loc (input_location, cos, 1, arg);
/* Find sin builtin function. */
- m = gfc_intrinsic_map;
- for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
- if (GFC_ISYM_SIN == m->id)
- break;
-
+ m = gfc_lookup_intrinsic (GFC_ISYM_SIN);
sin = gfc_get_intrinsic_lib_fndecl (m, expr);
sin = build_call_expr_loc (input_location, sin, 1, arg);
@@ -4675,11 +4682,7 @@ gfc_conv_intrinsic_cotand (gfc_se *se, gfc_expr *expr)
mpfr_clear (ninety);
/* Find tand. */
- gfc_intrinsic_map_t *m = gfc_intrinsic_map;
- for (; m->id != GFC_ISYM_NONE || m->double_built_in != END_BUILTINS; m++)
- if (GFC_ISYM_TAND == m->id)
- break;
-
+ gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_TAND);
tree tand = gfc_get_intrinsic_lib_fndecl (m, expr);
tand = build_call_expr_loc (input_location, tand, 1, arg);
@@ -4699,7 +4702,8 @@ gfc_conv_intrinsic_atan2d (gfc_se *se, gfc_expr *expr)
gfc_conv_intrinsic_function_args (se, expr, args, 2);
type = TREE_TYPE (args[0]);
- atan2d = gfc_builtin_decl_for_float_kind (BUILT_IN_ATAN2, expr->ts.kind);
+ gfc_intrinsic_map_t *m = gfc_lookup_intrinsic (GFC_ISYM_ATAN2);
+ atan2d = gfc_get_intrinsic_lib_fndecl (m, expr);
atan2d = build_call_expr_loc (input_location, atan2d, 2, args[0], args[1]);
se->expr = fold_build2_loc (input_location, MULT_EXPR, type, atan2d,
@@ -11085,7 +11089,7 @@ gfc_walk_intrinsic_function (gfc_ss * ss, gfc_expr * expr,
if (isym->elemental)
return gfc_walk_elemental_function_args (ss, expr->value.function.actual,
expr->value.function.isym,
- NULL, GFC_SS_SCALAR);
+ GFC_SS_SCALAR);
if (expr->rank == 0)
return ss;
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index bdf7957..1fc6d3a 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -375,27 +375,6 @@ get_intrinsic_for_code (gfc_code *code)
}
-/* Get the interface symbol for the procedure corresponding to the given call.
- We can't get the procedure symbol directly as we have to handle the case
- of (deferred) type-bound procedures. */
-
-static gfc_symbol *
-get_proc_ifc_for_call (gfc_code *c)
-{
- gfc_symbol *sym;
-
- gcc_assert (c->op == EXEC_ASSIGN_CALL || c->op == EXEC_CALL);
-
- sym = gfc_get_proc_ifc_for_expr (c->expr1);
-
- /* Fall back/last resort try. */
- if (sym == NULL)
- sym = c->resolved_sym;
-
- return sym;
-}
-
-
/* Translate the CALL statement. Builds a call to an F95 subroutine. */
tree
@@ -422,7 +401,6 @@ gfc_trans_call (gfc_code * code, bool dependency_check,
if (code->resolved_sym->attr.elemental)
ss = gfc_walk_elemental_function_args (ss, code->ext.actual,
get_intrinsic_for_code (code),
- get_proc_ifc_for_call (code),
GFC_SS_REFERENCE);
/* MVBITS is inlined but needs the dependency checking found here. */
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index e5d36d5..eec4aa6 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3459,8 +3459,8 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
if (!integer_zerop (dtype_off))
t = fold_build_pointer_plus (t, rank_off);
- t = build1 (NOP_EXPR, build_pointer_type (gfc_array_index_type), t);
- t = build1 (INDIRECT_REF, gfc_array_index_type, t);
+ t = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (field)), t);
+ t = build1 (INDIRECT_REF, TREE_TYPE (field), t);
info->rank = t;
t = build0 (PLACEHOLDER_EXPR, TREE_TYPE (dim_off));
t = size_binop (MULT_EXPR, t, dim_size);
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 0d4eed2..15012a3 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -266,8 +266,8 @@ typedef struct gfc_ss_info
struct
{
/* If the scalar is passed as actual argument to an (elemental) procedure,
- this is the symbol of the corresponding dummy argument. */
- gfc_symbol *dummy_arg;
+ this is the corresponding dummy argument. */
+ gfc_dummy_arg *dummy_arg;
tree value;
/* Tells that the scalar is a reference to a variable that might
be present on the lhs, so that we should evaluate the value
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 506c2ac..6ff2278 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -5098,7 +5098,8 @@ process_command (unsigned int decoded_options_count,
bool explicit_dumpdir = dumpdir;
- if (!save_temps_overrides_dumpdir && explicit_dumpdir)
+ if ((!save_temps_overrides_dumpdir && explicit_dumpdir)
+ || (output_file && not_actual_file_p (output_file)))
{
/* Do nothing. */
}
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 32ba5be..b6abed1 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -440,6 +440,10 @@ gt_pch_save (FILE *f)
(The extra work goes in HOST_HOOKS_GT_PCH_GET_ADDRESS and
HOST_HOOKS_GT_PCH_USE_ADDRESS.) */
mmi.preferred_base = host_hooks.gt_pch_get_address (mmi.size, fileno (f));
+ /* If the host cannot supply any suitable address for this, we are stuck. */
+ if (mmi.preferred_base == NULL)
+ fatal_error (input_location,
+ "cannot write PCH file: required memory segment unavailable");
ggc_pch_this_base (state.d, mmi.preferred_base);
@@ -589,6 +593,13 @@ gt_pch_restore (FILE *f)
struct mmap_info mmi;
int result;
+ /* We are about to reload the line maps along with the rest of the PCH
+ data, which means that the (loaded) ones cannot be guaranteed to be
+ in any valid state for reporting diagnostics that happen during the
+ load. Save the current table (and use it during the loading process
+ below). */
+ class line_maps *save_line_table = line_table;
+
/* Delete any deletable objects. This makes ggc_pch_read much
faster, as it can be sure that no GCable objects remain other
than the ones just read in. */
@@ -603,20 +614,40 @@ gt_pch_restore (FILE *f)
fatal_error (input_location, "cannot read PCH file: %m");
/* Read in all the global pointers, in 6 easy loops. */
+ bool error_reading_pointers = false;
for (rt = gt_ggc_rtab; *rt; rt++)
for (rti = *rt; rti->base != NULL; rti++)
for (i = 0; i < rti->nelt; i++)
if (fread ((char *)rti->base + rti->stride * i,
sizeof (void *), 1, f) != 1)
- fatal_error (input_location, "cannot read PCH file: %m");
+ error_reading_pointers = true;
+
+ /* Stash the newly read-in line table pointer - it does not point to
+ anything meaningful yet, so swap the old one back in. */
+ class line_maps *new_line_table = line_table;
+ line_table = save_line_table;
+ if (error_reading_pointers)
+ fatal_error (input_location, "cannot read PCH file: %m");
if (fread (&mmi, sizeof (mmi), 1, f) != 1)
fatal_error (input_location, "cannot read PCH file: %m");
result = host_hooks.gt_pch_use_address (mmi.preferred_base, mmi.size,
fileno (f), mmi.offset);
+
+ /* We could not mmap or otherwise allocate the required memory at the
+ address needed. */
if (result < 0)
- fatal_error (input_location, "had to relocate PCH");
+ {
+ sorry_at (input_location, "PCH relocation is not yet supported");
+ /* There is no point in continuing from here, we will only end up
+ with a crashed (most likely hanging) compiler. */
+ exit (-1);
+ }
+
+ /* (0) We allocated memory, but did not mmap the file, so we need to read
+ the data in manually. (>0) Otherwise the mmap succeed for the address
+ we wanted. */
if (result == 0)
{
if (fseek (f, mmi.offset, SEEK_SET) != 0
@@ -629,6 +660,10 @@ gt_pch_restore (FILE *f)
ggc_pch_read (f, mmi.preferred_base);
gt_pch_restore_stringpool ();
+
+ /* Barring corruption of the PCH file, the restored line table should be
+ complete and usable. */
+ line_table = new_line_table;
}
/* Default version of HOST_HOOKS_GT_PCH_GET_ADDRESS when mmap is not present.
diff --git a/gcc/gimple-array-bounds.cc b/gcc/gimple-array-bounds.cc
index a353559..ddb99d2 100644
--- a/gcc/gimple-array-bounds.cc
+++ b/gcc/gimple-array-bounds.cc
@@ -372,31 +372,6 @@ array_bounds_checker::check_array_ref (location_t location, tree ref,
return warned;
}
-/* Wrapper around build_array_type_nelts that makes sure the array
- can be created at all and handles zero sized arrays specially. */
-
-static tree
-build_printable_array_type (tree eltype, unsigned HOST_WIDE_INT nelts)
-{
- if (TYPE_SIZE_UNIT (eltype)
- && TREE_CODE (TYPE_SIZE_UNIT (eltype)) == INTEGER_CST
- && !integer_zerop (TYPE_SIZE_UNIT (eltype))
- && TYPE_ALIGN_UNIT (eltype) > 1
- && wi::zext (wi::to_wide (TYPE_SIZE_UNIT (eltype)),
- ffs_hwi (TYPE_ALIGN_UNIT (eltype)) - 1) != 0)
- eltype = TYPE_MAIN_VARIANT (eltype);
-
- if (nelts)
- return build_array_type_nelts (eltype, nelts);
-
- tree idxtype = build_range_type (sizetype, size_zero_node, NULL_TREE);
- tree arrtype = build_array_type (eltype, idxtype);
- arrtype = build_distinct_type_copy (TYPE_MAIN_VARIANT (arrtype));
- TYPE_SIZE (arrtype) = bitsize_zero_node;
- TYPE_SIZE_UNIT (arrtype) = size_zero_node;
- return arrtype;
-}
-
/* Checks one MEM_REF in REF, located at LOCATION, for out-of-bounds
references to string constants. If VRP can determine that the array
subscript is a constant, check if it is outside valid range.
diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c
index 765726c..ad9703e 100644
--- a/gcc/gimple-fold.c
+++ b/gcc/gimple-fold.c
@@ -86,7 +86,7 @@ enum strlen_range_kind {
};
static bool
-get_range_strlen (tree, bitmap *, strlen_range_kind, c_strlen_data *, unsigned);
+get_range_strlen (tree, bitmap, strlen_range_kind, c_strlen_data *, unsigned);
/* Return true when DECL can be referenced from current unit.
FROM_DECL (if non-null) specify constructor of variable DECL was taken from.
@@ -1525,7 +1525,7 @@ gimple_fold_builtin_memset (gimple_stmt_iterator *gsi, tree c, tree len)
/* Helper of get_range_strlen for ARG that is not an SSA_NAME. */
static bool
-get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind,
+get_range_strlen_tree (tree arg, bitmap visited, strlen_range_kind rkind,
c_strlen_data *pdata, unsigned eltsize)
{
gcc_assert (TREE_CODE (arg) != SSA_NAME);
@@ -1849,7 +1849,7 @@ get_range_strlen_tree (tree arg, bitmap *visited, strlen_range_kind rkind,
Return true if *PDATA was successfully populated and false otherwise. */
static bool
-get_range_strlen (tree arg, bitmap *visited,
+get_range_strlen (tree arg, bitmap visited,
strlen_range_kind rkind,
c_strlen_data *pdata, unsigned eltsize)
{
@@ -1863,9 +1863,7 @@ get_range_strlen (tree arg, bitmap *visited,
return false;
/* If we were already here, break the infinite cycle. */
- if (!*visited)
- *visited = BITMAP_ALLOC (NULL);
- if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (arg)))
+ if (!bitmap_set_bit (visited, SSA_NAME_VERSION (arg)))
return true;
tree var = arg;
@@ -1962,10 +1960,10 @@ get_range_strlen (tree arg, bitmap *visited,
bool
get_range_strlen (tree arg, c_strlen_data *pdata, unsigned eltsize)
{
- bitmap visited = NULL;
+ auto_bitmap visited;
tree maxbound = pdata->maxbound;
- if (!get_range_strlen (arg, &visited, SRK_LENRANGE, pdata, eltsize))
+ if (!get_range_strlen (arg, visited, SRK_LENRANGE, pdata, eltsize))
{
/* On failure extend the length range to an impossible maximum
(a valid MAXLEN must be less than PTRDIFF_MAX - 1). Other
@@ -1981,9 +1979,6 @@ get_range_strlen (tree arg, c_strlen_data *pdata, unsigned eltsize)
if (maxbound && pdata->maxbound == maxbound)
pdata->maxbound = build_all_ones_cst (size_type_node);
- if (visited)
- BITMAP_FREE (visited);
-
return !integer_all_onesp (pdata->maxlen);
}
@@ -2005,19 +2000,16 @@ get_maxval_strlen (tree arg, strlen_range_kind rkind, tree *nonstr = NULL)
/* ARG must have an integral type when RKIND says so. */
gcc_assert (rkind != SRK_INT_VALUE || INTEGRAL_TYPE_P (TREE_TYPE (arg)));
- bitmap visited = NULL;
+ auto_bitmap visited;
/* Reset DATA.MAXLEN if the call fails or when DATA.MAXLEN
is unbounded. */
c_strlen_data lendata = { };
- if (!get_range_strlen (arg, &visited, rkind, &lendata, /* eltsize = */1))
+ if (!get_range_strlen (arg, visited, rkind, &lendata, /* eltsize = */1))
lendata.maxlen = NULL_TREE;
else if (lendata.maxlen && integer_all_onesp (lendata.maxlen))
lendata.maxlen = NULL_TREE;
- if (visited)
- BITMAP_FREE (visited);
-
if (nonstr)
{
/* For callers prepared to handle unterminated arrays set
diff --git a/gcc/gimple-harden-conditionals.cc b/gcc/gimple-harden-conditionals.cc
index 8916420..cfa2361 100644
--- a/gcc/gimple-harden-conditionals.cc
+++ b/gcc/gimple-harden-conditionals.cc
@@ -123,7 +123,14 @@ detach_value (location_t loc, gimple_stmt_iterator *gsip, tree val)
return val;
}
- tree ret = copy_ssa_name (val);
+ /* Create a SSA "copy" of VAL. This could be an anonymous
+ temporary, but it's nice to have it named after the corresponding
+ variable. Alas, when VAL is a DECL_BY_REFERENCE RESULT_DECL,
+ setting (a copy of) it would be flagged by checking, so we don't
+ use copy_ssa_name: we create an anonymous SSA name, and then give
+ it the same identifier (rather than decl) as VAL. */
+ tree ret = make_ssa_name (TREE_TYPE (val));
+ SET_SSA_NAME_VAR_OR_IDENTIFIER (ret, SSA_NAME_IDENTIFIER (val));
/* Output asm ("" : "=g" (ret) : "0" (val)); */
vec<tree, va_gc> *inputs = NULL;
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 608d98b..ec9690b 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -720,14 +720,20 @@ fold_using_range::range_of_address (irange &r, gimple *stmt, fur_source &src)
}
/* If &X->a is equal to X, the range of X is the result. */
if (off_cst && known_eq (off, 0))
- return true;
+ return true;
else if (flag_delete_null_pointer_checks
&& !TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr)))
{
- /* For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't
- allow going from non-NULL pointer to NULL. */
- if(!range_includes_zero_p (&r))
- return true;
+ /* For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't
+ allow going from non-NULL pointer to NULL. */
+ if (!range_includes_zero_p (&r))
+ {
+ /* We could here instead adjust r by off >> LOG2_BITS_PER_UNIT
+ using POINTER_PLUS_EXPR if off_cst and just fall back to
+ this. */
+ r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
+ return true;
+ }
}
/* If MEM_REF has a "positive" offset, consider it non-NULL
always, for -fdelete-null-pointer-checks also "negative"
diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index fb2d571..911d7ac 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -331,7 +331,6 @@ range_def_chain::get_def_chain (tree name)
{
tree ssa1, ssa2, ssa3;
unsigned v = SSA_NAME_VERSION (name);
- bool is_logical = false;
// If it has already been processed, just return the cached value.
if (has_def_chain (name))
@@ -348,15 +347,6 @@ range_def_chain::get_def_chain (tree name)
gimple *stmt = SSA_NAME_DEF_STMT (name);
if (gimple_range_handler (stmt))
{
- is_logical = is_gimple_logical_p (stmt);
- // Terminate the def chains if we see too many cascading logical stmts.
- if (is_logical)
- {
- if (m_logical_depth == param_ranger_logical_depth)
- return NULL;
- m_logical_depth++;
- }
-
ssa1 = gimple_range_ssa_p (gimple_range_operand1 (stmt));
ssa2 = gimple_range_ssa_p (gimple_range_operand2 (stmt));
ssa3 = NULL_TREE;
@@ -376,6 +366,14 @@ range_def_chain::get_def_chain (tree name)
return NULL;
}
+ // Terminate the def chains if we see too many cascading stmts.
+ if (m_logical_depth == param_ranger_logical_depth)
+ return NULL;
+
+ // Increase the depth if we have a pair of ssa-names.
+ if (ssa1 && ssa2)
+ m_logical_depth++;
+
register_dependency (name, ssa1, gimple_bb (stmt));
register_dependency (name, ssa2, gimple_bb (stmt));
register_dependency (name, ssa3, gimple_bb (stmt));
@@ -383,7 +381,7 @@ range_def_chain::get_def_chain (tree name)
if (!ssa1 && !ssa2 & !ssa3)
set_import (m_def_chain[v], name, NULL);
- if (is_logical)
+ if (ssa1 && ssa2)
m_logical_depth--;
return m_def_chain[v].bm;
diff --git a/gcc/gimple-ssa-warn-access.cc b/gcc/gimple-ssa-warn-access.cc
index 22c791d..48bf8aa 100644
--- a/gcc/gimple-ssa-warn-access.cc
+++ b/gcc/gimple-ssa-warn-access.cc
@@ -2978,10 +2978,16 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
continue;
tree ptrtype = fntype_argno_type (fntype, ptridx);
+ if (!ptrtype)
+ /* A function with a prototype was redeclared without one and
+ the protype has been lost. See pr102759. Avoid dealing
+ with this pathological case. */
+ return;
+
tree argtype = TREE_TYPE (ptrtype);
- /* The size of the access by the call. */
- tree access_size;
+ /* The size of the access by the call in elements. */
+ tree access_nelts;
if (sizidx == -1)
{
/* If only the pointer attribute operand was specified and
@@ -2991,17 +2997,17 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
if the pointer is also declared with attribute nonnull. */
if (access.second.minsize
&& access.second.minsize != HOST_WIDE_INT_M1U)
- access_size = build_int_cstu (sizetype, access.second.minsize);
+ access_nelts = build_int_cstu (sizetype, access.second.minsize);
else
- access_size = size_one_node;
+ access_nelts = size_one_node;
}
else
- access_size = rwm->get (sizidx)->size;
+ access_nelts = rwm->get (sizidx)->size;
/* Format the value or range to avoid an explosion of messages. */
char sizstr[80];
tree sizrng[2] = { size_zero_node, build_all_ones_cst (sizetype) };
- if (get_size_range (m_ptr_qry.rvals, access_size, stmt, sizrng, 1))
+ if (get_size_range (m_ptr_qry.rvals, access_nelts, stmt, sizrng, 1))
{
char *s0 = print_generic_expr_to_str (sizrng[0]);
if (tree_int_cst_equal (sizrng[0], sizrng[1]))
@@ -3059,6 +3065,8 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
}
}
+ /* The size of the access by the call in bytes. */
+ tree access_size = NULL_TREE;
if (tree_int_cst_sgn (sizrng[0]) >= 0)
{
if (COMPLETE_TYPE_P (argtype))
@@ -3075,9 +3083,9 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
access_size = wide_int_to_tree (sizetype, minsize);
}
}
+ else
+ access_size = access_nelts;
}
- else
- access_size = NULL_TREE;
if (integer_zerop (ptr))
{
@@ -3172,8 +3180,13 @@ pass_waccess::maybe_check_access_sizes (rdwr_map *rwm, tree fndecl, tree fntype,
if (opt_warned != no_warning)
{
if (access.second.internal_p)
- inform (loc, "referencing argument %u of type %qT",
- ptridx + 1, ptrtype);
+ {
+ unsigned HOST_WIDE_INT nelts =
+ access_nelts ? access.second.minsize : HOST_WIDE_INT_M1U;
+ tree arrtype = build_printable_array_type (argtype, nelts);
+ inform (loc, "referencing argument %u of type %qT",
+ ptridx + 1, arrtype);
+ }
else
/* If check_access issued a warning above, append the relevant
attribute to the string. */
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 1602a62..467b135 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -2964,7 +2964,9 @@ gimplify_var_or_parm_decl (tree *expr_p)
declaration, for which we've already issued an error. It would
be really nice if the front end wouldn't leak these at all.
Currently the only known culprit is C++ destructors, as seen
- in g++.old-deja/g++.jason/binding.C. */
+ in g++.old-deja/g++.jason/binding.C.
+ Another possible culpit are size expressions for variably modified
+ types which are lost in the FE or not gimplified correctly. */
if (VAR_P (decl)
&& !DECL_SEEN_IN_BIND_EXPR_P (decl)
&& !TREE_STATIC (decl) && !DECL_EXTERNAL (decl)
@@ -3109,16 +3111,22 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
expression until we deal with any variable bounds, sizes, or
positions in order to deal with PLACEHOLDER_EXPRs.
- So we do this in three steps. First we deal with the annotations
- for any variables in the components, then we gimplify the base,
- then we gimplify any indices, from left to right. */
+ The base expression may contain a statement expression that
+ has declarations used in size expressions, so has to be
+ gimplified before gimplifying the size expressions.
+
+ So we do this in three steps. First we deal with variable
+ bounds, sizes, and positions, then we gimplify the base,
+ then we deal with the annotations for any variables in the
+ components and any indices, from left to right. */
+
for (i = expr_stack.length () - 1; i >= 0; i--)
{
tree t = expr_stack[i];
if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
{
- /* Gimplify the low bound and element type size and put them into
+ /* Deal with the low bound and element type size and put them into
the ARRAY_REF. If these values are set, they have already been
gimplified. */
if (TREE_OPERAND (t, 2) == NULL_TREE)
@@ -3127,18 +3135,8 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
if (!is_gimple_min_invariant (low))
{
TREE_OPERAND (t, 2) = low;
- tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
- post_p, is_gimple_reg,
- fb_rvalue);
- ret = MIN (ret, tret);
}
}
- else
- {
- tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
- is_gimple_reg, fb_rvalue);
- ret = MIN (ret, tret);
- }
if (TREE_OPERAND (t, 3) == NULL_TREE)
{
@@ -3155,18 +3153,8 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
elmt_size, factor);
TREE_OPERAND (t, 3) = elmt_size;
- tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p,
- post_p, is_gimple_reg,
- fb_rvalue);
- ret = MIN (ret, tret);
}
}
- else
- {
- tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
- is_gimple_reg, fb_rvalue);
- ret = MIN (ret, tret);
- }
}
else if (TREE_CODE (t) == COMPONENT_REF)
{
@@ -3186,18 +3174,8 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
offset, factor);
TREE_OPERAND (t, 2) = offset;
- tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p,
- post_p, is_gimple_reg,
- fb_rvalue);
- ret = MIN (ret, tret);
}
}
- else
- {
- tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
- is_gimple_reg, fb_rvalue);
- ret = MIN (ret, tret);
- }
}
}
@@ -3208,21 +3186,34 @@ gimplify_compound_lval (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
fallback | fb_lvalue);
ret = MIN (ret, tret);
- /* And finally, the indices and operands of ARRAY_REF. During this
- loop we also remove any useless conversions. */
+ /* Step 3: gimplify size expressions and the indices and operands of
+ ARRAY_REF. During this loop we also remove any useless conversions. */
+
for (; expr_stack.length () > 0; )
{
tree t = expr_stack.pop ();
if (TREE_CODE (t) == ARRAY_REF || TREE_CODE (t) == ARRAY_RANGE_REF)
{
+ /* Gimplify the low bound and element type size. */
+ tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
+ is_gimple_reg, fb_rvalue);
+ ret = MIN (ret, tret);
+
+ tret = gimplify_expr (&TREE_OPERAND (t, 3), pre_p, post_p,
+ is_gimple_reg, fb_rvalue);
+ ret = MIN (ret, tret);
+
/* Gimplify the dimension. */
- if (!is_gimple_min_invariant (TREE_OPERAND (t, 1)))
- {
- tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
- is_gimple_val, fb_rvalue);
- ret = MIN (ret, tret);
- }
+ tret = gimplify_expr (&TREE_OPERAND (t, 1), pre_p, post_p,
+ is_gimple_val, fb_rvalue);
+ ret = MIN (ret, tret);
+ }
+ else if (TREE_CODE (t) == COMPONENT_REF)
+ {
+ tret = gimplify_expr (&TREE_OPERAND (t, 2), pre_p, post_p,
+ is_gimple_reg, fb_rvalue);
+ ret = MIN (ret, tret);
}
STRIP_USELESS_TYPE_CONVERSION (TREE_OPERAND (t, 0));
@@ -6927,6 +6918,8 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
{
if (!TYPE_SIZES_GIMPLIFIED (TREE_TYPE (temp)))
gimplify_type_sizes (TREE_TYPE (temp), pre_p);
+ /* FIXME: this is correct only when the size of the type does
+ not depend on expressions evaluated in init. */
gimplify_vla_decl (temp, pre_p);
}
else
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index e8fd16b..e5b85f0 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -3842,6 +3842,8 @@ first_commutative_argument (internal_fn fn)
case IFN_COND_MUL:
case IFN_COND_MIN:
case IFN_COND_MAX:
+ case IFN_COND_FMIN:
+ case IFN_COND_FMAX:
case IFN_COND_AND:
case IFN_COND_IOR:
case IFN_COND_XOR:
@@ -3961,6 +3963,8 @@ conditional_internal_fn_code (internal_fn ifn)
/* Invoke T(IFN) for each internal function IFN that also has an
IFN_COND_* form. */
#define FOR_EACH_COND_FN_PAIR(T) \
+ T (FMAX) \
+ T (FMIN) \
T (FMA) \
T (FMS) \
T (FNMA) \
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index bb13c6c..bb4d8ab 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -188,6 +188,8 @@ DEF_INTERNAL_SIGNED_OPTAB_FN (COND_MIN, ECF_CONST, first,
cond_smin, cond_umin, cond_binary)
DEF_INTERNAL_SIGNED_OPTAB_FN (COND_MAX, ECF_CONST, first,
cond_smax, cond_umax, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_FMIN, ECF_CONST, cond_fmin, cond_binary)
+DEF_INTERNAL_OPTAB_FN (COND_FMAX, ECF_CONST, cond_fmax, cond_binary)
DEF_INTERNAL_OPTAB_FN (COND_AND, ECF_CONST | ECF_NOTHROW,
cond_and, cond_binary)
DEF_INTERNAL_OPTAB_FN (COND_IOR, ECF_CONST | ECF_NOTHROW,
diff --git a/gcc/ipa-modref-tree.c b/gcc/ipa-modref-tree.c
index bbe23a5..e23d88d 100644
--- a/gcc/ipa-modref-tree.c
+++ b/gcc/ipa-modref-tree.c
@@ -27,6 +27,8 @@ along with GCC; see the file COPYING3. If not see
#include "selftest.h"
#include "tree-ssa-alias.h"
#include "gimple.h"
+#include "cgraph.h"
+#include "tree-streamer.h"
/* Return true if both accesses are the same. */
bool
@@ -458,6 +460,50 @@ modref_access_node::try_merge_with (vec <modref_access_node, va_gc> *&accesses,
i++;
}
+/* Stream out to OB. */
+
+void
+modref_access_node::stream_out (struct output_block *ob) const
+{
+ streamer_write_hwi (ob, parm_index);
+ if (parm_index != MODREF_UNKNOWN_PARM)
+ {
+ streamer_write_uhwi (ob, parm_offset_known);
+ if (parm_offset_known)
+ {
+ streamer_write_poly_int64 (ob, parm_offset);
+ streamer_write_poly_int64 (ob, offset);
+ streamer_write_poly_int64 (ob, size);
+ streamer_write_poly_int64 (ob, max_size);
+ }
+ }
+}
+
+modref_access_node
+modref_access_node::stream_in (struct lto_input_block *ib)
+{
+ int parm_index = streamer_read_hwi (ib);
+ bool parm_offset_known = false;
+ poly_int64 parm_offset = 0;
+ poly_int64 offset = 0;
+ poly_int64 size = -1;
+ poly_int64 max_size = -1;
+
+ if (parm_index != MODREF_UNKNOWN_PARM)
+ {
+ parm_offset_known = streamer_read_uhwi (ib);
+ if (parm_offset_known)
+ {
+ parm_offset = streamer_read_poly_int64 (ib);
+ offset = streamer_read_poly_int64 (ib);
+ size = streamer_read_poly_int64 (ib);
+ max_size = streamer_read_poly_int64 (ib);
+ }
+ }
+ return {offset, size, max_size, parm_offset, parm_index,
+ parm_offset_known, false};
+}
+
/* Insert access with OFFSET and SIZE.
Collapse tree if it has more than MAX_ACCESSES entries.
If RECORD_ADJUSTMENTs is true avoid too many interval extensions.
diff --git a/gcc/ipa-modref-tree.h b/gcc/ipa-modref-tree.h
index 1bf2aa8..6796e6e 100644
--- a/gcc/ipa-modref-tree.h
+++ b/gcc/ipa-modref-tree.h
@@ -99,6 +99,10 @@ struct GTY(()) modref_access_node
tree get_call_arg (const gcall *stmt) const;
/* Build ao_ref corresponding to the access and return true if succesful. */
bool get_ao_ref (const gcall *stmt, class ao_ref *ref) const;
+ /* Stream access to OB. */
+ void stream_out (struct output_block *ob) const;
+ /* Stream access in from IB. */
+ static modref_access_node stream_in (struct lto_input_block *ib);
/* Insert A into vector ACCESSES. Limit size of vector to MAX_ACCESSES and
if RECORD_ADJUSTMENT is true keep track of adjustment counts.
Return 0 if nothing changed, 1 is insertion suceeded and -1 if failed. */
@@ -283,6 +287,11 @@ struct GTY((user)) modref_base_node
struct modref_parm_map
{
+ /* Default constructor. */
+ modref_parm_map ()
+ : parm_index (MODREF_UNKNOWN_PARM), parm_offset_known (false), parm_offset ()
+ {}
+
/* Index of parameter we translate to.
Values from special_params enum are permitted too. */
int parm_index;
diff --git a/gcc/ipa-modref.c b/gcc/ipa-modref.c
index 5783430..4f93231 100644
--- a/gcc/ipa-modref.c
+++ b/gcc/ipa-modref.c
@@ -410,6 +410,8 @@ modref_summary_lto::useful_p (int ecf_flags, bool check_flags)
&& (ecf_flags & ECF_LOOPING_CONST_OR_PURE));
if (loads && !loads->every_base)
return true;
+ else
+ kills.release ();
if (ecf_flags & ECF_PURE)
return ((!side_effects || !nondeterministic)
&& (ecf_flags & ECF_LOOPING_CONST_OR_PURE));
@@ -634,6 +636,15 @@ modref_summary_lto::dump (FILE *out)
dump_lto_records (loads, out);
fprintf (out, " stores:\n");
dump_lto_records (stores, out);
+ if (kills.length ())
+ {
+ fprintf (out, " kills:\n");
+ for (auto kill : kills)
+ {
+ fprintf (out, " ");
+ kill.dump (out);
+ }
+ }
if (writes_errno)
fprintf (out, " Writes errno\n");
if (side_effects)
@@ -740,11 +751,206 @@ get_modref_function_summary (cgraph_node *func)
return r;
}
+/* Get function summary for CALL if it exists, return NULL otherwise.
+ If non-null set interposed to indicate whether function may not
+ bind to current def. In this case sometimes loads from function
+ needs to be ignored. */
+
+modref_summary *
+get_modref_function_summary (gcall *call, bool *interposed)
+{
+ tree callee = gimple_call_fndecl (call);
+ if (!callee)
+ return NULL;
+ struct cgraph_node *node = cgraph_node::get (callee);
+ if (!node)
+ return NULL;
+ modref_summary *r = get_modref_function_summary (node);
+ if (interposed && r)
+ *interposed = r->calls_interposable
+ || !node->binds_to_current_def_p ();
+ return r;
+}
+
+
namespace {
+/* Return true if ECF flags says that nondeterminsm can be ignored. */
+
+static bool
+ignore_nondeterminism_p (tree caller, int flags)
+{
+ if (flags & (ECF_CONST | ECF_PURE))
+ return true;
+ if ((flags & (ECF_NORETURN | ECF_NOTHROW)) == (ECF_NORETURN | ECF_NOTHROW)
+ || (!opt_for_fn (caller, flag_exceptions) && (flags & ECF_NORETURN)))
+ return true;
+ return false;
+}
+
+/* Return true if ECF flags says that return value can be ignored. */
+
+static bool
+ignore_retval_p (tree caller, int flags)
+{
+ if ((flags & (ECF_NORETURN | ECF_NOTHROW)) == (ECF_NORETURN | ECF_NOTHROW)
+ || (!opt_for_fn (caller, flag_exceptions) && (flags & ECF_NORETURN)))
+ return true;
+ return false;
+}
+
+/* Return true if ECF flags says that stores can be ignored. */
+
+static bool
+ignore_stores_p (tree caller, int flags)
+{
+ if (flags & (ECF_PURE | ECF_CONST | ECF_NOVOPS))
+ return true;
+ if ((flags & (ECF_NORETURN | ECF_NOTHROW)) == (ECF_NORETURN | ECF_NOTHROW)
+ || (!opt_for_fn (caller, flag_exceptions) && (flags & ECF_NORETURN)))
+ return true;
+ return false;
+}
+
+/* Determine parm_map for PTR which is supposed to be a pointer. */
+
+modref_parm_map
+parm_map_for_ptr (tree op)
+{
+ bool offset_known;
+ poly_int64 offset;
+ struct modref_parm_map parm_map;
+ gcall *call;
+
+ parm_map.parm_offset_known = false;
+ parm_map.parm_offset = 0;
+
+ offset_known = unadjusted_ptr_and_unit_offset (op, &op, &offset);
+ if (TREE_CODE (op) == SSA_NAME
+ && SSA_NAME_IS_DEFAULT_DEF (op)
+ && TREE_CODE (SSA_NAME_VAR (op)) == PARM_DECL)
+ {
+ int index = 0;
+
+ if (cfun->static_chain_decl
+ && op == ssa_default_def (cfun, cfun->static_chain_decl))
+ index = MODREF_STATIC_CHAIN_PARM;
+ else
+ for (tree t = DECL_ARGUMENTS (current_function_decl);
+ t != SSA_NAME_VAR (op); t = DECL_CHAIN (t))
+ index++;
+ parm_map.parm_index = index;
+ parm_map.parm_offset_known = offset_known;
+ parm_map.parm_offset = offset;
+ }
+ else if (points_to_local_or_readonly_memory_p (op))
+ parm_map.parm_index = MODREF_LOCAL_MEMORY_PARM;
+ /* Memory allocated in the function is not visible to caller before the
+ call and thus we do not need to record it as load/stores/kills. */
+ else if (TREE_CODE (op) == SSA_NAME
+ && (call = dyn_cast<gcall *>(SSA_NAME_DEF_STMT (op))) != NULL
+ && gimple_call_flags (call) & ECF_MALLOC)
+ parm_map.parm_index = MODREF_LOCAL_MEMORY_PARM;
+ else
+ parm_map.parm_index = MODREF_UNKNOWN_PARM;
+ return parm_map;
+}
+
+/* Analyze memory accesses (loads, stores and kills) performed
+ by the function. Set also side_effects, calls_interposable
+ and nondeterminism flags. */
+
+class modref_access_analysis
+{
+public:
+ modref_access_analysis (bool ipa, modref_summary *summary,
+ modref_summary_lto *summary_lto)
+ : m_summary (summary), m_summary_lto (summary_lto), m_ipa (ipa)
+ {
+ }
+ void analyze ();
+private:
+ bool set_side_effects ();
+ bool set_nondeterministic ();
+ static modref_access_node get_access (ao_ref *ref);
+ static void record_access (modref_records *, ao_ref *, modref_access_node &);
+ static void record_access_lto (modref_records_lto *, ao_ref *,
+ modref_access_node &a);
+ bool record_access_p (tree);
+ bool record_unknown_load ();
+ bool record_unknown_store ();
+ bool merge_call_side_effects (gimple *, modref_summary *,
+ cgraph_node *, bool);
+ modref_access_node get_access_for_fnspec (gcall *, attr_fnspec &,
+ unsigned int, modref_parm_map &);
+ void process_fnspec (gcall *);
+ void analyze_call (gcall *);
+ static bool analyze_load (gimple *, tree, tree, void *);
+ static bool analyze_store (gimple *, tree, tree, void *);
+ void analyze_stmt (gimple *, bool);
+ void propagate ();
+
+ /* Summary being computed.
+ We work eitehr with m_summary or m_summary_lto. Never on both. */
+ modref_summary *m_summary;
+ modref_summary_lto *m_summary_lto;
+ /* Recursive calls needs simplisitc dataflow after analysis finished.
+ Collect all calls into this vector during analysis and later process
+ them in propagate. */
+ auto_vec <gimple *, 32> m_recursive_calls;
+ /* ECF flags of function being analysed. */
+ int m_ecf_flags;
+ /* True if IPA propagation will be done later. */
+ bool m_ipa;
+ /* Set true if statement currently analysed is known to be
+ executed each time function is called. */
+ bool m_always_executed;
+};
+
+/* Set side_effects flag and return if someting changed. */
+
+bool
+modref_access_analysis::set_side_effects ()
+{
+ bool changed = false;
+
+ if (m_summary && !m_summary->side_effects)
+ {
+ m_summary->side_effects = true;
+ changed = true;
+ }
+ if (m_summary_lto && !m_summary_lto->side_effects)
+ {
+ m_summary_lto->side_effects = true;
+ changed = true;
+ }
+ return changed;
+}
+
+/* Set nondeterministic flag and return if someting changed. */
+
+bool
+modref_access_analysis::set_nondeterministic ()
+{
+ bool changed = false;
+
+ if (m_summary && !m_summary->nondeterministic)
+ {
+ m_summary->side_effects = m_summary->nondeterministic = true;
+ changed = true;
+ }
+ if (m_summary_lto && !m_summary_lto->nondeterministic)
+ {
+ m_summary_lto->side_effects = m_summary_lto->nondeterministic = true;
+ changed = true;
+ }
+ return changed;
+}
+
/* Construct modref_access_node from REF. */
-static modref_access_node
-get_access (ao_ref *ref)
+
+modref_access_node
+modref_access_analysis::get_access (ao_ref *ref)
{
tree base;
@@ -754,33 +960,19 @@ get_access (ao_ref *ref)
if (TREE_CODE (base) == MEM_REF || TREE_CODE (base) == TARGET_MEM_REF)
{
tree memref = base;
- base = TREE_OPERAND (base, 0);
+ modref_parm_map m = parm_map_for_ptr (TREE_OPERAND (base, 0));
- if (TREE_CODE (base) == SSA_NAME
- && SSA_NAME_IS_DEFAULT_DEF (base)
- && TREE_CODE (SSA_NAME_VAR (base)) == PARM_DECL)
- {
- a.parm_index = 0;
- if (cfun->static_chain_decl
- && base == ssa_default_def (cfun, cfun->static_chain_decl))
- a.parm_index = MODREF_STATIC_CHAIN_PARM;
- else
- for (tree t = DECL_ARGUMENTS (current_function_decl);
- t != SSA_NAME_VAR (base); t = DECL_CHAIN (t))
- a.parm_index++;
- }
- else
- a.parm_index = MODREF_UNKNOWN_PARM;
-
- if (a.parm_index != MODREF_UNKNOWN_PARM
- && TREE_CODE (memref) == MEM_REF)
+ a.parm_index = m.parm_index;
+ if (a.parm_index != MODREF_UNKNOWN_PARM && TREE_CODE (memref) == MEM_REF)
{
a.parm_offset_known
= wi::to_poly_wide (TREE_OPERAND
(memref, 1)).to_shwi (&a.parm_offset);
+ if (a.parm_offset_known && m.parm_offset_known)
+ a.parm_offset += m.parm_offset;
+ else
+ a.parm_offset_known = false;
}
- else
- a.parm_offset_known = false;
}
else
a.parm_index = MODREF_UNKNOWN_PARM;
@@ -789,8 +981,10 @@ get_access (ao_ref *ref)
/* Record access into the modref_records data structure. */
-static void
-record_access (modref_records *tt, ao_ref *ref, modref_access_node &a)
+void
+modref_access_analysis::record_access (modref_records *tt,
+ ao_ref *ref,
+ modref_access_node &a)
{
alias_set_type base_set = !flag_strict_aliasing ? 0
: ao_ref_base_alias_set (ref);
@@ -807,8 +1001,9 @@ record_access (modref_records *tt, ao_ref *ref, modref_access_node &a)
/* IPA version of record_access_tree. */
-static void
-record_access_lto (modref_records_lto *tt, ao_ref *ref, modref_access_node &a)
+void
+modref_access_analysis::record_access_lto (modref_records_lto *tt, ao_ref *ref,
+ modref_access_node &a)
{
/* get_alias_set sometimes use different type to compute the alias set
than TREE_TYPE (base). Do same adjustments. */
@@ -873,9 +1068,23 @@ record_access_lto (modref_records_lto *tt, ao_ref *ref, modref_access_node &a)
/* Returns true if and only if we should store the access to EXPR.
Some accesses, e.g. loads from automatic variables, are not interesting. */
-static bool
-record_access_p (tree expr)
+bool
+modref_access_analysis::record_access_p (tree expr)
{
+ if (TREE_THIS_VOLATILE (expr))
+ {
+ if (dump_file)
+ fprintf (dump_file, " (volatile; marking nondeterministic) ");
+ set_nondeterministic ();
+ }
+ if (cfun->can_throw_non_call_exceptions
+ && tree_could_throw_p (expr))
+ {
+ if (dump_file)
+ fprintf (dump_file, " (can throw; marking side effects) ");
+ set_side_effects ();
+ }
+
if (refs_local_or_readonly_memory_p (expr))
{
if (dump_file)
@@ -885,156 +1094,124 @@ record_access_p (tree expr)
return true;
}
-/* Return true if ECF flags says that nondeterminsm can be ignored. */
-
-static bool
-ignore_nondeterminism_p (tree caller, int flags)
-{
- if ((flags & (ECF_CONST | ECF_PURE))
- && !(flags & ECF_LOOPING_CONST_OR_PURE))
- return true;
- if ((flags & (ECF_NORETURN | ECF_NOTHROW)) == (ECF_NORETURN | ECF_NOTHROW)
- || (!opt_for_fn (caller, flag_exceptions) && (flags & ECF_NORETURN)))
- return true;
- return false;
-}
-
-/* Return true if ECF flags says that return value can be ignored. */
+/* Collapse loads and return true if something changed. */
-static bool
-ignore_retval_p (tree caller, int flags)
+bool
+modref_access_analysis::record_unknown_load ()
{
- if ((flags & (ECF_NORETURN | ECF_NOTHROW)) == (ECF_NORETURN | ECF_NOTHROW)
- || (!opt_for_fn (caller, flag_exceptions) && (flags & ECF_NORETURN)))
- return true;
- return false;
-}
-
-/* Return true if ECF flags says that stores can be ignored. */
+ bool changed = false;
-static bool
-ignore_stores_p (tree caller, int flags)
-{
- if (flags & (ECF_PURE | ECF_CONST | ECF_NOVOPS))
- return true;
- if ((flags & (ECF_NORETURN | ECF_NOTHROW)) == (ECF_NORETURN | ECF_NOTHROW)
- || (!opt_for_fn (caller, flag_exceptions) && (flags & ECF_NORETURN)))
- return true;
- return false;
+ if (m_summary && !m_summary->loads->every_base)
+ {
+ m_summary->loads->collapse ();
+ changed = true;
+ }
+ if (m_summary_lto && !m_summary_lto->loads->every_base)
+ {
+ m_summary_lto->loads->collapse ();
+ changed = true;
+ }
+ return changed;
}
-/* Determine parm_map for argument OP. */
+/* Collapse loads and return true if something changed. */
-modref_parm_map
-parm_map_for_arg (tree op)
+bool
+modref_access_analysis::record_unknown_store ()
{
- bool offset_known;
- poly_int64 offset;
- struct modref_parm_map parm_map;
-
- parm_map.parm_offset_known = false;
- parm_map.parm_offset = 0;
+ bool changed = false;
- offset_known = unadjusted_ptr_and_unit_offset (op, &op, &offset);
- if (TREE_CODE (op) == SSA_NAME
- && SSA_NAME_IS_DEFAULT_DEF (op)
- && TREE_CODE (SSA_NAME_VAR (op)) == PARM_DECL)
+ if (m_summary && !m_summary->stores->every_base)
{
- int index = 0;
- for (tree t = DECL_ARGUMENTS (current_function_decl);
- t != SSA_NAME_VAR (op); t = DECL_CHAIN (t))
- {
- if (!t)
- {
- index = MODREF_UNKNOWN_PARM;
- break;
- }
- index++;
- }
- parm_map.parm_index = index;
- parm_map.parm_offset_known = offset_known;
- parm_map.parm_offset = offset;
+ m_summary->stores->collapse ();
+ changed = true;
}
- else if (points_to_local_or_readonly_memory_p (op))
- parm_map.parm_index = MODREF_LOCAL_MEMORY_PARM;
- else
- parm_map.parm_index = MODREF_UNKNOWN_PARM;
- return parm_map;
+ if (m_summary_lto && !m_summary_lto->stores->every_base)
+ {
+ m_summary_lto->stores->collapse ();
+ changed = true;
+ }
+ return changed;
}
-/* Merge side effects of call STMT to function with CALLEE_SUMMARY
- int CUR_SUMMARY. Return true if something changed.
+/* Merge side effects of call STMT to function with CALLEE_SUMMARY.
+ Return true if something changed.
If IGNORE_STORES is true, do not merge stores.
If RECORD_ADJUSTMENTS is true cap number of adjustments to
a given access to make dataflow finite. */
bool
-merge_call_side_effects (modref_summary *cur_summary,
- gimple *stmt, modref_summary *callee_summary,
- bool ignore_stores, cgraph_node *callee_node,
- bool record_adjustments, bool always_executed)
+modref_access_analysis::merge_call_side_effects
+ (gimple *stmt, modref_summary *callee_summary,
+ cgraph_node *callee_node, bool record_adjustments)
{
- auto_vec <modref_parm_map, 32> parm_map;
- modref_parm_map chain_map;
- bool changed = false;
int flags = gimple_call_flags (stmt);
+ /* Nothing to do for non-looping cont functions. */
if ((flags & (ECF_CONST | ECF_NOVOPS))
&& !(flags & ECF_LOOPING_CONST_OR_PURE))
- return changed;
+ return false;
+
+ bool changed = false;
+ if (dump_file)
+ fprintf (dump_file, " - Merging side effects of %s\n",
+ callee_node->dump_name ());
+
+ /* Merge side effects and non-determinism.
+ PURE/CONST flags makes functions deterministic and if there is
+ no LOOPING_CONST_OR_PURE they also have no side effects. */
if (!(flags & (ECF_CONST | ECF_NOVOPS | ECF_PURE))
|| (flags & ECF_LOOPING_CONST_OR_PURE))
{
- if (!cur_summary->side_effects && callee_summary->side_effects)
+ if (!m_summary->side_effects && callee_summary->side_effects)
{
if (dump_file)
fprintf (dump_file, " - merging side effects.\n");
- cur_summary->side_effects = true;
+ m_summary->side_effects = true;
changed = true;
}
- if (!cur_summary->nondeterministic && callee_summary->nondeterministic
+ if (!m_summary->nondeterministic && callee_summary->nondeterministic
&& !ignore_nondeterminism_p (current_function_decl, flags))
{
if (dump_file)
fprintf (dump_file, " - merging nondeterministic.\n");
- cur_summary->nondeterministic = true;
+ m_summary->nondeterministic = true;
changed = true;
}
}
+ /* For const functions we are done. */
if (flags & (ECF_CONST | ECF_NOVOPS))
return changed;
- if (!cur_summary->calls_interposable && callee_summary->calls_interposable)
+ /* Merge calls_interposable flags. */
+ if (!m_summary->calls_interposable && callee_summary->calls_interposable)
{
if (dump_file)
fprintf (dump_file, " - merging calls interposable.\n");
- cur_summary->calls_interposable = true;
+ m_summary->calls_interposable = true;
changed = true;
}
- /* We can not safely optimize based on summary of callee if it does
- not always bind to current def: it is possible that memory load
- was optimized out earlier which may not happen in the interposed
- variant. */
- if (!callee_node->binds_to_current_def_p ()
- && !cur_summary->calls_interposable)
+ if (!callee_node->binds_to_current_def_p () && !m_summary->calls_interposable)
{
if (dump_file)
fprintf (dump_file, " - May be interposed.\n");
- cur_summary->calls_interposable = true;
+ m_summary->calls_interposable = true;
changed = true;
}
+ /* Now merge the actual load, store and kill vectors. For this we need
+ to compute map translating new parameters to old. */
if (dump_file)
- fprintf (dump_file, " - Merging side effects of %s with parm map:",
- callee_node->dump_name ());
+ fprintf (dump_file, " Parm map:");
+ auto_vec <modref_parm_map, 32> parm_map;
parm_map.safe_grow_cleared (gimple_call_num_args (stmt), true);
for (unsigned i = 0; i < gimple_call_num_args (stmt); i++)
{
- parm_map[i] = parm_map_for_arg (gimple_call_arg (stmt, i));
+ parm_map[i] = parm_map_for_ptr (gimple_call_arg (stmt, i));
if (dump_file)
{
fprintf (dump_file, " %i", parm_map[i].parm_index);
@@ -1046,9 +1223,11 @@ merge_call_side_effects (modref_summary *cur_summary,
}
}
}
+
+ modref_parm_map chain_map;
if (gimple_call_chain (stmt))
{
- chain_map = parm_map_for_arg (gimple_call_chain (stmt));
+ chain_map = parm_map_for_ptr (gimple_call_chain (stmt));
if (dump_file)
{
fprintf (dump_file, "static chain %i", chain_map.parm_index);
@@ -1063,7 +1242,9 @@ merge_call_side_effects (modref_summary *cur_summary,
if (dump_file)
fprintf (dump_file, "\n");
- if (always_executed
+ /* Kills can me merged in only if we know the function is going to be
+ always executed. */
+ if (m_always_executed
&& callee_summary->kills.length ()
&& (!cfun->can_throw_non_call_exceptions
|| !stmt_could_throw_p (cfun, stmt)))
@@ -1089,24 +1270,25 @@ merge_call_side_effects (modref_summary *cur_summary,
modref_access_node n = kill;
n.parm_index = m.parm_index;
n.parm_offset += m.parm_offset;
- if (modref_access_node::insert_kill (cur_summary->kills, n,
+ if (modref_access_node::insert_kill (m_summary->kills, n,
record_adjustments))
changed = true;
}
}
- /* Merge with callee's summary. */
- changed |= cur_summary->loads->merge (callee_summary->loads, &parm_map,
- &chain_map, record_adjustments);
- if (!ignore_stores)
+ /* Merge in loads. */
+ changed |= m_summary->loads->merge (callee_summary->loads, &parm_map,
+ &chain_map, record_adjustments);
+ /* Merge in stores. */
+ if (!ignore_stores_p (current_function_decl, flags))
{
- changed |= cur_summary->stores->merge (callee_summary->stores,
- &parm_map, &chain_map,
- record_adjustments);
- if (!cur_summary->writes_errno
+ changed |= m_summary->stores->merge (callee_summary->stores,
+ &parm_map, &chain_map,
+ record_adjustments);
+ if (!m_summary->writes_errno
&& callee_summary->writes_errno)
{
- cur_summary->writes_errno = true;
+ m_summary->writes_errno = true;
changed = true;
}
}
@@ -1115,9 +1297,10 @@ merge_call_side_effects (modref_summary *cur_summary,
/* Return access mode for argument I of call STMT with FNSPEC. */
-static modref_access_node
-get_access_for_fnspec (gcall *call, attr_fnspec &fnspec,
- unsigned int i, modref_parm_map &map)
+modref_access_node
+modref_access_analysis::get_access_for_fnspec (gcall *call, attr_fnspec &fnspec,
+ unsigned int i,
+ modref_parm_map &map)
{
tree size = NULL_TREE;
unsigned int size_arg;
@@ -1150,97 +1333,46 @@ get_access_for_fnspec (gcall *call, attr_fnspec &fnspec,
return a;
}
-/* Collapse loads and return true if something changed. */
-
-static bool
-collapse_loads (modref_summary *cur_summary,
- modref_summary_lto *cur_summary_lto)
-{
- bool changed = false;
-
- if (cur_summary && !cur_summary->loads->every_base)
- {
- cur_summary->loads->collapse ();
- changed = true;
- }
- if (cur_summary_lto
- && !cur_summary_lto->loads->every_base)
- {
- cur_summary_lto->loads->collapse ();
- changed = true;
- }
- return changed;
-}
-
-/* Collapse loads and return true if something changed. */
-
-static bool
-collapse_stores (modref_summary *cur_summary,
- modref_summary_lto *cur_summary_lto)
-{
- bool changed = false;
-
- if (cur_summary && !cur_summary->stores->every_base)
- {
- cur_summary->stores->collapse ();
- changed = true;
- }
- if (cur_summary_lto
- && !cur_summary_lto->stores->every_base)
- {
- cur_summary_lto->stores->collapse ();
- changed = true;
- }
- return changed;
-}
-
-
/* Apply side effects of call STMT to CUR_SUMMARY using FNSPEC.
If IGNORE_STORES is true ignore them.
Return false if no useful summary can be produced. */
-static bool
-process_fnspec (modref_summary *cur_summary,
- modref_summary_lto *cur_summary_lto,
- gcall *call, bool ignore_stores)
+void
+modref_access_analysis::process_fnspec (gcall *call)
{
- attr_fnspec fnspec = gimple_call_fnspec (call);
int flags = gimple_call_flags (call);
+ /* PURE/CONST flags makes functions deterministic and if there is
+ no LOOPING_CONST_OR_PURE they also have no side effects. */
if (!(flags & (ECF_CONST | ECF_NOVOPS | ECF_PURE))
|| (flags & ECF_LOOPING_CONST_OR_PURE)
|| (cfun->can_throw_non_call_exceptions
&& stmt_could_throw_p (cfun, call)))
{
- if (cur_summary)
- {
- cur_summary->side_effects = true;
- if (!ignore_nondeterminism_p (current_function_decl, flags))
- cur_summary->nondeterministic = true;
- }
- if (cur_summary_lto)
- {
- cur_summary_lto->side_effects = true;
- if (!ignore_nondeterminism_p (current_function_decl, flags))
- cur_summary_lto->nondeterministic = true;
- }
+ set_side_effects ();
+ if (!ignore_nondeterminism_p (current_function_decl, flags))
+ set_nondeterministic ();
}
+
+ /* For const functions we are done. */
if (flags & (ECF_CONST | ECF_NOVOPS))
- return true;
+ return;
+
+ attr_fnspec fnspec = gimple_call_fnspec (call);
+ /* If there is no fnpec we know nothing about loads & stores. */
if (!fnspec.known_p ())
{
if (dump_file && gimple_call_builtin_p (call, BUILT_IN_NORMAL))
fprintf (dump_file, " Builtin with no fnspec: %s\n",
IDENTIFIER_POINTER (DECL_NAME (gimple_call_fndecl (call))));
- if (ignore_stores)
- {
- collapse_loads (cur_summary, cur_summary_lto);
- return true;
- }
- return false;
+ record_unknown_load ();
+ if (!ignore_stores_p (current_function_decl, flags))
+ record_unknown_store ();
+ return;
}
+ /* Process fnspec. */
if (fnspec.global_memory_read_p ())
- collapse_loads (cur_summary, cur_summary_lto);
+ record_unknown_load ();
else
{
for (unsigned int i = 0; i < gimple_call_num_args (call); i++)
@@ -1249,34 +1381,29 @@ process_fnspec (modref_summary *cur_summary,
else if (!fnspec.arg_specified_p (i)
|| fnspec.arg_maybe_read_p (i))
{
- modref_parm_map map = parm_map_for_arg
+ modref_parm_map map = parm_map_for_ptr
(gimple_call_arg (call, i));
if (map.parm_index == MODREF_LOCAL_MEMORY_PARM)
continue;
if (map.parm_index == MODREF_UNKNOWN_PARM)
{
- collapse_loads (cur_summary, cur_summary_lto);
+ record_unknown_load ();
break;
}
- if (cur_summary)
- cur_summary->loads->insert (0, 0,
- get_access_for_fnspec (call,
- fnspec, i,
- map),
- false);
- if (cur_summary_lto)
- cur_summary_lto->loads->insert (0, 0,
- get_access_for_fnspec (call,
- fnspec, i,
- map),
- false);
+ modref_access_node a = get_access_for_fnspec (call, fnspec, i, map);
+ if (a.parm_index == MODREF_LOCAL_MEMORY_PARM)
+ continue;
+ if (m_summary)
+ m_summary->loads->insert (0, 0, a, false);
+ if (m_summary_lto)
+ m_summary_lto->loads->insert (0, 0, a, false);
}
}
- if (ignore_stores)
- return true;
+ if (ignore_stores_p (current_function_decl, flags))
+ return;
if (fnspec.global_memory_written_p ())
- collapse_stores (cur_summary, cur_summary_lto);
+ record_unknown_store ();
else
{
for (unsigned int i = 0; i < gimple_call_num_args (call); i++)
@@ -1285,51 +1412,44 @@ process_fnspec (modref_summary *cur_summary,
else if (!fnspec.arg_specified_p (i)
|| fnspec.arg_maybe_written_p (i))
{
- modref_parm_map map = parm_map_for_arg
+ modref_parm_map map = parm_map_for_ptr
(gimple_call_arg (call, i));
if (map.parm_index == MODREF_LOCAL_MEMORY_PARM)
continue;
if (map.parm_index == MODREF_UNKNOWN_PARM)
{
- collapse_stores (cur_summary, cur_summary_lto);
+ record_unknown_store ();
break;
}
- if (cur_summary)
- cur_summary->stores->insert (0, 0,
- get_access_for_fnspec (call,
- fnspec, i,
- map),
- false);
- if (cur_summary_lto)
- cur_summary_lto->stores->insert (0, 0,
- get_access_for_fnspec (call,
- fnspec, i,
- map),
- false);
+ modref_access_node a = get_access_for_fnspec (call, fnspec, i, map);
+ if (a.parm_index == MODREF_LOCAL_MEMORY_PARM)
+ continue;
+ if (m_summary)
+ m_summary->stores->insert (0, 0, a, false);
+ if (m_summary_lto)
+ m_summary_lto->stores->insert (0, 0, a, false);
}
if (fnspec.errno_maybe_written_p () && flag_errno_math)
{
- if (cur_summary)
- cur_summary->writes_errno = true;
- if (cur_summary_lto)
- cur_summary_lto->writes_errno = true;
+ if (m_summary)
+ m_summary->writes_errno = true;
+ if (m_summary_lto)
+ m_summary_lto->writes_errno = true;
}
}
- return true;
}
/* Analyze function call STMT in function F.
Remember recursive calls in RECURSIVE_CALLS. */
-static bool
-analyze_call (modref_summary *cur_summary, modref_summary_lto *cur_summary_lto,
- gcall *stmt, vec <gimple *> *recursive_calls,
- bool always_executed)
+void
+modref_access_analysis::analyze_call (gcall *stmt)
{
/* Check flags on the function call. In certain cases, analysis can be
simplified. */
int flags = gimple_call_flags (stmt);
+
if ((flags & (ECF_CONST | ECF_NOVOPS))
&& !(flags & ECF_LOOPING_CONST_OR_PURE))
{
@@ -1337,13 +1457,9 @@ analyze_call (modref_summary *cur_summary, modref_summary_lto *cur_summary_lto,
fprintf (dump_file,
" - ECF_CONST | ECF_NOVOPS, ignoring all stores and all loads "
"except for args.\n");
- return true;
+ return;
}
- /* Pure functions do not affect global memory. Stores by functions which are
- noreturn and do not throw can safely be ignored. */
- bool ignore_stores = ignore_stores_p (current_function_decl, flags);
-
/* Next, we try to get the callee's function declaration. The goal is to
merge their summary with ours. */
tree callee = gimple_call_fndecl (stmt);
@@ -1354,10 +1470,11 @@ analyze_call (modref_summary *cur_summary, modref_summary_lto *cur_summary_lto,
if (dump_file)
fprintf (dump_file, gimple_call_internal_p (stmt)
? " - Internal call" : " - Indirect call.\n");
- return process_fnspec (cur_summary, cur_summary_lto, stmt, ignore_stores);
+ process_fnspec (stmt);
+ return;
}
/* We only need to handle internal calls in IPA mode. */
- gcc_checking_assert (!cur_summary_lto);
+ gcc_checking_assert (!m_summary_lto && !m_ipa);
struct cgraph_node *callee_node = cgraph_node::get_create (callee);
@@ -1365,14 +1482,11 @@ analyze_call (modref_summary *cur_summary, modref_summary_lto *cur_summary_lto,
there's nothing to do. */
if (recursive_call_p (current_function_decl, callee))
{
- recursive_calls->safe_push (stmt);
- if (cur_summary)
- cur_summary->side_effects = true;
- if (cur_summary_lto)
- cur_summary_lto->side_effects = true;
+ m_recursive_calls.safe_push (stmt);
+ set_side_effects ();
if (dump_file)
fprintf (dump_file, " - Skipping recursive call.\n");
- return true;
+ return;
}
gcc_assert (callee_node != NULL);
@@ -1384,21 +1498,18 @@ analyze_call (modref_summary *cur_summary, modref_summary_lto *cur_summary_lto,
if (builtin_safe_for_const_function_p (&looping, callee))
{
if (looping)
- {
- if (cur_summary)
- cur_summary->side_effects = true;
- if (cur_summary_lto)
- cur_summary_lto->side_effects = true;
- }
+ set_side_effects ();
if (dump_file)
- fprintf (dump_file, " - Bulitin is safe for const.\n");
- return true;
+ fprintf (dump_file, " - Builtin is safe for const.\n");
+ return;
}
if (avail <= AVAIL_INTERPOSABLE)
{
if (dump_file)
- fprintf (dump_file, " - Function availability <= AVAIL_INTERPOSABLE.\n");
- return process_fnspec (cur_summary, cur_summary_lto, stmt, ignore_stores);
+ fprintf (dump_file,
+ " - Function availability <= AVAIL_INTERPOSABLE.\n");
+ process_fnspec (stmt);
+ return;
}
/* Get callee's modref summary. As above, if there's no summary, we either
@@ -1408,31 +1519,21 @@ analyze_call (modref_summary *cur_summary, modref_summary_lto *cur_summary_lto,
{
if (dump_file)
fprintf (dump_file, " - No modref summary available for callee.\n");
- return process_fnspec (cur_summary, cur_summary_lto, stmt, ignore_stores);
+ process_fnspec (stmt);
+ return;
}
- merge_call_side_effects (cur_summary, stmt, callee_summary, ignore_stores,
- callee_node, false, always_executed);
+ merge_call_side_effects (stmt, callee_summary, callee_node, false);
- return true;
+ return;
}
-/* Support analysis in non-lto and lto mode in parallel. */
-
-struct summary_ptrs
-{
- struct modref_summary *nolto;
- struct modref_summary_lto *lto;
- bool always_executed;
-};
-
/* Helper for analyze_stmt. */
-static bool
-analyze_load (gimple *, tree, tree op, void *data)
+bool
+modref_access_analysis::analyze_load (gimple *, tree, tree op, void *data)
{
- modref_summary *summary = ((summary_ptrs *)data)->nolto;
- modref_summary_lto *summary_lto = ((summary_ptrs *)data)->lto;
+ modref_access_analysis *t = (modref_access_analysis *)data;
if (dump_file)
{
@@ -1441,39 +1542,28 @@ analyze_load (gimple *, tree, tree op, void *data)
fprintf (dump_file, "\n");
}
- if (TREE_THIS_VOLATILE (op)
- || (cfun->can_throw_non_call_exceptions
- && tree_could_throw_p (op)))
- {
- if (dump_file)
- fprintf (dump_file, " (volatile or can throw; marking side effects) ");
- if (summary)
- summary->side_effects = summary->nondeterministic = true;
- if (summary_lto)
- summary_lto->side_effects = summary_lto->nondeterministic = true;
- }
-
- if (!record_access_p (op))
+ if (!t->record_access_p (op))
return false;
ao_ref r;
ao_ref_init (&r, op);
modref_access_node a = get_access (&r);
+ if (a.parm_index == MODREF_LOCAL_MEMORY_PARM)
+ return false;
- if (summary)
- record_access (summary->loads, &r, a);
- if (summary_lto)
- record_access_lto (summary_lto->loads, &r, a);
+ if (t->m_summary)
+ t->record_access (t->m_summary->loads, &r, a);
+ if (t->m_summary_lto)
+ t->record_access_lto (t->m_summary_lto->loads, &r, a);
return false;
}
/* Helper for analyze_stmt. */
-static bool
-analyze_store (gimple *stmt, tree, tree op, void *data)
+bool
+modref_access_analysis::analyze_store (gimple *stmt, tree, tree op, void *data)
{
- modref_summary *summary = ((summary_ptrs *)data)->nolto;
- modref_summary_lto *summary_lto = ((summary_ptrs *)data)->lto;
+ modref_access_analysis *t = (modref_access_analysis *)data;
if (dump_file)
{
@@ -1482,38 +1572,30 @@ analyze_store (gimple *stmt, tree, tree op, void *data)
fprintf (dump_file, "\n");
}
- if (TREE_THIS_VOLATILE (op)
- || (cfun->can_throw_non_call_exceptions
- && tree_could_throw_p (op)))
- {
- if (dump_file)
- fprintf (dump_file, " (volatile or can throw; marking side effects) ");
- if (summary)
- summary->side_effects = summary->nondeterministic = true;
- if (summary_lto)
- summary_lto->side_effects = summary_lto->nondeterministic = true;
- }
-
- if (!record_access_p (op))
+ if (!t->record_access_p (op))
return false;
ao_ref r;
ao_ref_init (&r, op);
modref_access_node a = get_access (&r);
+ if (a.parm_index == MODREF_LOCAL_MEMORY_PARM)
+ return false;
- if (summary)
- record_access (summary->stores, &r, a);
- if (summary_lto)
- record_access_lto (summary_lto->stores, &r, a);
- if (summary
- && ((summary_ptrs *)data)->always_executed
+ if (t->m_summary)
+ t->record_access (t->m_summary->stores, &r, a);
+ if (t->m_summary_lto)
+ t->record_access_lto (t->m_summary_lto->stores, &r, a);
+ if (t->m_always_executed
&& a.useful_for_kill_p ()
&& (!cfun->can_throw_non_call_exceptions
|| !stmt_could_throw_p (cfun, stmt)))
{
if (dump_file)
fprintf (dump_file, " - Recording kill\n");
- modref_access_node::insert_kill (summary->kills, a, false);
+ if (t->m_summary)
+ modref_access_node::insert_kill (t->m_summary->kills, a, false);
+ if (t->m_summary_lto)
+ modref_access_node::insert_kill (t->m_summary_lto->kills, a, false);
}
return false;
}
@@ -1521,19 +1603,17 @@ analyze_store (gimple *stmt, tree, tree op, void *data)
/* Analyze statement STMT of function F.
If IPA is true do not merge in side effects of calls. */
-static bool
-analyze_stmt (modref_summary *summary, modref_summary_lto *summary_lto,
- gimple *stmt, bool ipa, vec <gimple *> *recursive_calls,
- bool always_executed)
+void
+modref_access_analysis::analyze_stmt (gimple *stmt, bool always_executed)
{
+ m_always_executed = always_executed;
/* In general we can not ignore clobbers because they are barriers for code
motion, however after inlining it is safe to do because local optimization
passes do not consider clobbers from other functions.
Similar logic is in ipa-pure-const.c. */
- if ((ipa || cfun->after_inlining) && gimple_clobber_p (stmt))
+ if ((m_ipa || cfun->after_inlining) && gimple_clobber_p (stmt))
{
- if (summary
- && always_executed && record_access_p (gimple_assign_lhs (stmt)))
+ if (always_executed && record_access_p (gimple_assign_lhs (stmt)))
{
ao_ref r;
ao_ref_init (&r, gimple_assign_lhs (stmt));
@@ -1542,101 +1622,145 @@ analyze_stmt (modref_summary *summary, modref_summary_lto *summary_lto,
{
if (dump_file)
fprintf (dump_file, " - Recording kill\n");
- modref_access_node::insert_kill (summary->kills, a, false);
+ if (m_summary)
+ modref_access_node::insert_kill (m_summary->kills, a, false);
+ if (m_summary_lto)
+ modref_access_node::insert_kill (m_summary_lto->kills,
+ a, false);
}
}
- return true;
+ return;
}
- struct summary_ptrs sums = {summary, summary_lto, always_executed};
-
/* Analyze all loads and stores in STMT. */
- walk_stmt_load_store_ops (stmt, &sums,
+ walk_stmt_load_store_ops (stmt, this,
analyze_load, analyze_store);
switch (gimple_code (stmt))
{
case GIMPLE_ASM:
if (gimple_asm_volatile_p (as_a <gasm *> (stmt)))
- {
- if (summary)
- summary->side_effects = summary->nondeterministic = true;
- if (summary_lto)
- summary_lto->side_effects = summary_lto->nondeterministic = true;
- }
+ set_nondeterministic ();
if (cfun->can_throw_non_call_exceptions
&& stmt_could_throw_p (cfun, stmt))
- {
- if (summary)
- summary->side_effects = true;
- if (summary_lto)
- summary_lto->side_effects = true;
- }
+ set_side_effects ();
/* If the ASM statement does not read nor write memory, there's nothing
to do. Otherwise just give up. */
if (!gimple_asm_clobbers_memory_p (as_a <gasm *> (stmt)))
- return true;
+ return;
if (dump_file)
fprintf (dump_file, " - Function contains GIMPLE_ASM statement "
"which clobbers memory.\n");
- return false;
+ record_unknown_load ();
+ record_unknown_store ();
+ return;
case GIMPLE_CALL:
- if (!ipa || gimple_call_internal_p (stmt))
- return analyze_call (summary, summary_lto,
- as_a <gcall *> (stmt), recursive_calls,
- always_executed);
+ if (!m_ipa || gimple_call_internal_p (stmt))
+ analyze_call (as_a <gcall *> (stmt));
else
- {
- attr_fnspec fnspec = gimple_call_fnspec (as_a <gcall *>(stmt));
-
- if (fnspec.known_p ()
- && (!fnspec.global_memory_read_p ()
- || !fnspec.global_memory_written_p ()))
- {
- cgraph_edge *e = cgraph_node::get (current_function_decl)->get_edge (stmt);
- if (e->callee)
- {
- fnspec_summaries->get_create (e)->fnspec = xstrdup (fnspec.get_str ());
- if (dump_file)
- fprintf (dump_file, " Recorded fnspec %s\n", fnspec.get_str ());
- }
- }
- }
- return true;
+ {
+ attr_fnspec fnspec = gimple_call_fnspec (as_a <gcall *>(stmt));
+
+ if (fnspec.known_p ()
+ && (!fnspec.global_memory_read_p ()
+ || !fnspec.global_memory_written_p ()))
+ {
+ cgraph_edge *e = cgraph_node::get
+ (current_function_decl)->get_edge (stmt);
+ if (e->callee)
+ {
+ fnspec_summaries->get_create (e)->fnspec
+ = xstrdup (fnspec.get_str ());
+ if (dump_file)
+ fprintf (dump_file, " Recorded fnspec %s\n",
+ fnspec.get_str ());
+ }
+ }
+ }
+ return;
default:
if (cfun->can_throw_non_call_exceptions
&& stmt_could_throw_p (cfun, stmt))
- {
- if (summary)
- summary->side_effects = true;
- if (summary_lto)
- summary_lto->side_effects = true;
- }
- return true;
+ set_side_effects ();
+ return;
}
}
-/* Remove summary of current function because during the function body
- scan we determined it is not useful. LTO, NOLTO and IPA determines the
- mode of scan. */
+/* Propagate load/stres acress recursive calls. */
-static void
-remove_summary (bool lto, bool nolto, bool ipa)
+void
+modref_access_analysis::propagate ()
{
+ if (m_ipa && m_summary)
+ return;
+
+ bool changed = true;
+ bool first = true;
cgraph_node *fnode = cgraph_node::get (current_function_decl);
- if (!ipa)
- optimization_summaries->remove (fnode);
- else
+
+ m_always_executed = false;
+ while (changed && m_summary->useful_p (m_ecf_flags, false))
{
- if (nolto)
- summaries->remove (fnode);
- if (lto)
- summaries_lto->remove (fnode);
- remove_modref_edge_summaries (fnode);
+ changed = false;
+ for (unsigned i = 0; i < m_recursive_calls.length (); i++)
+ {
+ changed |= merge_call_side_effects (m_recursive_calls[i], m_summary,
+ fnode, !first);
+ }
+ first = false;
+ }
+}
+
+/* Analyze function. */
+
+void
+modref_access_analysis::analyze ()
+{
+ m_ecf_flags = flags_from_decl_or_type (current_function_decl);
+ bool summary_useful = true;
+
+ /* Analyze each statement in each basic block of the function. If the
+ statement cannot be analyzed (for any reason), the entire function cannot
+ be analyzed by modref. */
+ basic_block bb;
+ FOR_EACH_BB_FN (bb, cfun)
+ {
+ gimple_stmt_iterator si;
+ bool always_executed
+ = bb == single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))->dest;
+
+ for (si = gsi_start_nondebug_after_labels_bb (bb);
+ !gsi_end_p (si); gsi_next_nondebug (&si))
+ {
+ analyze_stmt (gsi_stmt (si), always_executed);
+
+ /* Avoid doing useles work. */
+ if ((!m_summary || !m_summary->useful_p (m_ecf_flags, false))
+ && (!m_summary_lto
+ || !m_summary_lto->useful_p (m_ecf_flags, false)))
+ {
+ summary_useful = false;
+ break;
+ }
+ if (always_executed
+ && stmt_can_throw_external (cfun, gsi_stmt (si)))
+ always_executed = false;
+ }
+ if (!summary_useful)
+ break;
+ }
+ /* In non-IPA mode we need to perform iterative datafow on recursive calls.
+ This needs to be done after all other side effects are computed. */
+ if (summary_useful)
+ {
+ if (!m_ipa)
+ propagate ();
+ if (m_summary && !m_summary->side_effects && !finite_function_p ())
+ m_summary->side_effects = true;
+ if (m_summary_lto && !m_summary_lto->side_effects
+ && !finite_function_p ())
+ m_summary_lto->side_effects = true;
}
- if (dump_file)
- fprintf (dump_file,
- " - modref done with result: not tracked.\n");
}
/* Return true if OP accesses memory pointed to by SSA_NAME. */
@@ -1691,7 +1815,8 @@ deref_flags (int flags, bool ignore_stores)
}
-/* Description of an escape point. */
+/* Description of an escape point: a call which affects flags of a given
+ SSA name. */
struct escape_point
{
@@ -1706,6 +1831,10 @@ struct escape_point
bool direct;
};
+/* Lattice used during the eaf flags analsysis dataflow. For a given SSA name
+ we aim to compute its flags and escape points. We also use the lattice
+ to dynamically build dataflow graph to propagate on. */
+
class modref_lattice
{
public:
@@ -1996,10 +2125,7 @@ modref_eaf_analysis::merge_call_lhs_flags (gcall *call, int arg,
bool indirect)
{
int index = SSA_NAME_VERSION (name);
-
- /* If value is not returned at all, do nothing. */
- if (!direct && !indirect)
- return;
+ bool returned_directly = false;
/* If there is no return value, no flags are affected. */
if (!gimple_call_lhs (call))
@@ -2010,10 +2136,23 @@ modref_eaf_analysis::merge_call_lhs_flags (gcall *call, int arg,
if (arg >= 0)
{
int flags = gimple_call_return_flags (call);
- if ((flags & ERF_RETURNS_ARG)
- && (flags & ERF_RETURN_ARG_MASK) != arg)
- return;
+ if (flags & ERF_RETURNS_ARG)
+ {
+ if ((flags & ERF_RETURN_ARG_MASK) == arg)
+ returned_directly = true;
+ else
+ return;
+ }
}
+ /* Make ERF_RETURNS_ARG overwrite EAF_UNUSED. */
+ if (returned_directly)
+ {
+ direct = true;
+ indirect = false;
+ }
+ /* If value is not returned at all, do nothing. */
+ else if (!direct && !indirect)
+ return;
/* If return value is SSA name determine its flags. */
if (TREE_CODE (gimple_call_lhs (call)) == SSA_NAME)
@@ -2236,11 +2375,13 @@ modref_eaf_analysis::analyze_ssa_name (tree name)
if (gimple_call_arg (call, i) == name)
{
int call_flags = gimple_call_arg_flags (call, i);
- if (!ignore_retval && !(call_flags & EAF_UNUSED))
+ if (!ignore_retval)
merge_call_lhs_flags
(call, i, name,
- !(call_flags & EAF_NOT_RETURNED_DIRECTLY),
- !(call_flags & EAF_NOT_RETURNED_INDIRECTLY));
+ !(call_flags & (EAF_NOT_RETURNED_DIRECTLY
+ | EAF_UNUSED)),
+ !(call_flags & (EAF_NOT_RETURNED_INDIRECTLY
+ | EAF_UNUSED)));
if (!(ecf_flags & (ECF_CONST | ECF_NOVOPS)))
{
call_flags = callee_to_caller_flags
@@ -2831,24 +2972,24 @@ analyze_function (function *f, bool ipa)
optimization_summaries = modref_summaries::create_ggc (symtab);
else /* Remove existing summary if we are re-running the pass. */
{
- if (dump_file
- && (summary
- = optimization_summaries->get (cgraph_node::get (f->decl)))
- != NULL
+ summary = optimization_summaries->get (fnode);
+ if (summary != NULL
&& summary->loads)
{
- fprintf (dump_file, "Past summary:\n");
- optimization_summaries->get
- (cgraph_node::get (f->decl))->dump (dump_file);
+ if (dump_file)
+ {
+ fprintf (dump_file, "Past summary:\n");
+ optimization_summaries->get (fnode)->dump (dump_file);
+ }
past_flags.reserve_exact (summary->arg_flags.length ());
past_flags.splice (summary->arg_flags);
past_retslot_flags = summary->retslot_flags;
past_static_chain_flags = summary->static_chain_flags;
past_flags_known = true;
}
- optimization_summaries->remove (cgraph_node::get (f->decl));
+ optimization_summaries->remove (fnode);
}
- summary = optimization_summaries->get_create (cgraph_node::get (f->decl));
+ summary = optimization_summaries->get_create (fnode);
gcc_checking_assert (nolto && !lto);
}
/* In IPA mode we analyze every function precisely once. Assert that. */
@@ -2859,16 +3000,16 @@ analyze_function (function *f, bool ipa)
if (!summaries)
summaries = modref_summaries::create_ggc (symtab);
else
- summaries->remove (cgraph_node::get (f->decl));
- summary = summaries->get_create (cgraph_node::get (f->decl));
+ summaries->remove (fnode);
+ summary = summaries->get_create (fnode);
}
if (lto)
{
if (!summaries_lto)
summaries_lto = modref_summaries_lto::create_ggc (symtab);
else
- summaries_lto->remove (cgraph_node::get (f->decl));
- summary_lto = summaries_lto->get_create (cgraph_node::get (f->decl));
+ summaries_lto->remove (fnode);
+ summary_lto = summaries_lto->get_create (fnode);
}
if (!fnspec_summaries)
fnspec_summaries = new fnspec_summaries_t (symtab);
@@ -2916,69 +3057,10 @@ analyze_function (function *f, bool ipa)
analyze_parms (summary, summary_lto, ipa,
past_flags, past_retslot_flags, past_static_chain_flags);
- int ecf_flags = flags_from_decl_or_type (current_function_decl);
- auto_vec <gimple *, 32> recursive_calls;
-
- /* Analyze each statement in each basic block of the function. If the
- statement cannot be analyzed (for any reason), the entire function cannot
- be analyzed by modref. */
- basic_block bb;
- FOR_EACH_BB_FN (bb, f)
- {
- gimple_stmt_iterator si;
- bool always_executed
- = bb == single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun))->dest;
-
- for (si = gsi_start_nondebug_after_labels_bb (bb);
- !gsi_end_p (si); gsi_next_nondebug (&si))
- {
- if (!analyze_stmt (summary, summary_lto,
- gsi_stmt (si), ipa, &recursive_calls,
- always_executed)
- || ((!summary || !summary->useful_p (ecf_flags, false))
- && (!summary_lto
- || !summary_lto->useful_p (ecf_flags, false))))
- {
- collapse_loads (summary, summary_lto);
- collapse_stores (summary, summary_lto);
- break;
- }
- if (always_executed
- && stmt_can_throw_external (cfun, gsi_stmt (si)))
- always_executed = false;
- }
- }
-
- /* In non-IPA mode we need to perform iterative datafow on recursive calls.
- This needs to be done after all other side effects are computed. */
- if (!ipa)
- {
- bool changed = true;
- bool first = true;
- while (changed)
- {
- changed = false;
- for (unsigned i = 0; i < recursive_calls.length (); i++)
- {
- changed |= merge_call_side_effects
- (summary, recursive_calls[i], summary,
- ignore_stores_p (current_function_decl,
- gimple_call_flags
- (recursive_calls[i])),
- fnode, !first, false);
- if (!summary->useful_p (ecf_flags, false))
- {
- remove_summary (lto, nolto, ipa);
- return false;
- }
- }
- first = false;
- }
- }
- if (summary && !summary->side_effects && !finite_function_p ())
- summary->side_effects = true;
- if (summary_lto && !summary_lto->side_effects && !finite_function_p ())
- summary_lto->side_effects = true;
+ {
+ modref_access_analysis analyzer (ipa, summary, summary_lto);
+ analyzer.analyze ();
+ }
if (!ipa && flag_ipa_pure_const)
{
@@ -2987,15 +3069,14 @@ analyze_function (function *f, bool ipa)
{
if (!summary->loads->every_base && !summary->loads->bases
&& !summary->calls_interposable)
- fixup_cfg = ipa_make_function_const
- (cgraph_node::get (current_function_decl),
- summary->side_effects, true);
+ fixup_cfg = ipa_make_function_const (fnode,
+ summary->side_effects, true);
else
- fixup_cfg = ipa_make_function_pure
- (cgraph_node::get (current_function_decl),
- summary->side_effects, true);
+ fixup_cfg = ipa_make_function_pure (fnode,
+ summary->side_effects, true);
}
}
+ int ecf_flags = flags_from_decl_or_type (current_function_decl);
if (summary && !summary->useful_p (ecf_flags))
{
if (!ipa)
@@ -3248,6 +3329,8 @@ modref_summaries_lto::duplicate (cgraph_node *, cgraph_node *,
src_data->loads->max_refs,
src_data->loads->max_accesses);
dst_data->loads->copy_from (src_data->loads);
+ dst_data->kills.reserve_exact (src_data->kills.length ());
+ dst_data->kills.splice (src_data->kills);
dst_data->writes_errno = src_data->writes_errno;
dst_data->side_effects = src_data->side_effects;
dst_data->nondeterministic = src_data->nondeterministic;
@@ -3302,40 +3385,21 @@ write_modref_records (modref_records_lto *tt, struct output_block *ob)
streamer_write_uhwi (ob, tt->every_base);
streamer_write_uhwi (ob, vec_safe_length (tt->bases));
- size_t i;
- modref_base_node <tree> *base_node;
- FOR_EACH_VEC_SAFE_ELT (tt->bases, i, base_node)
+ for (auto base_node : tt->bases)
{
stream_write_tree (ob, base_node->base, true);
streamer_write_uhwi (ob, base_node->every_ref);
streamer_write_uhwi (ob, vec_safe_length (base_node->refs));
- size_t j;
- modref_ref_node <tree> *ref_node;
- FOR_EACH_VEC_SAFE_ELT (base_node->refs, j, ref_node)
+ for (auto ref_node : base_node->refs)
{
stream_write_tree (ob, ref_node->ref, true);
streamer_write_uhwi (ob, ref_node->every_access);
streamer_write_uhwi (ob, vec_safe_length (ref_node->accesses));
- size_t k;
- modref_access_node *access_node;
- FOR_EACH_VEC_SAFE_ELT (ref_node->accesses, k, access_node)
- {
- streamer_write_hwi (ob, access_node->parm_index);
- if (access_node->parm_index != -1)
- {
- streamer_write_uhwi (ob, access_node->parm_offset_known);
- if (access_node->parm_offset_known)
- {
- streamer_write_poly_int64 (ob, access_node->parm_offset);
- streamer_write_poly_int64 (ob, access_node->offset);
- streamer_write_poly_int64 (ob, access_node->size);
- streamer_write_poly_int64 (ob, access_node->max_size);
- }
- }
- }
+ for (auto access_node : ref_node->accesses)
+ access_node.stream_out (ob);
}
}
}
@@ -3440,33 +3504,14 @@ read_modref_records (lto_input_block *ib, struct data_in *data_in,
size_t every_access = streamer_read_uhwi (ib);
size_t naccesses = streamer_read_uhwi (ib);
- if (nolto_ref_node)
- nolto_ref_node->every_access = every_access;
- if (lto_ref_node)
- lto_ref_node->every_access = every_access;
+ if (nolto_ref_node && every_access)
+ nolto_ref_node->collapse ();
+ if (lto_ref_node && every_access)
+ lto_ref_node->collapse ();
for (size_t k = 0; k < naccesses; k++)
{
- int parm_index = streamer_read_hwi (ib);
- bool parm_offset_known = false;
- poly_int64 parm_offset = 0;
- poly_int64 offset = 0;
- poly_int64 size = -1;
- poly_int64 max_size = -1;
-
- if (parm_index != -1)
- {
- parm_offset_known = streamer_read_uhwi (ib);
- if (parm_offset_known)
- {
- parm_offset = streamer_read_poly_int64 (ib);
- offset = streamer_read_poly_int64 (ib);
- size = streamer_read_poly_int64 (ib);
- max_size = streamer_read_poly_int64 (ib);
- }
- }
- modref_access_node a = {offset, size, max_size, parm_offset,
- parm_index, parm_offset_known, false};
+ modref_access_node a = modref_access_node::stream_in (ib);
if (nolto_ref_node)
nolto_ref_node->insert_access (a, max_accesses, false);
if (lto_ref_node)
@@ -3577,6 +3622,9 @@ modref_write ()
write_modref_records (r->loads, ob);
write_modref_records (r->stores, ob);
+ streamer_write_uhwi (ob, r->kills.length ());
+ for (auto kill : r->kills)
+ kill.stream_out (ob);
struct bitpack_d bp = bitpack_create (ob->main_stream);
bp_pack_value (&bp, r->writes_errno, 1);
@@ -3701,6 +3749,20 @@ read_section (struct lto_file_decl_data *file_data, const char *data,
read_modref_records (&ib, data_in,
modref_sum ? &modref_sum->stores : NULL,
modref_sum_lto ? &modref_sum_lto->stores : NULL);
+ int j = streamer_read_uhwi (&ib);
+ if (j && modref_sum)
+ modref_sum->kills.reserve_exact (j);
+ if (j && modref_sum_lto)
+ modref_sum_lto->kills.reserve_exact (j);
+ for (int k = 0; k < j; k++)
+ {
+ modref_access_node a = modref_access_node::stream_in (&ib);
+
+ if (modref_sum)
+ modref_sum->kills.quick_push (a);
+ if (modref_sum_lto)
+ modref_sum_lto->kills.quick_push (a);
+ }
struct bitpack_d bp = streamer_read_bitpack (&ib);
if (bp_unpack_value (&bp, 1))
{
@@ -3841,6 +3903,27 @@ remap_arg_flags (auto_vec <eaf_flags_t> &arg_flags, clone_info *info)
}
}
+/* Update kills accrdoing to the parm map MAP. */
+
+static void
+remap_kills (vec <modref_access_node> &kills, const vec <int> &map)
+{
+ for (size_t i = 0; i < kills.length ();)
+ if (kills[i].parm_index >= 0)
+ {
+ if (kills[i].parm_index < (int)map.length ()
+ && map[kills[i].parm_index] != MODREF_UNKNOWN_PARM)
+ {
+ kills[i].parm_index = map[kills[i].parm_index];
+ i++;
+ }
+ else
+ kills.unordered_remove (i);
+ }
+ else
+ i++;
+}
+
/* If signature changed, update the summary. */
static void
@@ -3891,8 +3974,7 @@ update_signature (struct cgraph_node *node)
{
r->loads->remap_params (&map);
r->stores->remap_params (&map);
- /* TODO: One we do IPA kills analysis, update the table here. */
- r->kills.release ();
+ remap_kills (r->kills, map);
if (r->arg_flags.length ())
remap_arg_flags (r->arg_flags, info);
}
@@ -3900,8 +3982,7 @@ update_signature (struct cgraph_node *node)
{
r_lto->loads->remap_params (&map);
r_lto->stores->remap_params (&map);
- /* TODO: One we do IPA kills analysis, update the table here. */
- r_lto->kills.release ();
+ remap_kills (r_lto->kills, map);
if (r_lto->arg_flags.length ())
remap_arg_flags (r_lto->arg_flags, info);
}
@@ -4212,6 +4293,49 @@ get_access_for_fnspec (cgraph_edge *e, attr_fnspec &fnspec,
return a;
}
+ /* Collapse loads and return true if something changed. */
+static bool
+collapse_loads (modref_summary *cur_summary,
+ modref_summary_lto *cur_summary_lto)
+{
+ bool changed = false;
+
+ if (cur_summary && !cur_summary->loads->every_base)
+ {
+ cur_summary->loads->collapse ();
+ changed = true;
+ }
+ if (cur_summary_lto
+ && !cur_summary_lto->loads->every_base)
+ {
+ cur_summary_lto->loads->collapse ();
+ changed = true;
+ }
+ return changed;
+}
+
+/* Collapse loads and return true if something changed. */
+
+static bool
+collapse_stores (modref_summary *cur_summary,
+ modref_summary_lto *cur_summary_lto)
+{
+ bool changed = false;
+
+ if (cur_summary && !cur_summary->stores->every_base)
+ {
+ cur_summary->stores->collapse ();
+ changed = true;
+ }
+ if (cur_summary_lto
+ && !cur_summary_lto->stores->every_base)
+ {
+ cur_summary_lto->stores->collapse ();
+ changed = true;
+ }
+ return changed;
+}
+
/* Call E in NODE with ECF_FLAGS has no summary; update MODREF_SUMMARY and
CUR_SUMMARY_LTO accordingly. Return true if something changed. */
@@ -4983,8 +5107,7 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
auto_vec <modref_parm_map, 32> parm_map;
modref_parm_map chain_map;
/* TODO: Once we get jump functions for static chains we could
- compute this. */
- chain_map.parm_index = MODREF_UNKNOWN_PARM;
+ compute parm_index. */
compute_parm_map (edge, &parm_map);
@@ -5101,6 +5224,7 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
fprintf (dump_file, "Removed mod-ref summary for %s\n",
to->dump_name ());
summaries_lto->remove (to);
+ to_info_lto = NULL;
}
else if (to_info_lto && dump_file)
{
@@ -5108,7 +5232,6 @@ ipa_merge_modref_summary_after_inlining (cgraph_edge *edge)
fprintf (dump_file, "Updated mod-ref summary for %s\n",
to->dump_name ());
to_info_lto->dump (dump_file);
- to_info_lto = NULL;
}
if (callee_info_lto)
summaries_lto->remove (edge->callee);
diff --git a/gcc/ipa-modref.h b/gcc/ipa-modref.h
index 4eb696d..f868eb6 100644
--- a/gcc/ipa-modref.h
+++ b/gcc/ipa-modref.h
@@ -70,6 +70,7 @@ struct GTY(()) modref_summary
};
modref_summary *get_modref_function_summary (cgraph_node *func);
+modref_summary *get_modref_function_summary (gcall *call, bool *interposed);
void ipa_modref_c_finalize ();
void ipa_merge_modref_summary_after_inlining (cgraph_edge *e);
diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c
index a332940..fea8b08 100644
--- a/gcc/ipa-pure-const.c
+++ b/gcc/ipa-pure-const.c
@@ -1782,9 +1782,9 @@ propagate_pure_const (void)
if (w_l->state_previously_known != IPA_NEITHER
&& this_state > w_l->state_previously_known)
{
- this_state = w_l->state_previously_known;
if (this_state == IPA_NEITHER)
- this_looping = w_l->looping_previously_known;
+ this_looping = w_l->looping_previously_known;
+ this_state = w_l->state_previously_known;
}
if (!this_looping && self_recursive_p (w))
this_looping = true;
diff --git a/gcc/jit/ChangeLog b/gcc/jit/ChangeLog
index d7f7cc5..c2fc2bd 100644
--- a/gcc/jit/ChangeLog
+++ b/gcc/jit/ChangeLog
@@ -1,3 +1,54 @@
+2021-11-20 Antoni Boucher <bouanto@zoho.com>
+
+ PR target/96889
+ * docs/topics/compatibility.rst (LIBGCCJIT_ABI_16): New ABI tag.
+ * docs/topics/functions.rst: Add documentation for the
+ functions gcc_jit_function_get_return_type and
+ gcc_jit_function_get_param_count
+ * docs/topics/types.rst: Add documentation for the functions
+ gcc_jit_function_type_get_return_type,
+ gcc_jit_function_type_get_param_count,
+ gcc_jit_function_type_get_param_type,
+ gcc_jit_type_unqualified, gcc_jit_type_dyncast_array,
+ gcc_jit_type_is_bool,
+ gcc_jit_type_dyncast_function_ptr_type,
+ gcc_jit_type_is_integral, gcc_jit_type_is_pointer,
+ gcc_jit_type_dyncast_vector,
+ gcc_jit_vector_type_get_element_type,
+ gcc_jit_vector_type_get_num_units,
+ gcc_jit_struct_get_field, gcc_jit_type_is_struct,
+ and gcc_jit_struct_get_field_count
+ * libgccjit.c:
+ (gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
+ gcc_jit_function_type_get_return_type,
+ gcc_jit_function_type_get_param_count,
+ gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
+ gcc_jit_type_dyncast_array, gcc_jit_type_is_bool,
+ gcc_jit_type_dyncast_function_ptr_type, gcc_jit_type_is_integral,
+ gcc_jit_type_is_pointer, gcc_jit_type_dyncast_vector,
+ gcc_jit_vector_type_get_element_type,
+ gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
+ gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
+ functions.
+ (struct gcc_jit_function_type, struct gcc_jit_vector_type):
+ New types.
+ * libgccjit.h:
+ (gcc_jit_function_get_return_type, gcc_jit_function_get_param_count,
+ gcc_jit_function_type_get_return_type,
+ gcc_jit_function_type_get_param_count,
+ gcc_jit_function_type_get_param_type, gcc_jit_type_unqualified,
+ gcc_jit_type_dyncast_array, gcc_jit_type_is_bool,
+ gcc_jit_type_dyncast_function_ptr_type, gcc_jit_type_is_integral,
+ gcc_jit_type_is_pointer, gcc_jit_type_dyncast_vector,
+ gcc_jit_vector_type_get_element_type,
+ gcc_jit_vector_type_get_num_units, gcc_jit_struct_get_field,
+ gcc_jit_type_is_struct, gcc_jit_struct_get_field_count): New
+ function declarations.
+ (struct gcc_jit_function_type, struct gcc_jit_vector_type):
+ New types.
+ * jit-recording.h: New functions (is_struct and is_vector)
+ * libgccjit.map (LIBGCCJIT_ABI_16): New ABI tag.
+
2021-11-12 David Malcolm <dmalcolm@redhat.com>
PR jit/103199
diff --git a/gcc/jit/docs/topics/compatibility.rst b/gcc/jit/docs/topics/compatibility.rst
index 239b6aa..52ee3f8 100644
--- a/gcc/jit/docs/topics/compatibility.rst
+++ b/gcc/jit/docs/topics/compatibility.rst
@@ -230,7 +230,7 @@ entrypoints:
.. _LIBGCCJIT_ABI_15:
``LIBGCCJIT_ABI_15``
------------------------
+--------------------
``LIBGCCJIT_ABI_15`` covers the addition of API entrypoints for directly
embedding assembler instructions:
@@ -243,3 +243,44 @@ embedding assembler instructions:
* :func:`gcc_jit_extended_asm_add_input_operand`
* :func:`gcc_jit_extended_asm_add_clobber`
* :func:`gcc_jit_context_add_top_level_asm`
+
+.. _LIBGCCJIT_ABI_16:
+
+``LIBGCCJIT_ABI_16``
+--------------------
+``LIBGCCJIT_ABI_16`` covers the addition of reflection functions via API
+entrypoints:
+
+ * :func:`gcc_jit_function_get_return_type`
+
+ * :func:`gcc_jit_function_get_param_count`
+
+ * :func:`gcc_jit_type_dyncast_array`
+
+ * :func:`gcc_jit_type_is_bool`
+
+ * :func:`gcc_jit_type_is_integral`
+
+ * :func:`gcc_jit_type_is_pointer`
+
+ * :func:`gcc_jit_type_is_struct`
+
+ * :func:`gcc_jit_type_dyncast_vector`
+
+ * :func:`gcc_jit_type_unqualified`
+
+ * :func:`gcc_jit_type_dyncast_function_ptr_type`
+
+ * :func:`gcc_jit_function_type_get_return_type`
+
+ * :func:`gcc_jit_function_type_get_param_count`
+
+ * :func:`gcc_jit_function_type_get_param_type`
+
+ * :func:`gcc_jit_vector_type_get_num_units`
+
+ * :func:`gcc_jit_vector_type_get_element_type`
+
+ * :func:`gcc_jit_struct_get_field`
+
+ * :func:`gcc_jit_struct_get_field_count`
diff --git a/gcc/jit/docs/topics/functions.rst b/gcc/jit/docs/topics/functions.rst
index b2d9239..8399345 100644
--- a/gcc/jit/docs/topics/functions.rst
+++ b/gcc/jit/docs/topics/functions.rst
@@ -171,6 +171,32 @@ Functions
underlying string, so it is valid to pass in a pointer to an on-stack
buffer.
+.. function:: size_t \
+ gcc_jit_function_get_param_count (gcc_jit_function *func)
+
+ Get the number of parameters of the function.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_function_get_return_type (gcc_jit_function *func)
+
+ Get the return type of the function.
+
+ The API entrypoints relating to getting info about parameters and return
+ types:
+
+ * :c:func:`gcc_jit_function_get_return_type`
+
+ * :c:func:`gcc_jit_function_get_param_count`
+
+ were added in :ref:`LIBGCCJIT_ABI_16`; you can test for their presence
+ using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+ .. type:: gcc_jit_case
+
Blocks
------
.. type:: gcc_jit_block
diff --git a/gcc/jit/docs/topics/types.rst b/gcc/jit/docs/topics/types.rst
index 831f11b..6260e9a 100644
--- a/gcc/jit/docs/topics/types.rst
+++ b/gcc/jit/docs/topics/types.rst
@@ -345,3 +345,125 @@ Function pointer types
Function pointer types can be created using
:c:func:`gcc_jit_context_new_function_ptr_type`.
+
+Reflection API
+--------------
+
+.. function:: gcc_jit_type *\
+ gcc_jit_type_dyncast_array (gcc_jit_type *type)
+
+ Get the element type of an array type or NULL if it's not an array.
+
+.. function:: int\
+ gcc_jit_type_is_bool (gcc_jit_type *type)
+
+ Return non-zero if the type is a bool.
+
+.. function:: gcc_jit_function_type *\
+ gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type)
+
+ Return the function type if it is one or NULL.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+
+ Given a function type, return its return type.
+
+.. function:: size_t\
+ gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+
+ Given a function type, return its number of parameters.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+ size_t index)
+
+ Given a function type, return the type of the specified parameter.
+
+.. function:: int\
+ gcc_jit_type_is_integral (gcc_jit_type *type)
+
+ Return non-zero if the type is an integral.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_type_is_pointer (gcc_jit_type *type)
+
+ Return the type pointed by the pointer type or NULL if it's not a pointer.
+
+.. function:: gcc_jit_vector_type *\
+ gcc_jit_type_dyncast_vector (gcc_jit_type *type)
+
+ Given a type, return a dynamic cast to a vector type or NULL.
+
+.. function:: gcc_jit_struct *\
+ gcc_jit_type_is_struct (gcc_jit_type *type)
+
+ Given a type, return a dynamic cast to a struct type or NULL.
+
+.. function:: size_t\
+ gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+
+ Given a vector type, return the number of units it contains.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_vector_type_get_element_type (gcc_jit_vector_type * vector_type)
+
+ Given a vector type, return the type of its elements.
+
+.. function:: gcc_jit_type *\
+ gcc_jit_type_unqualified (gcc_jit_type *type)
+
+ Given a type, return the unqualified type, removing "const", "volatile" and
+ alignment qualifiers.
+
+.. function:: gcc_jit_field *\
+ gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+ size_t index)
+
+ Get a struct field by index.
+
+.. function:: size_t\
+ gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+
+ Get the number of fields in the struct.
+
+ The API entrypoints related to the reflection API:
+
+ * :c:func:`gcc_jit_function_type_get_return_type`
+
+ * :c:func:`gcc_jit_function_type_get_param_count`
+
+ * :c:func:`gcc_jit_function_type_get_param_type`
+
+ * :c:func:`gcc_jit_type_unqualified`
+
+ * :c:func:`gcc_jit_type_dyncast_array`
+
+ * :c:func:`gcc_jit_type_is_bool`
+
+ * :c:func:`gcc_jit_type_dyncast_function_ptr_type`
+
+ * :c:func:`gcc_jit_type_is_integral`
+
+ * :c:func:`gcc_jit_type_is_pointer`
+
+ * :c:func:`gcc_jit_type_dyncast_vector`
+
+ * :c:func:`gcc_jit_vector_type_get_element_type`
+
+ * :c:func:`gcc_jit_vector_type_get_num_units`
+
+ * :c:func:`gcc_jit_struct_get_field`
+
+ * :c:func:`gcc_jit_type_is_struct`
+
+ * :c:func:`gcc_jit_struct_get_field_count`
+
+ were added in :ref:`LIBGCCJIT_ABI_16`; you can test for their presence
+ using
+
+ .. code-block:: c
+
+ #ifdef LIBGCCJIT_HAVE_REFLECTION
+
+ .. type:: gcc_jit_case
diff --git a/gcc/jit/jit-recording.h b/gcc/jit/jit-recording.h
index 03fa116..4a994fe 100644
--- a/gcc/jit/jit-recording.h
+++ b/gcc/jit/jit-recording.h
@@ -546,7 +546,9 @@ public:
virtual bool is_bool () const = 0;
virtual type *is_pointer () = 0;
virtual type *is_array () = 0;
+ virtual struct_ *is_struct () { return NULL; }
virtual bool is_void () const { return false; }
+ virtual vector_type *is_vector () { return NULL; }
virtual bool has_known_size () const { return true; }
bool is_numeric () const
@@ -663,6 +665,7 @@ public:
bool is_bool () const FINAL OVERRIDE { return m_other_type->is_bool (); }
type *is_pointer () FINAL OVERRIDE { return m_other_type->is_pointer (); }
type *is_array () FINAL OVERRIDE { return m_other_type->is_array (); }
+ struct_ *is_struct () FINAL OVERRIDE { return m_other_type->is_struct (); }
protected:
type *m_other_type;
@@ -745,6 +748,8 @@ public:
void replay_into (replayer *) FINAL OVERRIDE;
+ vector_type *is_vector () FINAL OVERRIDE { return this; }
+
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
@@ -951,6 +956,8 @@ public:
const char *access_as_type (reproducer &r) FINAL OVERRIDE;
+ struct_ *is_struct () FINAL OVERRIDE { return this; }
+
private:
string * make_debug_string () FINAL OVERRIDE;
void write_reproducer (reproducer &r) FINAL OVERRIDE;
diff --git a/gcc/jit/libgccjit.c b/gcc/jit/libgccjit.c
index 7fa9480..c744b63 100644
--- a/gcc/jit/libgccjit.c
+++ b/gcc/jit/libgccjit.c
@@ -60,6 +60,14 @@ struct gcc_jit_struct : public gcc::jit::recording::struct_
{
};
+struct gcc_jit_function_type : public gcc::jit::recording::function_type
+{
+};
+
+struct gcc_jit_vector_type : public gcc::jit::recording::vector_type
+{
+};
+
struct gcc_jit_field : public gcc::jit::recording::field
{
};
@@ -518,6 +526,197 @@ gcc_jit_type_get_volatile (gcc_jit_type *type)
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_array method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_type_dyncast_array (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+ return (gcc_jit_type *)type->is_array ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_bool method, in
+ jit-recording.c. */
+
+int
+gcc_jit_type_is_bool (gcc_jit_type *type)
+{
+ RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+ return type->is_bool ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_pointer method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+ return (gcc_jit_type *)type->is_pointer ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_int method, in
+ jit-recording.c. */
+
+int
+gcc_jit_type_is_integral (gcc_jit_type *type)
+{
+ RETURN_VAL_IF_FAIL (type, FALSE, NULL, NULL, "NULL type");
+
+ return type->is_int ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_vector method, in
+ jit-recording.c. */
+
+gcc_jit_vector_type *
+gcc_jit_type_dyncast_vector (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+ gcc::jit::recording::vector_type *vector_type = type->is_vector ();
+ return (gcc_jit_vector_type *)vector_type;
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::is_struct method, in
+ jit-recording.c. */
+
+gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+ gcc::jit::recording::struct_ *struct_type = type->is_struct ();
+ return (gcc_jit_struct *)struct_type;
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::vector_type::get_num_units method, in
+ jit-recording.c. */
+
+size_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type)
+{
+ RETURN_VAL_IF_FAIL (vector_type, 0, NULL, NULL, "NULL vector_type");
+ return vector_type->get_num_units ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::vector_type::get_element_type method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type)
+{
+ RETURN_NULL_IF_FAIL (vector_type, NULL, NULL, "NULL vector_type");
+ return (gcc_jit_type *)vector_type->get_element_type ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::unqualified method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+
+ return (gcc_jit_type *)type->unqualified ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::type::dyn_cast_function_type method, in
+ jit-recording.c. */
+
+gcc_jit_function_type *
+gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type)
+{
+ RETURN_NULL_IF_FAIL (type, NULL, NULL, "NULL type");
+ gcc::jit::recording::type *func_ptr_type = type->dereference ();
+ if (!func_ptr_type)
+ {
+ return NULL;
+ }
+
+ return (gcc_jit_function_type *)func_ptr_type->dyn_cast_function_type ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function_type::get_return_type method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type)
+{
+ RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+ return (gcc_jit_type *)function_type->get_return_type ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function_type::get_param_types method, in
+ jit-recording.c. */
+
+size_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type)
+{
+ RETURN_VAL_IF_FAIL (function_type, 0, NULL, NULL, "NULL function_type");
+ return function_type->get_param_types ().length ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function_type::get_param_types method, in
+ jit-recording.c. */
+
+gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+ size_t index)
+{
+ RETURN_NULL_IF_FAIL (function_type, NULL, NULL, "NULL function_type");
+ size_t num_params = function_type->get_param_types ().length ();
+ gcc::jit::recording::context *ctxt = function_type->m_ctxt;
+ RETURN_NULL_IF_FAIL_PRINTF3 (index < num_params,
+ ctxt, NULL,
+ "index of %ld is too large (%s has %ld params)",
+ index,
+ function_type->get_debug_string (),
+ num_params);
+ return (gcc_jit_type *)function_type->get_param_types ()[index];
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
gcc::jit::recording::context::new_array_type method, in
jit-recording.c. */
@@ -736,6 +935,42 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
(gcc::jit::recording::field **)fields);
}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::fields::get_field method in
+ jit-recording.c. */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+ size_t index)
+{
+ RETURN_NULL_IF_FAIL (struct_type, NULL, NULL, "NULL struct type");
+ RETURN_NULL_IF_FAIL (struct_type->get_fields (), NULL, NULL,
+ "NULL struct fields");
+ size_t num_fields = struct_type->get_fields ()->length ();
+ RETURN_NULL_IF_FAIL_PRINTF3 (index < num_fields,
+ NULL, NULL,
+ "index of %ld is too large (%s has %ld fields)",
+ index,
+ struct_type->get_debug_string (),
+ num_fields);
+ return (gcc_jit_field *)struct_type->get_fields ()->get_field (index);
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, this calls the trivial
+ gcc::jit::recording::struct_::get_fields method in
+ jit-recording.h. */
+
+size_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type)
+{
+ RETURN_VAL_IF_FAIL (struct_type, 0, NULL, NULL, "NULL struct type");
+ return struct_type->get_fields ()->length ();
+}
+
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
@@ -1020,6 +1255,35 @@ gcc_jit_function_get_param (gcc_jit_function *func, int index)
/* Public entrypoint. See description in libgccjit.h.
After error-checking, the real work is done by the
+ gcc::jit::recording::function::get_params method, in
+ jit-recording.h.
+ */
+
+size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func)
+{
+ RETURN_VAL_IF_FAIL (func, 0, NULL, NULL, "NULL function");
+ gcc::jit::recording::context *ctxt = func->m_ctxt;
+ JIT_LOG_FUNC (ctxt->get_logger ());
+ return func->get_params ().length ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
+ gcc::jit::recording::function::get_return_type method, in
+ jit-recording.h. */
+
+gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func)
+{
+ RETURN_NULL_IF_FAIL (func, NULL, NULL, "NULL function_type");
+ return (gcc_jit_type *)func->get_return_type ();
+}
+
+/* Public entrypoint. See description in libgccjit.h.
+
+ After error-checking, the real work is done by the
gcc::jit::recording::function::dump_to_dot method, in
jit-recording.c. */
diff --git a/gcc/jit/libgccjit.h b/gcc/jit/libgccjit.h
index 5c722c2..a1c9436 100644
--- a/gcc/jit/libgccjit.h
+++ b/gcc/jit/libgccjit.h
@@ -61,6 +61,8 @@ typedef struct gcc_jit_result gcc_jit_result;
+- gcc_jit_location
+- gcc_jit_type
+- gcc_jit_struct
+ +- gcc_jit_function_type
+ +- gcc_jit_vector_type
+- gcc_jit_field
+- gcc_jit_function
+- gcc_jit_block
@@ -97,6 +99,12 @@ typedef struct gcc_jit_field gcc_jit_field;
the layout for, or an opaque type. */
typedef struct gcc_jit_struct gcc_jit_struct;
+/* A gcc_jit_function_type encapsulates a function type. */
+typedef struct gcc_jit_function_type gcc_jit_function_type;
+
+/* A gcc_jit_vector_type encapsulates a vector type. */
+typedef struct gcc_jit_vector_type gcc_jit_vector_type;
+
/* A gcc_jit_function encapsulates a function: either one that you're
creating yourself, or a reference to one that you're dynamically
linking to within the rest of the process. */
@@ -654,6 +662,15 @@ gcc_jit_struct_set_fields (gcc_jit_struct *struct_type,
int num_fields,
gcc_jit_field **fields);
+/* Get a field by index. */
+extern gcc_jit_field *
+gcc_jit_struct_get_field (gcc_jit_struct *struct_type,
+ size_t index);
+
+/* Get the number of fields. */
+extern size_t
+gcc_jit_struct_get_field_count (gcc_jit_struct *struct_type);
+
/* Unions work similarly to structs. */
extern gcc_jit_type *
gcc_jit_context_new_union_type (gcc_jit_context *ctxt,
@@ -1621,6 +1638,78 @@ gcc_jit_context_add_top_level_asm (gcc_jit_context *ctxt,
gcc_jit_location *loc,
const char *asm_stmts);
+#define LIBGCCJIT_HAVE_REFLECTION
+
+/* Reflection functions to get the number of parameters, return type of
+ a function and whether a type is a bool from the C API.
+
+ This API entrypoint was added in LIBGCCJIT_ABI_16; you can test for its
+ presence using
+ #ifdef LIBGCCJIT_HAVE_REFLECTION
+*/
+/* Get the return type of a function. */
+extern gcc_jit_type *
+gcc_jit_function_get_return_type (gcc_jit_function *func);
+
+/* Get the number of params of a function. */
+extern size_t
+gcc_jit_function_get_param_count (gcc_jit_function *func);
+
+/* Get the element type of an array type or NULL if it's not an array. */
+extern gcc_jit_type *
+gcc_jit_type_dyncast_array (gcc_jit_type *type);
+
+/* Return non-zero if the type is a bool. */
+extern int
+gcc_jit_type_is_bool (gcc_jit_type *type);
+
+/* Return the function type if it is one or NULL. */
+extern gcc_jit_function_type *
+gcc_jit_type_dyncast_function_ptr_type (gcc_jit_type *type);
+
+/* Given a function type, return its return type. */
+extern gcc_jit_type *
+gcc_jit_function_type_get_return_type (gcc_jit_function_type *function_type);
+
+/* Given a function type, return its number of parameters. */
+extern size_t
+gcc_jit_function_type_get_param_count (gcc_jit_function_type *function_type);
+
+/* Given a function type, return the type of the specified parameter. */
+extern gcc_jit_type *
+gcc_jit_function_type_get_param_type (gcc_jit_function_type *function_type,
+ size_t index);
+
+/* Return non-zero if the type is an integral. */
+extern int
+gcc_jit_type_is_integral (gcc_jit_type *type);
+
+/* Return the type pointed by the pointer type or NULL if it's not a
+ * pointer. */
+extern gcc_jit_type *
+gcc_jit_type_is_pointer (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a vector type or NULL. */
+extern gcc_jit_vector_type *
+gcc_jit_type_dyncast_vector (gcc_jit_type *type);
+
+/* Given a type, return a dynamic cast to a struct type or NULL. */
+extern gcc_jit_struct *
+gcc_jit_type_is_struct (gcc_jit_type *type);
+
+/* Given a vector type, return the number of units it contains. */
+extern size_t
+gcc_jit_vector_type_get_num_units (gcc_jit_vector_type *vector_type);
+
+/* Given a vector type, return the type of its elements. */
+extern gcc_jit_type *
+gcc_jit_vector_type_get_element_type (gcc_jit_vector_type *vector_type);
+
+/* Given a type, return the unqualified type, removing "const", "volatile"
+ * and alignment qualifiers. */
+extern gcc_jit_type *
+gcc_jit_type_unqualified (gcc_jit_type *type);
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/gcc/jit/libgccjit.map b/gcc/jit/libgccjit.map
index 337ea6c..64e7909 100644
--- a/gcc/jit/libgccjit.map
+++ b/gcc/jit/libgccjit.map
@@ -205,3 +205,24 @@ LIBGCCJIT_ABI_15 {
gcc_jit_extended_asm_add_clobber;
gcc_jit_context_add_top_level_asm;
} LIBGCCJIT_ABI_14;
+
+LIBGCCJIT_ABI_16 {
+ global:
+ gcc_jit_function_get_return_type;
+ gcc_jit_function_get_param_count;
+ gcc_jit_function_type_get_return_type;
+ gcc_jit_function_type_get_param_count;
+ gcc_jit_function_type_get_param_type;
+ gcc_jit_type_unqualified;
+ gcc_jit_type_dyncast_array;
+ gcc_jit_type_is_bool;
+ gcc_jit_type_dyncast_function_ptr_type;
+ gcc_jit_type_is_integral;
+ gcc_jit_type_is_pointer;
+ gcc_jit_type_dyncast_vector;
+ gcc_jit_vector_type_get_element_type;
+ gcc_jit_vector_type_get_num_units;
+ gcc_jit_struct_get_field;
+ gcc_jit_type_is_struct;
+ gcc_jit_struct_get_field_count;
+} LIBGCCJIT_ABI_15;
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 3e89134..3db8f2a 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -477,7 +477,7 @@ struct lang_hooks
void (*print_statistics) (void);
/* Called by print_tree when there is a tree of class tcc_exceptional
- that it doesn't know how to display. */
+ or tcc_constant that it doesn't know how to display. */
lang_print_tree_hook print_xnode;
/* Called to print language-dependent parts of tcc_decl, tcc_type,
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 7c3e276..ef3c371 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -516,6 +516,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node,
bp_pack_value (&bp, node->forced_by_abi, 1);
bp_pack_value (&bp, node->unique_name, 1);
bp_pack_value (&bp, node->body_removed, 1);
+ bp_pack_value (&bp, node->semantic_interposition, 1);
bp_pack_value (&bp, node->implicit_section, 1);
bp_pack_value (&bp, node->address_taken, 1);
bp_pack_value (&bp, tag == LTO_symtab_analyzed_node
@@ -604,6 +605,7 @@ lto_output_varpool_node (struct lto_simple_output_block *ob, varpool_node *node,
node->body_removed
|| (!encode_initializer_p && !node->alias && node->definition),
1);
+ bp_pack_value (&bp, node->semantic_interposition, 1);
bp_pack_value (&bp, node->implicit_section, 1);
bp_pack_value (&bp, node->writeonly, 1);
bp_pack_value (&bp, node->definition && (encode_initializer_p || node->alias),
@@ -1167,6 +1169,7 @@ input_overwrite_node (struct lto_file_decl_data *file_data,
node->forced_by_abi = bp_unpack_value (bp, 1);
node->unique_name = bp_unpack_value (bp, 1);
node->body_removed = bp_unpack_value (bp, 1);
+ node->semantic_interposition = bp_unpack_value (bp, 1);
node->implicit_section = bp_unpack_value (bp, 1);
node->address_taken = bp_unpack_value (bp, 1);
node->used_from_other_partition = bp_unpack_value (bp, 1);
@@ -1373,6 +1376,7 @@ input_varpool_node (struct lto_file_decl_data *file_data,
node->forced_by_abi = bp_unpack_value (&bp, 1);
node->unique_name = bp_unpack_value (&bp, 1);
node->body_removed = bp_unpack_value (&bp, 1);
+ node->semantic_interposition = bp_unpack_value (&bp, 1);
node->implicit_section = bp_unpack_value (&bp, 1);
node->writeonly = bp_unpack_value (&bp, 1);
node->definition = bp_unpack_value (&bp, 1);
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 38350b3..580a631 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,7 @@
+2021-11-18 Jan Hubicka <hubicka@ucw.cz>
+
+ * lto-partition.c (promote_symbol): Clear semantic_interposition flag.
+
2021-11-06 Jan Hubicka <hubicka@ucw.cz>
PR ipa/103070
diff --git a/gcc/lto/lto-partition.c b/gcc/lto/lto-partition.c
index bee4021..6d20555 100644
--- a/gcc/lto/lto-partition.c
+++ b/gcc/lto/lto-partition.c
@@ -1001,6 +1001,7 @@ promote_symbol (symtab_node *node)
so it is prevailing. This is important to keep binds_to_current_def_p
to work across partitions. */
node->resolution = LDPR_PREVAILING_DEF_IRONLY;
+ node->semantic_interposition = false;
DECL_VISIBILITY (node->decl) = VISIBILITY_HIDDEN;
DECL_VISIBILITY_SPECIFIED (node->decl) = true;
if (dump_file)
diff --git a/gcc/match.pd b/gcc/match.pd
index 758322d..f059b47 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -90,12 +90,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
plus minus
mult trunc_div trunc_mod rdiv
min max
+ IFN_FMIN IFN_FMAX
bit_and bit_ior bit_xor
lshift rshift)
(define_operator_list COND_BINARY
IFN_COND_ADD IFN_COND_SUB
IFN_COND_MUL IFN_COND_DIV IFN_COND_MOD IFN_COND_RDIV
IFN_COND_MIN IFN_COND_MAX
+ IFN_COND_FMIN IFN_COND_FMAX
IFN_COND_AND IFN_COND_IOR IFN_COND_XOR
IFN_COND_SHL IFN_COND_SHR)
@@ -865,6 +867,16 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
{ tree utype = unsigned_type_for (type); }
(convert (rshift (lshift (convert:utype @0) @2) @3))))))
+/* Fold ((type)(a<0)) << SIGNBITOFA into ((type)a) & signbit. */
+(simplify
+ (lshift (convert (lt @0 integer_zerop@1)) INTEGER_CST@2)
+ (if (TYPE_SIGN (TREE_TYPE (@0)) == SIGNED
+ && wi::eq_p (wi::to_wide (@2), TYPE_PRECISION (TREE_TYPE (@0)) - 1))
+ (with { wide_int wone = wi::one (TYPE_PRECISION (type)); }
+ (bit_and (convert @0)
+ { wide_int_to_tree (type,
+ wi::lshift (wone, wi::to_wide (@2))); }))))
+
/* Fold (-x >> C) into -(x > 0) where C = precision(type) - 1. */
(for cst (INTEGER_CST VECTOR_CST)
(simplify
@@ -1595,7 +1607,8 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(bitop (convert@2 @0) (convert?@3 @1))
(if (((TREE_CODE (@1) == INTEGER_CST
&& INTEGRAL_TYPE_P (TREE_TYPE (@0))
- && int_fits_type_p (@1, TREE_TYPE (@0)))
+ && (int_fits_type_p (@1, TREE_TYPE (@0))
+ || tree_nop_conversion_p (TREE_TYPE (@0), type)))
|| types_match (@0, @1))
/* ??? This transform conflicts with fold-const.c doing
Convert (T)(x & c) into (T)x & (T)c, if c is an integer
@@ -1604,8 +1617,14 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
Restrict it to GIMPLE to avoid endless recursions. */
&& (bitop != BIT_AND_EXPR || GIMPLE)
&& (/* That's a good idea if the conversion widens the operand, thus
- after hoisting the conversion the operation will be narrower. */
+ after hoisting the conversion the operation will be narrower.
+ It is also a good if the conversion is a nop as moves the
+ conversion to one side; allowing for combining of the conversions. */
TYPE_PRECISION (TREE_TYPE (@0)) < TYPE_PRECISION (type)
+ /* The conversion check for being a nop can only be done at the gimple
+ level as fold_binary has some re-association code which can conflict
+ with this if there is a "constant" which is not a full INTEGER_CST. */
+ || (GIMPLE && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (type))
/* It's also a good idea if the conversion is to a non-integer
mode. */
|| GET_MODE_CLASS (TYPE_MODE (type)) != MODE_INT
@@ -1771,10 +1790,10 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(convert (bit_and (bit_not @1) @0))))
/* (m1 CMP m2) * d -> (m1 CMP m2) ? d : 0 */
-(for cmp (gt lt ge le)
-(simplify
- (mult (convert (cmp @0 @1)) @2)
- (if (GIMPLE || !TREE_SIDE_EFFECTS (@2))
+(if (!canonicalize_math_p ())
+ (for cmp (gt lt ge le)
+ (simplify
+ (mult (convert (cmp @0 @1)) @2)
(cond (cmp @0 @1) @2 { build_zero_cst (type); }))))
/* For integral types with undefined overflow and C != 0 fold
diff --git a/gcc/optabs.def b/gcc/optabs.def
index b889ad2..e25f4c9 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -241,6 +241,8 @@ OPTAB_D (cond_smin_optab, "cond_smin$a")
OPTAB_D (cond_smax_optab, "cond_smax$a")
OPTAB_D (cond_umin_optab, "cond_umin$a")
OPTAB_D (cond_umax_optab, "cond_umax$a")
+OPTAB_D (cond_fmin_optab, "cond_fmin$a")
+OPTAB_D (cond_fmax_optab, "cond_fmax$a")
OPTAB_D (cond_fma_optab, "cond_fma$a")
OPTAB_D (cond_fms_optab, "cond_fms$a")
OPTAB_D (cond_fnma_optab, "cond_fnma$a")
diff --git a/gcc/opts.c b/gcc/opts.c
index 175b463..b16497e 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -682,6 +682,7 @@ static const struct default_options default_options_table[] =
/* -Ofast adds optimizations to -O3. */
{ OPT_LEVELS_FAST, OPT_ffast_math, NULL, 1 },
{ OPT_LEVELS_FAST, OPT_fallow_store_data_races, NULL, 1 },
+ { OPT_LEVELS_FAST, OPT_fsemantic_interposition, NULL, 0 },
{ OPT_LEVELS_NONE, 0, NULL, 0 }
};
diff --git a/gcc/pointer-query.cc b/gcc/pointer-query.cc
index a0e4543..2ead027 100644
--- a/gcc/pointer-query.cc
+++ b/gcc/pointer-query.cc
@@ -2358,3 +2358,33 @@ array_elt_at_offset (tree artype, HOST_WIDE_INT off,
return NULL_TREE;
}
+
+/* Wrapper around build_array_type_nelts that makes sure the array
+ can be created at all and handles zero sized arrays specially. */
+
+tree
+build_printable_array_type (tree eltype, unsigned HOST_WIDE_INT nelts)
+{
+ if (TYPE_SIZE_UNIT (eltype)
+ && TREE_CODE (TYPE_SIZE_UNIT (eltype)) == INTEGER_CST
+ && !integer_zerop (TYPE_SIZE_UNIT (eltype))
+ && TYPE_ALIGN_UNIT (eltype) > 1
+ && wi::zext (wi::to_wide (TYPE_SIZE_UNIT (eltype)),
+ ffs_hwi (TYPE_ALIGN_UNIT (eltype)) - 1) != 0)
+ eltype = TYPE_MAIN_VARIANT (eltype);
+
+ /* Consider excessive NELTS an array of unknown bound. */
+ tree idxtype = NULL_TREE;
+ if (nelts < HOST_WIDE_INT_MAX)
+ {
+ if (nelts)
+ return build_array_type_nelts (eltype, nelts);
+ idxtype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+ }
+
+ tree arrtype = build_array_type (eltype, idxtype);
+ arrtype = build_distinct_type_copy (TYPE_MAIN_VARIANT (arrtype));
+ TYPE_SIZE (arrtype) = bitsize_zero_node;
+ TYPE_SIZE_UNIT (arrtype) = size_zero_node;
+ return arrtype;
+}
diff --git a/gcc/pointer-query.h b/gcc/pointer-query.h
index c8215b6..fbea331 100644
--- a/gcc/pointer-query.h
+++ b/gcc/pointer-query.h
@@ -275,4 +275,7 @@ extern tree array_elt_at_offset (tree, HOST_WIDE_INT,
HOST_WIDE_INT * = nullptr,
HOST_WIDE_INT * = nullptr);
+/* Helper to build an array type that can be printed. */
+extern tree build_printable_array_type (tree, unsigned HOST_WIDE_INT);
+
#endif // GCC_POINTER_QUERY_H
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index d1fbd04..b5dc523 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -1004,8 +1004,7 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
break;
default:
- if (EXCEPTIONAL_CLASS_P (node))
- lang_hooks.print_xnode (file, node, indent);
+ lang_hooks.print_xnode (file, node, indent);
break;
}
diff --git a/gcc/symtab.c b/gcc/symtab.c
index c7ea8ec..94b4e47 100644
--- a/gcc/symtab.c
+++ b/gcc/symtab.c
@@ -929,6 +929,8 @@ symtab_node::dump_base (FILE *f)
fprintf (f, " forced_by_abi");
if (externally_visible)
fprintf (f, " externally_visible");
+ if (semantic_interposition)
+ fprintf (f, " semantic_interposition");
if (no_reorder)
fprintf (f, " no_reorder");
if (resolution != LDPR_UNKNOWN)
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b221cba..9872619 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,495 @@
+2021-11-21 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/101180
+ * gcc.target/i386/pr101180.c: New test.
+
+2021-11-21 Harald Anlauf <anlauf@gmx.de>
+ Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/99061
+ * gfortran.dg/dec_math_5.f90: New test.
+
+2021-11-21 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/103227
+ * gcc.dg/tree-ssa/modref-15.c: New test.
+
+2021-11-21 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/103264
+ * gcc.dg/tree-prof/merge_block.c: Add -fno-ipa-modref
+
+2021-11-21 Roger Sayle <roger@nextmovesoftware.com>
+ Robin Dapp <rdapp@linux.ibm.com>
+
+ PR target/102117
+ * gcc.target/s390/mul-wide.c: New test case.
+ * gcc.target/s390/umul-wide.c: New test case.
+
+2021-11-20 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/103052
+ * gcc.c-torture/execute/pr103052.c: New test.
+
+2021-11-20 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103220
+ * gcc.dg/tree-ssa/pr103220-1.c: New test.
+ * gcc.dg/tree-ssa/pr103220-2.c: New test.
+ * gcc.dg/pr25530.c: Update test to check for
+ 4294967294 in the case -2 is not matched.
+
+2021-11-20 Alexandre Oliva <oliva@adacore.com>
+
+ PR tree-optimization/102988
+ * g++.dg/pr102988.C: New.
+
+2021-11-20 Antoni Boucher <bouanto@zoho.com>
+
+ PR target/96889
+ * jit.dg/all-non-failing-tests.h: Add test-reflection.c.
+ * jit.dg/test-reflection.c: New test.
+
+2021-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/101180
+ * g++.target/i386/pr101180.C: New test.
+
+2021-11-19 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/103217
+ * gcc.dg/analyzer/explode-1.c: Update for improvement to location
+ of leak warning.
+ * gcc.dg/analyzer/pr103217.c: New test.
+ * gcc.dg/analyzer/pr94858-1.c: Add -Wno-analyzer-too-complex.
+
+2021-11-19 Marek Polacek <polacek@redhat.com>
+
+ * g++.dg/cpp0x/lambda/lambda-nested9.C: Adjust dg-error.
+
+2021-11-19 Iain Sandoe <iain@sandoe.co.uk>
+
+ * gcc.dg/torture/fp-int-convert-timode-3.c: Remove XFAIL.
+ * gcc.dg/torture/fp-int-convert-timode-4.c: Likewise.
+
+2021-11-19 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.dg/tree-ssa/modref-dse-6.c: New test.
+
+2021-11-19 Martin Sebor <msebor@redhat.com>
+
+ PR c++/33925
+ PR c/102867
+ * g++.dg/warn/Walways-true-2.C: Adjust to avoid a valid warning.
+ * c-c++-common/Waddress-5.c: New test.
+ * c-c++-common/Waddress-6.c: New test.
+ * g++.dg/warn/Waddress-7.C: New test.
+ * gcc.dg/Walways-true-2.c: Adjust to avoid a valid warning.
+ * gcc.dg/weak/weak-3.c: Expect a warning.
+
+2021-11-19 Andrew MacLeod <amacleod@redhat.com>
+
+ * gcc.dg/pr103254.c: New.
+
+2021-11-19 Stefan Schulze Frielinghaus <stefansf@linux.ibm.com>
+
+ * gcc.target/s390/20211119.c: New test.
+
+2021-11-19 Tamar Christina <tamar.christina@arm.com>
+
+ PR tree-optimization/103311
+ PR target/103330
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-double.c: Fix it.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-float.c: Likewise.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-double.c: Likewise.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-float.c: Likewise.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-double.c: Likewise.
+ * gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-float.c: Likewise.
+ * lib/target-supports.exp
+ (check_effective_target_vect_complex_add_double): Add Adv. SIMD.
+
+2021-11-19 Giuliano Belinassi <gbelinassi@suse.de>
+
+ * gcc.dg/devnull-dump.c: New.
+
+2021-11-19 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/94376
+ * g++.dg/cpp0x/lambda/lambda-nested9.C: New test.
+
+2021-11-19 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103314
+ * gcc.c-torture/compile/pr103314-1.c: New test.
+
+2021-11-19 Richard Biener <rguenther@suse.de>
+
+ PR c++/103326
+ * g++.dg/pr103326.C: New testcase.
+
+2021-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70796
+ * g++.dg/cpp1z/eval-order11.C: New test.
+
+2021-11-19 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/103248
+ * gcc.dg/pr103248.c: New testcase.
+
+2021-11-19 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102436
+ * gcc.dg/torture/20211118-1.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-lim-18.c: Likewise.
+
+2021-11-19 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103317
+ * gcc.c-torture/compile/pr103317-1.c: New test.
+
+2021-11-19 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103257
+ * gcc.dg/tree-ssa/vrp116.c: Check optimized instead of vrp1.
+ * gcc.dg/tree-ssa/pr103257-1.c: New test.
+
+2021-11-19 Marek Polacek <polacek@redhat.com>
+
+ PR c++/19808
+ PR c++/96121
+ * g++.dg/warn/Wuninitialized-14.C: New test.
+ * g++.dg/warn/Wuninitialized-15.C: New test.
+ * g++.dg/warn/Wuninitialized-16.C: New test.
+ * g++.dg/warn/Wuninitialized-17.C: New test.
+ * g++.dg/warn/Wuninitialized-18.C: New test.
+ * g++.dg/warn/Wuninitialized-19.C: New test.
+ * g++.dg/warn/Wuninitialized-20.C: New test.
+ * g++.dg/warn/Wuninitialized-21.C: New test.
+ * g++.dg/warn/Wuninitialized-22.C: New test.
+ * g++.dg/warn/Wuninitialized-23.C: New test.
+ * g++.dg/warn/Wuninitialized-24.C: New test.
+ * g++.dg/warn/Wuninitialized-25.C: New test.
+ * g++.dg/warn/Wuninitialized-26.C: New test.
+ * g++.dg/warn/Wuninitialized-27.C: New test.
+ * g++.dg/warn/Wuninitialized-28.C: New test.
+ * g++.dg/warn/Wuninitialized-29.C: New test.
+ * g++.dg/warn/Wuninitialized-30.C: New test.
+
+2021-11-19 liuhongt <hongtao.liu@intel.com>
+
+ * gcc.target/i386/pr102543.c: New test.
+
+2021-11-19 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/103198
+ * g++.dg/cpp2a/concepts-this1.C: New test.
+
+2021-11-18 Marek Polacek <polacek@redhat.com>
+
+ PR c++/103049
+ * g++.dg/cpp0x/auto25.C: Adjust dg-error.
+ * g++.dg/cpp0x/auto9.C: Likewise.
+ * g++.dg/cpp2a/concepts-pr84979-2.C: Likewise.
+ * g++.dg/cpp2a/concepts-pr84979-3.C: Likewise.
+ * g++.dg/cpp23/auto-fncast1.C: New test.
+ * g++.dg/cpp23/auto-fncast2.C: New test.
+ * g++.dg/cpp23/auto-fncast3.C: New test.
+ * g++.dg/cpp23/auto-fncast4.C: New test.
+ * g++.dg/cpp23/auto-fncast5.C: New test.
+ * g++.dg/cpp23/auto-fncast6.C: New test.
+
+2021-11-18 Harald Anlauf <anlauf@gmx.de>
+ Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/101329
+ * gfortran.dg/pr101329.f90: New test.
+
+2021-11-18 Patrick Palka <ppalka@redhat.com>
+
+ * g++.dg/cpp2a/fn-template25.C: New test.
+
+2021-11-18 Jan Hubicka <hubicka@ucw.cz>
+
+ * gcc.dg/lto/semantic-interposition-1_0.c: New test.
+ * gcc.dg/lto/semantic-interposition-1_1.c: New test.
+
+2021-11-18 Jan Hubicka <hubicka@ucw.cz>
+
+ PR ipa/103266
+ * g++.dg/torture/pr103266.C: New test.
+
+2021-11-18 Tamar Christina <tamar.christina@arm.com>
+
+ PR tree-optimization/103311
+ * gcc.target/aarch64/pr103311.c: New test.
+
+2021-11-18 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/102952
+ * gcc.target/i386/indirect-thunk-cs-prefix-1.c: New test.
+ * gcc.target/i386/indirect-thunk-cs-prefix-2.c: Likewise.
+
+2021-11-18 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gcc.target/mips/octeon-bbit-1.c (f3): Add noipa attribute.
+
+2021-11-18 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/99911
+ * g++.dg/cpp2a/fn-template24.C: New test.
+
+2021-11-18 Patrick Palka <ppalka@redhat.com>
+
+ PR c++/102670
+ * g++.dg/cpp2a/concepts-recursive-sat1.C: Adjust to use ADL
+ proper.
+ * g++.dg/cpp2a/fn-template23.C: New test.
+
+2021-11-18 Tamar Christina <tamar.christina@arm.com>
+
+ PR tree-optimization/103253
+ * gcc.dg/vect/pr103253.c: New test.
+
+2021-11-18 Matthias Kretz <m.kretz@gsi.de>
+
+ * c-c++-common/builtin-assoc-barrier-1.c: New test.
+
+2021-11-18 Richard Biener <rguenther@suse.de>
+
+ PR testsuite/103278
+ * gcc.dg/tree-ssa/if-to-switch-3.c: Supply
+ --param case-values-threshold=4.
+
+2021-11-18 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/103277
+ * gcc.dg/pr103277.c: New testcase.
+
+2021-11-18 Hongyu Wang <hongyu.wang@intel.com>
+
+ * gcc.target/i386/pr103069-2.c: Adjust.
+
+2021-11-18 konglin1 <lingling.kong@intel.com>
+
+ * gcc.target/i386/avx512fp16-vfcmulcph-1a.c: Add new test for alias.
+ * gcc.target/i386/avx512fp16-vfcmulcsh-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vfmulcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16-vfmulcsh-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c: Likewise.
+ * gcc.target/i386/avx512fp16vl-vfmulcph-1a.c: Likewise.
+
+2021-11-17 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103228
+ PR tree-optimization/55177
+ * gcc.dg/tree-ssa/pr103228-1.c: New test.
+ * gcc.dg/tree-ssa/pr55177-1.c: New test.
+
+2021-11-17 David Malcolm <dmalcolm@redhat.com>
+
+ PR preprocessor/103026
+ * c-c++-common/Wbidi-chars-ranges.c: New test.
+
+2021-11-17 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/102759
+ * gcc.dg/Warray-parameter-10.c: New test.
+ * gcc.dg/Wstringop-overflow-82.c: New test.
+
+2021-11-17 H.J. Lu <hjl.tools@gmail.com>
+
+ PR target/102952
+ * gcc.target/i386/harden-sls-1.c: New test.
+ * gcc.target/i386/harden-sls-2.c: Likewise.
+ * gcc.target/i386/harden-sls-3.c: Likewise.
+ * gcc.target/i386/harden-sls-4.c: Likewise.
+ * gcc.target/i386/harden-sls-5.c: Likewise.
+
+2021-11-17 Martin Sebor <msebor@redhat.com>
+
+ PR c/101702
+ * gcc.dg/Warray-parameter-11.c: New test.
+
+2021-11-17 Jeff Law <jeffreyalaw@gmail.com>
+
+ * gcc.target/mips/frame-header-1.c (bar): Add noipa attribute.
+ * gcc.target/mips/frame-header-2.c (bar): Likewise.
+
+2021-11-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR preprocessor/103130
+ * c-c++-common/cpp/dir-only-9.c: New test.
+
+2021-11-17 Martin Uecker <uecker@gcc.gnu.org>
+
+ PR c/91038
+ PR c/29970
+ * gcc.dg/vla-stexp-3.c: New test.
+ * gcc.dg/vla-stexp-4.c: New test.
+ * gcc.dg/vla-stexp-5.c: New test.
+ * gcc.dg/vla-stexp-6.c: New test.
+ * gcc.dg/vla-stexp-7.c: New test.
+ * gcc.dg/vla-stexp-8.c: New test.
+ * gcc.dg/vla-stexp-9.c: New test.
+
+2021-11-17 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/103255
+ * gcc.c-torture/execute/pr103255.c: New test.
+
+2021-11-17 Richard Sandiford <richard.sandiford@arm.com>
+
+ * gcc.target/aarch64/sve/cond_fmaxnm_5.c: New test.
+ * gcc.target/aarch64/sve/cond_fmaxnm_5_run.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fmaxnm_6.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fmaxnm_6_run.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fmaxnm_7.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fmaxnm_7_run.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fmaxnm_8.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fmaxnm_8_run.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fminnm_5.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fminnm_5_run.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fminnm_6.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fminnm_6_run.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fminnm_7.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fminnm_7_run.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fminnm_8.c: Likewise.
+ * gcc.target/aarch64/sve/cond_fminnm_8_run.c: Likewise.
+
+2021-11-17 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103288
+ * gcc.c-torture/compile/pr103288-1.c: New test.
+
+2021-11-17 Marek Polacek <polacek@redhat.com>
+
+ PR preprocessor/103026
+ * c-c++-common/Wbidi-chars-1.c: New test.
+ * c-c++-common/Wbidi-chars-2.c: New test.
+ * c-c++-common/Wbidi-chars-3.c: New test.
+ * c-c++-common/Wbidi-chars-4.c: New test.
+ * c-c++-common/Wbidi-chars-5.c: New test.
+ * c-c++-common/Wbidi-chars-6.c: New test.
+ * c-c++-common/Wbidi-chars-7.c: New test.
+ * c-c++-common/Wbidi-chars-8.c: New test.
+ * c-c++-common/Wbidi-chars-9.c: New test.
+ * c-c++-common/Wbidi-chars-10.c: New test.
+ * c-c++-common/Wbidi-chars-11.c: New test.
+ * c-c++-common/Wbidi-chars-12.c: New test.
+ * c-c++-common/Wbidi-chars-13.c: New test.
+ * c-c++-common/Wbidi-chars-14.c: New test.
+ * c-c++-common/Wbidi-chars-15.c: New test.
+ * c-c++-common/Wbidi-chars-16.c: New test.
+ * c-c++-common/Wbidi-chars-17.c: New test.
+
+2021-11-17 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/102695
+ * gcc.dg/analyzer/pr102695.c: New test.
+ * gcc.dg/analyzer/strchr-1.c: New test.
+
+2021-11-17 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/102779
+ * gcc.dg/analyzer/capacity-1.c: Add dg-require-effective-target
+ alloca. Use __builtin_alloca rather than alloca.
+ * gcc.dg/analyzer/capacity-3.c: Likewise.
+
+2021-11-16 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/tree-ssa/modref-dse-4.c: New test.
+
+2021-11-16 Harald Anlauf <anlauf@gmx.de>
+
+ PR fortran/103286
+ * gfortran.dg/pr103286.f90: New test.
+
+2021-11-16 Peter Bergner <bergner@linux.ibm.com>
+
+ PR target/102976
+ * gcc.target/powerpc/pr102976.c: New test.
+
+2021-11-16 Martin Sebor <msebor@redhat.com>
+
+ PR tree-optimization/102960
+ * gcc.dg/Wstringop-overflow-84.c: New test.
+
+2021-11-16 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.target/aarch64/shrn-combine-10.c: Use shrn.
+
+2021-11-16 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.dg/signbit-2.c: CHeck vect or scalar.
+
+2021-11-16 David Malcolm <dmalcolm@redhat.com>
+
+ PR analyzer/102662
+ * g++.dg/analyzer/pr102662.C: New test.
+
+2021-11-16 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103218
+ * gcc.dg/tree-ssa/pr103218-1.c: New test.
+
+2021-11-16 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * gcc.target/arc/tmac-4.c: New test.
+
+2021-11-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102880
+ * gcc.dg/tree-ssa/pr102880.c: New testcase.
+ * gcc.dg/tree-ssa/pr69270-3.c: Robustify.
+ * gcc.dg/tree-ssa/ssa-dom-thread-7.c: Change the number of
+ expected threadings.
+
+2021-11-16 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/102880
+ * gcc.dg/tree-ssa/phi-opt-26.c: New testcase.
+
+2021-11-16 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * gcc.target/arc/add_n-combine.c: Update test patterns.
+ * gcc.target/arc/builtin_eh.c: Update test for linux platforms.
+ * gcc.target/arc/mul64-1.c: Disable this test while running on
+ linux.
+ * gcc.target/arc/tls-gd.c: Update matching patterns.
+ * gcc.target/arc/tls-ie.c: Likewise.
+ * gcc.target/arc/tls-ld.c: Likewise.
+ * gcc.target/arc/uncached-8.c: Likewise.
+
+2021-11-16 Martin Jambor <mjambor@suse.cz>
+
+ * gcc.dg/ipa/ipa-sra-ret-nonull.c: New test.
+
+2021-11-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/103208
+ * c-c++-common/gomp/loop-11.c: New test.
+
+2021-11-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR tree-optimization/102009
+ * gcc.dg/pr102009.c: New test.
+
+2021-11-16 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/tree-ssa/modref-dse-5.c: New test.
+
+2021-11-16 Andrew Pinski <apinski@marvell.com>
+
+ PR tree-optimization/103245
+ * gcc.dg/tree-ssa/pr103245-1.c: New test.
+
+2021-11-16 H.J. Lu <hjl.tools@gmail.com>
+
+ PR middle-end/103268
+ * gcc.dg/pr103268-1.c: New test.
+ * gcc.dg/pr103268-2.c: Likewise.
+
2021-11-15 Jason Merrill <jason@redhat.com>
* lib/g++-dg.exp: Handle "impcx".
diff --git a/gcc/testsuite/c-c++-common/Waddress-5.c b/gcc/testsuite/c-c++-common/Waddress-5.c
new file mode 100644
index 0000000..5d63c7d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Waddress-5.c
@@ -0,0 +1,133 @@
+/* PR c/33925 - missing -Waddress with the address of an inline function
+ { dg-do compile }
+ { dg-options "-Wall" }
+ { dg-require-weak "" } */
+
+extern inline int eifn (void);
+extern inline int eifn_def (void) { return 0; }
+
+static inline int sifn (void);
+static inline int sifn_def (void) { return 0; }
+
+inline int ifn (void);
+inline int ifn_def (void) { return 0; }
+
+extern __attribute__ ((weak)) int ewfn (void);
+extern __attribute__ ((weak)) int ewfn_def (void) { return 0; }
+
+__attribute__ ((weak)) int wfn (void);
+__attribute__ ((weak)) int wfn_def (void) { return 0; }
+
+static __attribute__((weakref ("ewfn"))) int swrfn (void);
+
+void test_function_eqz (int *p)
+{
+ *p++ = eifn == 0; // { dg-warning "-Waddress" }
+ *p++ = eifn_def == 0; // { dg-warning "-Waddress" }
+ *p++ = sifn == 0; // { dg-warning "-Waddress" }
+ *p++ = sifn_def == 0; // { dg-warning "-Waddress" }
+ *p++ = ifn == 0; // { dg-warning "-Waddress" }
+ *p++ = ifn_def == 0; // { dg-warning "-Waddress" }
+ *p++ = ewfn == 0;
+ *p++ = ewfn_def == 0; // { dg-warning "-Waddress" }
+ *p++ = wfn == 0;
+ *p++ = wfn_def == 0; // { dg-warning "-Waddress" }
+ *p++ = swrfn == 0;
+}
+
+
+int test_function_if (int i)
+{
+ if (eifn) // { dg-warning "-Waddress" }
+ i++;
+ if (eifn_def) // { dg-warning "-Waddress" }
+ i++;
+ if (sifn) // { dg-warning "-Waddress" }
+ i++;
+ if (sifn_def) // { dg-warning "-Waddress" }
+ i++;
+ if (ifn) // { dg-warning "-Waddress" }
+ i++;
+ if (ifn_def) // { dg-warning "-Waddress" }
+ i++;
+ if (ewfn)
+ i++;
+ if (ewfn_def) // { dg-warning "-Waddress" }
+ i++;
+ if (wfn)
+ i++;
+ if(wfn_def) // { dg-warning "-Waddress" }
+ i++;
+ if (swrfn)
+ i++;
+ return i;
+}
+
+
+extern int ei;
+extern int ei_def = 1;
+
+static int si;
+static int si_def = 1;
+
+int i;
+int i_def = 1;
+
+extern __attribute__ ((weak)) int ewi; // declaration (may be null)
+extern __attribute__ ((weak)) int ewi_def = 1;
+
+__attribute__ ((weak)) int wi; // definition (cannot be bull)
+__attribute__ ((weak)) int wi_def = 1;
+
+static __attribute__((weakref ("ewi"))) int swri;
+
+void test_scalar (int *p)
+{
+ *p++ = &ei == 0; // { dg-warning "-Waddress" }
+ *p++ = &ei_def == 0; // { dg-warning "-Waddress" }
+ *p++ = &si == 0; // { dg-warning "-Waddress" }
+ *p++ = &si_def == 0; // { dg-warning "-Waddress" }
+ *p++ = &i == 0; // { dg-warning "-Waddress" }
+ *p++ = &i_def == 0; // { dg-warning "-Waddress" }
+ *p++ = &ewi == 0;
+ *p++ = &ewi_def == 0; // { dg-warning "-Waddress" }
+ *p++ = &wi == 0; // { dg-warning "-Waddress" }
+ *p++ = &wi_def == 0; // { dg-warning "-Waddress" }
+ *p++ = &swri == 0;
+}
+
+
+extern int eia[];
+extern int eia_def[] = { 1 };
+
+static int sia[1];
+static int sia_def[1] = { 1 };
+
+int ia[1];
+int ia_def[] = { 1 };
+
+extern __attribute__ ((weak)) int ewia[];
+extern __attribute__ ((weak)) int ewia_def[] = { 1 };
+
+__attribute__ ((weak)) int wia[1]; // definition (cannot be null)
+__attribute__ ((weak)) int wia_def[] = { 1 };
+
+static __attribute__((weakref ("ewia"))) int swria[1];
+
+void test_array (int *p)
+{
+ *p++ = eia == 0; // { dg-warning "-Waddress" }
+ *p++ = eia_def == 0; // { dg-warning "-Waddress" }
+ *p++ = sia == 0; // { dg-warning "-Waddress" }
+ *p++ = sia_def == 0; // { dg-warning "-Waddress" }
+ *p++ = ia == 0; // { dg-warning "-Waddress" }
+ *p++ = ia_def == 0; // { dg-warning "-Waddress" }
+ *p++ = ewia == 0;
+ *p++ = ewia_def == 0; // { dg-warning "-Waddress" }
+ *p++ = wia == 0; // { dg-warning "-Waddress" }
+ *p++ = wia_def == 0; // { dg-warning "-Waddress" }
+ *p++ = swria == 0;
+}
+
+/* { dg-prune-output "never defined" }
+ { dg-prune-output "initialized and declared 'extern'" } */
diff --git a/gcc/testsuite/c-c++-common/Waddress-6.c b/gcc/testsuite/c-c++-common/Waddress-6.c
new file mode 100644
index 0000000..e66e6e4
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Waddress-6.c
@@ -0,0 +1,32 @@
+/* PR c/102867 - -Waddress from macro expansion in readelf.c
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+#define F(x) ((&x) != 0)
+
+int warn_nomacro (int *p, int i)
+{
+ return &p[i] != 0; // { dg-warning "-Waddress" }
+}
+
+int nowarn_macro_expansion (int *p, int i)
+{
+ // Verify that -Waddress isn't issued for code from macro expansion.
+ return F (p[i]); // { dg-bogus "-Waddress" }
+}
+
+#define G(x, i) ((&x) + i)
+
+int warn_function_macro_expansion (int *p, int i)
+{
+ /* Verify that -Waddress is issued for code involving macro expansion
+ where the comparison takes place outside the macro. */
+ return G (*p, i) != 0; // { dg-warning "-Waddress" }
+}
+
+#define malloc __builtin_malloc
+
+int warn_object_macro_expansion (int *p, int i)
+{
+ return malloc != 0; // { dg-warning "-Waddress" }
+}
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-1.c b/gcc/testsuite/c-c++-common/Wbidi-chars-1.c
new file mode 100644
index 0000000..34f5ac1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-1.c
@@ -0,0 +1,12 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+
+int main() {
+ int isAdmin = 0;
+ /*‮ } ⁦if (isAdmin)⁩ ⁦ begin admins only */
+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
+ __builtin_printf("You are an admin.\n");
+ /* end admins only ‮ { ⁦*/
+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-10.c b/gcc/testsuite/c-c++-common/Wbidi-chars-10.c
new file mode 100644
index 0000000..3f851b6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-10.c
@@ -0,0 +1,27 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=unpaired" } */
+/* More nesting testing. */
+
+/* RLE‫ LRI⁦ PDF‬ PDI⁩*/
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int LRE_\u202a_PDF_\u202c;
+int LRE_\u202a_PDF_\u202c_LRE_\u202a_PDF_\u202c;
+int LRE_\u202a_LRI_\u2066_PDF_\u202c_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int RLE_\u202b_RLI_\u2067_PDF_\u202c_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int RLE_\u202b_RLI_\u2067_PDI_\u2069_PDF_\u202c;
+int FSI_\u2068_LRO_\u202d_PDI_\u2069_PDF_\u202c;
+int FSI_\u2068;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int FSI_\u2068_PDI_\u2069;
+int FSI_\u2068_FSI_\u2068_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069;
+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDF_\u202c;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int RLI_\u2067_RLI_\u2067_RLI_\u2067_RLI_\u2067_FSI_\u2068_PDI_\u2069_PDI_\u2069_PDI_\u2069_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-11.c b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c
new file mode 100644
index 0000000..270ce23
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-11.c
@@ -0,0 +1,13 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=unpaired" } */
+/* Test that we warn when mixing UCN and UTF-8. */
+
+int LRE_‪_PDF_\u202c;
+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
+int LRE_\u202a_PDF_‬_;
+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
+const char *s1 = "LRE_‪_PDF_\u202c";
+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
+const char *s2 = "LRE_\u202a_PDF_‬";
+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-12.c b/gcc/testsuite/c-c++-common/Wbidi-chars-12.c
new file mode 100644
index 0000000..b07eec1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-12.c
@@ -0,0 +1,19 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile { target { c || c++11 } } } */
+/* { dg-options "-Wbidi-chars=any" } */
+/* Test raw strings. */
+
+const char *s1 = R"(a b c LRE‪ 1 2 3 PDF‬ x y z)";
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+const char *s2 = R"(a b c RLE‫ 1 2 3 PDF‬ x y z)";
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+const char *s3 = R"(a b c LRO‭ 1 2 3 PDF‬ x y z)";
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+const char *s4 = R"(a b c RLO‮ 1 2 3 PDF‬ x y z)";
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+const char *s7 = R"(a b c FSI⁨ 1 2 3 PDI⁩ x y) z";
+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
+const char *s8 = R"(a b c PDI⁩ x y )z";
+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
+const char *s9 = R"(a b c PDF‬ x y z)";
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-13.c b/gcc/testsuite/c-c++-common/Wbidi-chars-13.c
new file mode 100644
index 0000000..b2dd9fd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-13.c
@@ -0,0 +1,17 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile { target { c || c++11 } } } */
+/* { dg-options "-Wbidi-chars=unpaired" } */
+/* Test raw strings. */
+
+const char *s1 = R"(a b c LRE‪ 1 2 3)";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+const char *s2 = R"(a b c RLE‫ 1 2 3)";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+const char *s3 = R"(a b c LRO‭ 1 2 3)";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+const char *s4 = R"(a b c FSI⁨ 1 2 3)";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+const char *s5 = R"(a b c LRI⁦ 1 2 3)";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+const char *s6 = R"(a b c RLI⁧ 1 2 3)";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-14.c b/gcc/testsuite/c-c++-common/Wbidi-chars-14.c
new file mode 100644
index 0000000..ba5f75d
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-14.c
@@ -0,0 +1,38 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=unpaired" } */
+/* Test PDI handling, which also pops any subsequent LREs, RLEs, LROs,
+ or RLOs. */
+
+/* LRI_⁦_LRI_⁦_RLE_‫_RLE_‫_RLE_‫_PDI_⁩*/
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+// LRI_⁦_RLE_‫_RLE_‫_RLE_‫_PDI_⁩
+// LRI_⁦_RLO_‮_RLE_‫_RLE_‫_PDI_⁩
+// LRI_⁦_RLO_‮_RLE_‫_PDI_⁩
+// FSI_⁨_RLO_‮_PDI_⁩
+// FSI_⁨_FSI_⁨_RLO_‮_PDI_⁩
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+
+int LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069_PDI_\u2069;
+int LRI_\u2066_LRI_\u2066_LRI_\u2066_LRE_\u202a_LRE_\u202a_LRE_\u202a_PDI_\u2069_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int PDI_\u2069;
+int LRI_\u2066_PDI_\u2069;
+int RLI_\u2067_PDI_\u2069;
+int LRE_\u202a_LRI_\u2066_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int LRI_\u2066_LRE_\u202a_PDF_\u202c_PDI_\u2069;
+int LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069;
+int RLI_\u2067_LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int FSI_\u2068_LRI_\u2066_LRE_\u202a_LRE_\u202a_PDF_\u202c_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int RLO_\u202e_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int RLI_\u2067_PDI_\u2069_RLI_\u2067;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int FSI_\u2068_PDF_\u202c_PDI_\u2069;
+int FSI_\u2068_FSI_\u2068_PDF_\u202c_PDI_\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-15.c b/gcc/testsuite/c-c++-common/Wbidi-chars-15.c
new file mode 100644
index 0000000..a0ce8ff
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-15.c
@@ -0,0 +1,59 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=unpaired" } */
+/* Test unpaired bidi control chars in multiline comments. */
+
+/*
+ * LRE‪ end
+ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+/*
+ * RLE‫ end
+ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+/*
+ * LRO‭ end
+ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+/*
+ * RLO‮ end
+ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+/*
+ * LRI⁦ end
+ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+/*
+ * RLI⁧ end
+ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+/*
+ * FSI⁨ end
+ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+/* LRE‪
+ PDF‬ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+/* FSI⁨
+ PDI⁩ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+
+/* LRE<‪>
+ *
+ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-3 } */
+
+/*
+ * LRE<‪>
+ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+
+/*
+ *
+ * LRE<‪> */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+
+/* RLI<⁧> */ /* PDI<⁩> */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* LRE<‪> */ /* PDF<‬> */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-16.c b/gcc/testsuite/c-c++-common/Wbidi-chars-16.c
new file mode 100644
index 0000000..baa0159
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-16.c
@@ -0,0 +1,26 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=any" } */
+/* Test LTR/RTL chars. */
+
+/* LTR<‎> */
+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */
+// LTR<‎>
+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */
+/* RTL<‏> */
+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */
+// RTL<‏>
+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */
+
+const char *s1 = "LTR<‎>";
+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */
+const char *s2 = "LTR\u200e";
+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */
+const char *s3 = "LTR\u200E";
+/* { dg-warning "U\\+200E" "" { target *-*-* } .-1 } */
+const char *s4 = "RTL<‏>";
+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */
+const char *s5 = "RTL\u200f";
+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */
+const char *s6 = "RTL\u200F";
+/* { dg-warning "U\\+200F" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-17.c b/gcc/testsuite/c-c++-common/Wbidi-chars-17.c
new file mode 100644
index 0000000..07cb432
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-17.c
@@ -0,0 +1,30 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=unpaired" } */
+/* Test LTR/RTL chars. */
+
+/* LTR<‎> */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+// LTR<‎>
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+/* RTL<‏> */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+// RTL<‏>
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int ltr_\u200e;
+/* { dg-error "universal character " "" { target *-*-* } .-1 } */
+int rtl_\u200f;
+/* { dg-error "universal character " "" { target *-*-* } .-1 } */
+
+const char *s1 = "LTR<‎>";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+const char *s2 = "LTR\u200e";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+const char *s3 = "LTR\u200E";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+const char *s4 = "RTL<‏>";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+const char *s5 = "RTL\u200f";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+const char *s6 = "RTL\u200F";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-2.c b/gcc/testsuite/c-c++-common/Wbidi-chars-2.c
new file mode 100644
index 0000000..2340374
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-2.c
@@ -0,0 +1,9 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+
+int main() {
+ /* Say hello; newline⁧/*/ return 0 ;
+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
+ __builtin_printf("Hello world.\n");
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-3.c b/gcc/testsuite/c-c++-common/Wbidi-chars-3.c
new file mode 100644
index 0000000..9dc7edb
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-3.c
@@ -0,0 +1,11 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+
+int main() {
+ const char* access_level = "user";
+ if (__builtin_strcmp(access_level, "user‮ ⁦// Check if admin⁩ ⁦")) {
+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
+ __builtin_printf("You are an admin.\n");
+ }
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-4.c b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c
new file mode 100644
index 0000000..639e5c6
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-4.c
@@ -0,0 +1,188 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=any -Wno-multichar -Wno-overflow" } */
+/* Test all bidi chars in various contexts (identifiers, comments,
+ string literals, character constants), both UCN and UTF-8. The bidi
+ chars here are properly terminated, except for the character constants. */
+
+/* a b c LRE‪ 1 2 3 PDF‬ x y z */
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+/* a b c RLE‫ 1 2 3 PDF‬ x y z */
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+/* a b c LRO‭ 1 2 3 PDF‬ x y z */
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+/* a b c RLO‮ 1 2 3 PDF‬ x y z */
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+/* a b c LRI⁦ 1 2 3 PDI⁩ x y z */
+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
+/* a b c RLI⁧ 1 2 3 PDI⁩ x y */
+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
+/* a b c FSI⁨ 1 2 3 PDI⁩ x y z */
+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
+
+/* Same but C++ comments instead. */
+// a b c LRE‪ 1 2 3 PDF‬ x y z
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+// a b c RLE‫ 1 2 3 PDF‬ x y z
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+// a b c LRO‭ 1 2 3 PDF‬ x y z
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+// a b c RLO‮ 1 2 3 PDF‬ x y z
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+// a b c LRI⁦ 1 2 3 PDI⁩ x y z
+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
+// a b c RLI⁧ 1 2 3 PDI⁩ x y
+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
+// a b c FSI⁨ 1 2 3 PDI⁩ x y z
+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
+
+/* Here we're closing an unopened context, warn when =any. */
+/* a b c PDI⁩ x y z */
+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
+/* a b c PDF‬ x y z */
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
+// a b c PDI⁩ x y z
+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
+// a b c PDF‬ x y z
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
+
+/* Multiline comments. */
+/* a b c PDI⁩ x y z
+ */
+/* { dg-warning "U\\+2069" "" { target *-*-* } .-2 } */
+/* a b c PDF‬ x y z
+ */
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-2 } */
+/* first
+ a b c PDI⁩ x y z
+ */
+/* { dg-warning "U\\+2069" "" { target *-*-* } .-2 } */
+/* first
+ a b c PDF‬ x y z
+ */
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-2 } */
+/* first
+ a b c PDI⁩ x y z */
+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
+/* first
+ a b c PDF‬ x y z */
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
+
+void
+g1 ()
+{
+ const char *s1 = "a b c LRE‪ 1 2 3 PDF‬ x y z";
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+ const char *s2 = "a b c RLE‫ 1 2 3 PDF‬ x y z";
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+ const char *s3 = "a b c LRO‭ 1 2 3 PDF‬ x y z";
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+ const char *s4 = "a b c RLO‮ 1 2 3 PDF‬ x y z";
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+ const char *s5 = "a b c LRI⁦ 1 2 3 PDI⁩ x y z";
+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
+ const char *s6 = "a b c RLI⁧ 1 2 3 PDI⁩ x y z";
+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
+ const char *s7 = "a b c FSI⁨ 1 2 3 PDI⁩ x y z";
+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
+ const char *s8 = "a b c PDI⁩ x y z";
+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
+ const char *s9 = "a b c PDF‬ x y z";
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
+
+ const char *s10 = "a b c LRE\u202a 1 2 3 PDF\u202c x y z";
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+ const char *s11 = "a b c LRE\u202A 1 2 3 PDF\u202c x y z";
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+ const char *s12 = "a b c RLE\u202b 1 2 3 PDF\u202c x y z";
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+ const char *s13 = "a b c RLE\u202B 1 2 3 PDF\u202c x y z";
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+ const char *s14 = "a b c LRO\u202d 1 2 3 PDF\u202c x y z";
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+ const char *s15 = "a b c LRO\u202D 1 2 3 PDF\u202c x y z";
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+ const char *s16 = "a b c RLO\u202e 1 2 3 PDF\u202c x y z";
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+ const char *s17 = "a b c RLO\u202E 1 2 3 PDF\u202c x y z";
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+ const char *s18 = "a b c LRI\u2066 1 2 3 PDI\u2069 x y z";
+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
+ const char *s19 = "a b c RLI\u2067 1 2 3 PDI\u2069 x y z";
+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
+ const char *s20 = "a b c FSI\u2068 1 2 3 PDI\u2069 x y z";
+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
+}
+
+void
+g2 ()
+{
+ const char c1 = '\u202a';
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+ const char c2 = '\u202A';
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+ const char c3 = '\u202b';
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+ const char c4 = '\u202B';
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+ const char c5 = '\u202d';
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+ const char c6 = '\u202D';
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+ const char c7 = '\u202e';
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+ const char c8 = '\u202E';
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+ const char c9 = '\u2066';
+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
+ const char c10 = '\u2067';
+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
+ const char c11 = '\u2068';
+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
+}
+
+int a‪b‬c;
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+int a‫b‬c;
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+int a‭b‬c;
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+int a‮b‬c;
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+int a⁦b⁩c;
+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
+int a⁧b⁩c;
+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
+int a⁨b⁩c;
+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
+int A‬X;
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
+int A\u202cY;
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
+int A\u202CY2;
+/* { dg-warning "U\\+202C" "" { target *-*-* } .-1 } */
+
+int d\u202ae\u202cf;
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+int d\u202Ae\u202cf2;
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+int d\u202be\u202cf;
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+int d\u202Be\u202cf2;
+/* { dg-warning "U\\+202B" "" { target *-*-* } .-1 } */
+int d\u202de\u202cf;
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+int d\u202De\u202cf2;
+/* { dg-warning "U\\+202D" "" { target *-*-* } .-1 } */
+int d\u202ee\u202cf;
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+int d\u202Ee\u202cf2;
+/* { dg-warning "U\\+202E" "" { target *-*-* } .-1 } */
+int d\u2066e\u2069f;
+/* { dg-warning "U\\+2066" "" { target *-*-* } .-1 } */
+int d\u2067e\u2069f;
+/* { dg-warning "U\\+2067" "" { target *-*-* } .-1 } */
+int d\u2068e\u2069f;
+/* { dg-warning "U\\+2068" "" { target *-*-* } .-1 } */
+int X\u2069;
+/* { dg-warning "U\\+2069" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-5.c b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c
new file mode 100644
index 0000000..68cb053
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-5.c
@@ -0,0 +1,188 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=unpaired -Wno-multichar -Wno-overflow" } */
+/* Test all bidi chars in various contexts (identifiers, comments,
+ string literals, character constants), both UCN and UTF-8. The bidi
+ chars here are properly terminated, except for the character constants. */
+
+/* a b c LRE‪ 1 2 3 PDF‬ x y z */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+/* a b c RLE‫ 1 2 3 PDF‬ x y z */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+/* a b c LRO‭ 1 2 3 PDF‬ x y z */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+/* a b c RLO‮ 1 2 3 PDF‬ x y z */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+/* a b c LRI⁦ 1 2 3 PDI⁩ x y z */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+/* a b c RLI⁧ 1 2 3 PDI⁩ x y */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+/* a b c FSI⁨ 1 2 3 PDI⁩ x y z */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+
+/* Same but C++ comments instead. */
+// a b c LRE‪ 1 2 3 PDF‬ x y z
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+// a b c RLE‫ 1 2 3 PDF‬ x y z
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+// a b c LRO‭ 1 2 3 PDF‬ x y z
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+// a b c RLO‮ 1 2 3 PDF‬ x y z
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+// a b c LRI⁦ 1 2 3 PDI⁩ x y z
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+// a b c RLI⁧ 1 2 3 PDI⁩ x y
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+// a b c FSI⁨ 1 2 3 PDI⁩ x y z
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+
+/* Here we're closing an unopened context, warn when =any. */
+/* a b c PDI⁩ x y z */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+/* a b c PDF‬ x y z */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+// a b c PDI⁩ x y z
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+// a b c PDF‬ x y z
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+
+/* Multiline comments. */
+/* a b c PDI⁩ x y z
+ */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */
+/* a b c PDF‬ x y z
+ */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */
+/* first
+ a b c PDI⁩ x y z
+ */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */
+/* first
+ a b c PDF‬ x y z
+ */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-2 } */
+/* first
+ a b c PDI⁩ x y z */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+/* first
+ a b c PDF‬ x y z */
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+
+void
+g1 ()
+{
+ const char *s1 = "a b c LRE‪ 1 2 3 PDF‬ x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s2 = "a b c RLE‫ 1 2 3 PDF‬ x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s3 = "a b c LRO‭ 1 2 3 PDF‬ x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s4 = "a b c RLO‮ 1 2 3 PDF‬ x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s5 = "a b c LRI⁦ 1 2 3 PDI⁩ x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s6 = "a b c RLI⁧ 1 2 3 PDI⁩ x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s7 = "a b c FSI⁨ 1 2 3 PDI⁩ x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s8 = "a b c PDI⁩ x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s9 = "a b c PDF‬ x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+
+ const char *s10 = "a b c LRE\u202a 1 2 3 PDF\u202c x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s11 = "a b c LRE\u202A 1 2 3 PDF\u202c x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s12 = "a b c RLE\u202b 1 2 3 PDF\u202c x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s13 = "a b c RLE\u202B 1 2 3 PDF\u202c x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s14 = "a b c LRO\u202d 1 2 3 PDF\u202c x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s15 = "a b c LRO\u202D 1 2 3 PDF\u202c x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s16 = "a b c RLO\u202e 1 2 3 PDF\u202c x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s17 = "a b c RLO\u202E 1 2 3 PDF\u202c x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s18 = "a b c LRI\u2066 1 2 3 PDI\u2069 x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s19 = "a b c RLI\u2067 1 2 3 PDI\u2069 x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+ const char *s20 = "a b c FSI\u2068 1 2 3 PDI\u2069 x y z";
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+}
+
+void
+g2 ()
+{
+ const char c1 = '\u202a';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char c2 = '\u202A';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char c3 = '\u202b';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char c4 = '\u202B';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char c5 = '\u202d';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char c6 = '\u202D';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char c7 = '\u202e';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char c8 = '\u202E';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char c9 = '\u2066';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char c10 = '\u2067';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char c11 = '\u2068';
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+}
+
+int a‪b‬c;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int a‫b‬c;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int a‭b‬c;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int a‮b‬c;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int a⁦b⁩c;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int a⁧b⁩c;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int a⁨b⁩c;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int A‬X;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int A\u202cY;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int A\u202CY2;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+
+int d\u202ae\u202cf;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int d\u202Ae\u202cf2;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int d\u202be\u202cf;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int d\u202Be\u202cf2;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int d\u202de\u202cf;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int d\u202De\u202cf2;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int d\u202ee\u202cf;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int d\u202Ee\u202cf2;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int d\u2066e\u2069f;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int d\u2067e\u2069f;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int d\u2068e\u2069f;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
+int X\u2069;
+/* { dg-bogus "unpaired" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-6.c b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c
new file mode 100644
index 0000000..0ce6fff
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-6.c
@@ -0,0 +1,155 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=unpaired" } */
+/* Test nesting of bidi chars in various contexts. */
+
+/* Terminated by the wrong char: */
+/* a b c LRE‪ 1 2 3 PDI⁩ x y z */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* a b c RLE‫ 1 2 3 PDI⁩ x y z*/
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* a b c LRO‭ 1 2 3 PDI⁩ x y z */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* a b c RLO‮ 1 2 3 PDI⁩ x y z */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* a b c LRI⁦ 1 2 3 PDF‬ x y z */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* a b c RLI⁧ 1 2 3 PDF‬ x y z */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* a b c FSI⁨ 1 2 3 PDF‬ x y z*/
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+
+/* LRE‪ PDF‬ */
+/* LRE‪ LRE‪ PDF‬ PDF‬ */
+/* PDF‬ LRE‪ PDF‬ */
+/* LRE‪ PDF‬ LRE‪ PDF‬ */
+/* LRE‪ LRE‪ PDF‬ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* PDF‬ LRE‪ */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+
+// a b c LRE‪ 1 2 3 PDI⁩ x y z
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+// a b c RLE‫ 1 2 3 PDI⁩ x y z*/
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+// a b c LRO‭ 1 2 3 PDI⁩ x y z
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+// a b c RLO‮ 1 2 3 PDI⁩ x y z
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+// a b c LRI⁦ 1 2 3 PDF‬ x y z
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+// a b c RLI⁧ 1 2 3 PDF‬ x y z
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+// a b c FSI⁨ 1 2 3 PDF‬ x y z
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+
+// LRE‪ PDF‬
+// LRE‪ LRE‪ PDF‬ PDF‬
+// PDF‬ LRE‪ PDF‬
+// LRE‪ PDF‬ LRE‪ PDF‬
+// LRE‪ LRE‪ PDF‬
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+// PDF‬ LRE‪
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+
+void
+g1 ()
+{
+ const char *s1 = "a b c LRE‪ 1 2 3 PDI⁩ x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s2 = "a b c LRE\u202a 1 2 3 PDI\u2069 x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s3 = "a b c RLE‫ 1 2 3 PDI⁩ x y ";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s4 = "a b c RLE\u202b 1 2 3 PDI\u2069 x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s5 = "a b c LRO‭ 1 2 3 PDI⁩ x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s6 = "a b c LRO\u202d 1 2 3 PDI\u2069 x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s7 = "a b c RLO‮ 1 2 3 PDI⁩ x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s8 = "a b c RLO\u202e 1 2 3 PDI\u2069 x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s9 = "a b c LRI⁦ 1 2 3 PDF‬ x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s10 = "a b c LRI\u2066 1 2 3 PDF\u202c x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s11 = "a b c RLI⁧ 1 2 3 PDF‬ x y z\
+ ";
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+ const char *s12 = "a b c RLI\u2067 1 2 3 PDF\u202c x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s13 = "a b c FSI⁨ 1 2 3 PDF‬ x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s14 = "a b c FSI\u2068 1 2 3 PDF\u202c x y z";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s15 = "PDF‬ LRE‪";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s16 = "PDF\u202c LRE\u202a";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s17 = "LRE‪ PDF‬";
+ const char *s18 = "LRE\u202a PDF\u202c";
+ const char *s19 = "LRE‪ LRE‪ PDF‬ PDF‬";
+ const char *s20 = "LRE\u202a LRE\u202a PDF\u202c PDF\u202c";
+ const char *s21 = "PDF‬ LRE‪ PDF‬";
+ const char *s22 = "PDF\u202c LRE\u202a PDF\u202c";
+ const char *s23 = "LRE‪ LRE‪ PDF‬";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s24 = "LRE\u202a LRE\u202a PDF\u202c";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s25 = "PDF‬ LRE‪";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s26 = "PDF\u202c LRE\u202a";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s27 = "PDF‬ LRE\u202a";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+ const char *s28 = "PDF\u202c LRE‪";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+}
+
+int aLRE‪bPDI⁩;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int A\u202aB\u2069C;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int aRLE‫bPDI⁩;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int a\u202bB\u2069c;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int aLRO‭bPDI⁩;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int a\u202db\u2069c2;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int aRLO‮bPDI⁩;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int a\u202eb\u2069;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int aLRI⁦bPDF‬;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int a\u2066b\u202c;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int aRLI⁧bPDF‬c
+;
+/* { dg-warning "unpaired" "" { target *-*-* } .-2 } */
+int a\u2067b\u202c;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int aFSI⁨bPDF‬;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int a\u2068b\u202c;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int aFSI⁨bPD\u202C;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int aFSI\u2068bPDF‬_;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int aLRE‪bPDF‬b;
+int A\u202aB\u202c;
+int a_LRE‪_LRE‪_b_PDF‬_PDF‬;
+int A\u202aA\u202aB\u202cB\u202c;
+int aPDF‬bLREadPDF‬;
+int a_\u202C_\u202a_\u202c;
+int a_LRE‪_b_PDF‬_c_LRE‪_PDF‬;
+int a_\u202a_\u202c_\u202a_\u202c_;
+int a_LRE‪_b_PDF‬_c_LRE‪;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int a_\u202a_\u202c_\u202a_;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-7.c b/gcc/testsuite/c-c++-common/Wbidi-chars-7.c
new file mode 100644
index 0000000..d012d42
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-7.c
@@ -0,0 +1,9 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=any" } */
+/* Test we ignore UCNs in comments. */
+
+// a b c \u202a 1 2 3
+// a b c \u202A 1 2 3
+/* a b c \u202a 1 2 3 */
+/* a b c \u202A 1 2 3 */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-8.c b/gcc/testsuite/c-c++-common/Wbidi-chars-8.c
new file mode 100644
index 0000000..4f54c50
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-8.c
@@ -0,0 +1,13 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=any" } */
+/* Test \u vs \U. */
+
+int a_\u202A;
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+int a_\u202a_2;
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+int a_\U0000202A_3;
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
+int a_\U0000202a_4;
+/* { dg-warning "U\\+202A" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-9.c b/gcc/testsuite/c-c++-common/Wbidi-chars-9.c
new file mode 100644
index 0000000..e2af1b1
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-9.c
@@ -0,0 +1,29 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=unpaired" } */
+/* Test that we properly separate bidi contexts (comment/identifier/character
+ constant/string literal). */
+
+/* LRE ->‪<- */ int pdf_\u202c_1;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* RLE ->‫<- */ int pdf_\u202c_2;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* LRO ->‭<- */ int pdf_\u202c_3;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* RLO ->‮<- */ int pdf_\u202c_4;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* LRI ->⁦<-*/ int pdi_\u2069_1;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* RLI ->⁧<- */ int pdi_\u2069_12;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* FSI ->⁨<- */ int pdi_\u2069_3;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+
+const char *s1 = "LRE\u202a"; /* PDF ->‬<- */
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+/* LRE ->‪<- */ const char *s2 = "PDF\u202c";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+const char *s3 = "LRE\u202a"; int pdf_\u202c_5;
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
+int lre_\u202a; const char *s4 = "PDF\u202c";
+/* { dg-warning "unpaired" "" { target *-*-* } .-1 } */
diff --git a/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c b/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c
new file mode 100644
index 0000000..298750a
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/Wbidi-chars-ranges.c
@@ -0,0 +1,54 @@
+/* PR preprocessor/103026 */
+/* { dg-do compile } */
+/* { dg-options "-Wbidi-chars=unpaired -fdiagnostics-show-caret" } */
+/* Verify that we escape and underline pertinent bidirectional
+ control characters when quoting the source. */
+
+int test_unpaired_bidi () {
+ int isAdmin = 0;
+ /*‮ } ⁦if (isAdmin)⁩ ⁦ begin admins only */
+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
+#if 0
+ { dg-begin-multiline-output "" }
+ /*<U+202E> } <U+2066>if (isAdmin)<U+2069> <U+2066> begin admins only */
+ ~~~~~~~~ ~~~~~~~~ ^
+ | | |
+ | | end of bidirectional context
+ U+202E (RIGHT-TO-LEFT OVERRIDE) U+2066 (LEFT-TO-RIGHT ISOLATE)
+ { dg-end-multiline-output "" }
+#endif
+
+ __builtin_printf("You are an admin.\n");
+ /* end admins only ‮ { ⁦*/
+/* { dg-warning "bidirectional" "" { target *-*-* } .-1 } */
+#if 0
+ { dg-begin-multiline-output "" }
+ /* end admins only <U+202E> { <U+2066>*/
+ ~~~~~~~~ ~~~~~~~~ ^
+ | | |
+ | | end of bidirectional context
+ | U+2066 (LEFT-TO-RIGHT ISOLATE)
+ U+202E (RIGHT-TO-LEFT OVERRIDE)
+ { dg-end-multiline-output "" }
+#endif
+
+ return 0;
+}
+
+int LRE_‪_PDF_\u202c;
+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
+#if 0
+ { dg-begin-multiline-output "" }
+ int LRE_<U+202A>_PDF_\u202c;
+ ~~~~~~~~ ^~~~~~
+ { dg-end-multiline-output "" }
+#endif
+
+const char *s1 = "LRE_‪_PDF_\u202c";
+/* { dg-warning "mismatch" "" { target *-*-* } .-1 } */
+#if 0
+ { dg-begin-multiline-output "" }
+ const char *s1 = "LRE_<U+202A>_PDF_\u202c";
+ ~~~~~~~~ ^~~~~~
+ { dg-end-multiline-output "" }
+#endif
diff --git a/gcc/testsuite/c-c++-common/builtin-assoc-barrier-1.c b/gcc/testsuite/c-c++-common/builtin-assoc-barrier-1.c
new file mode 100644
index 0000000..3ff3249
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/builtin-assoc-barrier-1.c
@@ -0,0 +1,71 @@
+// { dg-options "-O2 -ffast-math" }
+/* { dg-do run } */
+
+float a = 1.f;
+float b = 1.e20f;
+
+float
+fast()
+{
+ return __builtin_assoc_barrier (a + b) - b;
+}
+
+__attribute__((optimize("-fno-associative-math")))
+float
+normal()
+{
+ return a + b - b;
+}
+
+void test0()
+{
+ if (fast() != normal())
+ __builtin_abort();
+}
+
+#ifdef __cplusplus
+#ifdef __cpp_constexpr
+constexpr float
+pm(float x, float y)
+{
+ return __builtin_assoc_barrier(x + y) - y;
+}
+
+template <int x>
+ constexpr int
+ f()
+ {
+ return x;
+ }
+#endif
+
+template <class T>
+ T
+ pm(T x, T y)
+ {
+ return __builtin_assoc_barrier(x + y) - y;
+ }
+
+void test1()
+{
+ if (pm(a, b) != normal())
+ __builtin_abort();
+#ifdef __cpp_constexpr
+ constexpr float x = pm(1.f, 1.e20f);
+ constexpr int y = f<int(pm(1.f, 1.e20f))>();
+ if (x != normal())
+ __builtin_abort();
+ if (y != 0)
+ __builtin_abort();
+#endif
+}
+#else
+void test1() {}
+#endif
+
+int main()
+{
+ test0();
+ test1();
+ return 0;
+}
diff --git a/gcc/testsuite/c-c++-common/cpp/dir-only-9.c b/gcc/testsuite/c-c++-common/cpp/dir-only-9.c
new file mode 100644
index 0000000..d11cd97
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/cpp/dir-only-9.c
@@ -0,0 +1,13 @@
+/* PR preprocessor/103130 */
+/* { dg-do preprocess } */
+/* { dg-options -fdirectives-only } */
+
+/*\
+ * this is a comment
+\*/
+
+int
+main ()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/analyzer/pr102662.C b/gcc/testsuite/g++.dg/analyzer/pr102662.C
new file mode 100644
index 0000000..99252c7
--- /dev/null
+++ b/gcc/testsuite/g++.dg/analyzer/pr102662.C
@@ -0,0 +1,39 @@
+/* { dg-additional-options "-fstrict-enums" } */
+
+enum OpCode {
+ OP_MOVE,
+ OP_LOADK,
+ OP_LOADBOOL,
+ OP_LOADNIL,
+ OP_GETUPVAL,
+ OP_SETUPVAL
+};
+
+enum OpArg {
+ OpArgN,
+ OpArgU,
+ OpArgR,
+ OpArgK
+};
+
+void
+symbexec_lastpc (enum OpCode symbexec_lastpc_op, enum OpArg luaP_opmodes)
+{
+ switch (luaP_opmodes)
+ {
+ case OpArgN:
+ case OpArgK:
+ {
+ switch (symbexec_lastpc_op)
+ {
+ case OP_LOADNIL:
+ case OP_SETUPVAL:
+ break;
+ default:
+ break;
+ }
+ }
+ default:
+ break;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto25.C b/gcc/testsuite/g++.dg/cpp0x/auto25.C
index 19d51bc..3af0899 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto25.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto25.C
@@ -3,10 +3,10 @@
template<int> struct A
{
- int a[auto(1)]; // { dg-error "9:invalid use of" }
+ int a[auto(1)]; // { dg-error "9:only available" "" { target c++20_down } }
};
template<int> void foo()
{
- int a[auto(1)]; // { dg-error "9:invalid use of" }
+ int a[auto(1)]; // { dg-error "9:only available" "" { target c++20_down } }
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto9.C b/gcc/testsuite/g++.dg/cpp0x/auto9.C
index 0e80c30..a3a6caf 100644
--- a/gcc/testsuite/g++.dg/cpp0x/auto9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/auto9.C
@@ -45,7 +45,7 @@ foo ()
C<int> c;
dynamic_cast<auto> (c); // { dg-error "auto" }
reinterpret_cast<auto> (c); // { dg-error "auto" }
- int i = auto (0); // { dg-error "auto" }
+ int i = auto (0); // { dg-error "auto" "" { target c++20_down } }
auto p1 = new (auto); // { dg-error "auto" }
auto p2 = new (auto) (42); // { dg-error "invalid use of|deduce" }
offsetof (auto, fld); // { dg-error "auto" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested9.C b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested9.C
new file mode 100644
index 0000000..8f67f22
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-nested9.C
@@ -0,0 +1,41 @@
+// PR c++/94376
+// { dg-do compile { target c++11 } }
+
+int main() {
+ // We used to incorrectly reject the first two cases.
+ int i = 0;
+ [=] () {
+ [=] () mutable {
+ ++i;
+ };
+ };
+
+#if __cpp_init_captures
+ [j=0] () {
+ [=] () mutable {
+ ++j;
+ };
+ };
+#endif
+
+ [=] () {
+ [&] () mutable {
+ ++i; // { dg-error "read-only" }
+ };
+ };
+
+ const int j = 0;
+ [=] () {
+ [=] () mutable {
+ ++j; // { dg-error "read-only" }
+ };
+ };
+
+#if __cpp_init_captures
+ [j=0] () {
+ [&] () mutable {
+ ++j; // { dg-error "read-only" "" { target c++14 } }
+ };
+ };
+#endif
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/eval-order11.C b/gcc/testsuite/g++.dg/cpp1z/eval-order11.C
new file mode 100644
index 0000000..19a24c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/eval-order11.C
@@ -0,0 +1,89 @@
+// PR c++/70796
+// { dg-do run { target c++11 } }
+// { dg-options "-fstrong-eval-order" { target c++14_down } }
+
+struct A
+{
+ int x = 0;
+ A & operator ++ () { ++x; return *this; }
+};
+struct B
+{
+ A first, second;
+ B (A x, A y) : first{x}, second{y} {}
+};
+struct C
+{
+ int first, second;
+ C (int x, int y) : first{x}, second{y} {}
+};
+struct D
+{
+ int d;
+ void foo (int x, D *y)
+ {
+ if (y != this + 1)
+ __builtin_abort ();
+ d = x;
+ }
+};
+D d[2] = { { 1 }, { 2 } };
+
+void
+foo ()
+{
+ int i = 0;
+ C p{++i, ++i};
+ if (p.first != 1 || p.second != 2)
+ __builtin_abort ();
+}
+
+void
+bar ()
+{
+ int i = 0;
+ C p{++i, ++i};
+ if (p.first != 1 || p.second != 2)
+ __builtin_abort ();
+ int &j = i;
+ C q{++j, ++j};
+ if (q.first != 3 || q.second != 4)
+ __builtin_abort ();
+}
+
+void
+baz ()
+{
+ int i = 0;
+ C p{(int &) ++i, (int &) ++i};
+ if (p.first != 1 || p.second != 2)
+ __builtin_abort ();
+}
+
+void
+qux ()
+{
+ A i;
+ B p{++i, ++i};
+ if (p.first.x != 1 || p.second.x != 2)
+ __builtin_abort ();
+}
+
+void
+corge ()
+{
+ D *p = &d[0];
+ p->foo (3, ++p);
+ if (d[0].d != 3 || d[1].d != 2)
+ __builtin_abort ();
+}
+
+int
+main ()
+{
+ bar ();
+ baz ();
+ foo ();
+ qux ();
+ corge ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast1.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast1.C
new file mode 100644
index 0000000..25e53c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast1.C
@@ -0,0 +1,14 @@
+// PR c++/103049
+// P0849R8 - auto(x)
+// { dg-do compile { target c++23 } }
+// Testcase from P0849R8.
+
+struct A {};
+void f(A&) = delete; // #1
+void f(A&&); // #2
+A& g();
+void h() {
+// f(g()); // calls #1
+ f(A(g())); // calls #2 with a temporary object
+ f(auto(g())); // calls #2 with a temporary object
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast2.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast2.C
new file mode 100644
index 0000000..327a448
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast2.C
@@ -0,0 +1,62 @@
+// PR c++/103049
+// P0849R8 - auto(x)
+// { dg-do compile { target c++23 } }
+
+struct X { };
+X& fn ();
+X&& fnr ();
+
+void h()
+{
+ double v[] = { 1.2, 3.4 };
+ +auto(v);
+ +auto{v};
+ static_assert (__is_same_as (decltype (auto(v)), double *));
+ static_assert (__is_same_as (decltype (auto{v}), double *));
+ auto a1 = fn ();
+ static_assert (__is_same_as (decltype (auto(fn())), decltype (a1)));
+ static_assert (__is_same_as (decltype (auto{fn()}), decltype (a1)));
+ auto a2 = fnr ();
+ static_assert (__is_same_as (decltype (auto(fnr())), decltype (a2)));
+ static_assert (__is_same_as (decltype (auto{fnr()}), decltype (a2)));
+ +auto(1);
+ new auto(1);
+ +auto{1};
+ new auto{1};
+}
+
+template<typename T>
+void baz (T t, const T &tr, T &&trr)
+{
+ +auto(t);
+ +auto{t};
+ +auto(tr);
+ +auto{tr};
+ +auto(trr);
+ +auto{trr};
+ static_assert (__is_same_as (decltype (auto(t)), T));
+ static_assert (__is_same_as (decltype (auto{t}), T));
+ static_assert (__is_same_as (decltype (auto(tr)), T));
+ static_assert (__is_same_as (decltype (auto{tr}), T));
+ static_assert (__is_same_as (decltype (auto(trr)), T));
+ static_assert (__is_same_as (decltype (auto{trr}), T));
+}
+
+template<typename = decltype(auto(1))>
+void foo ()
+{
+}
+
+template<int = auto(1)>
+void bar ()
+{
+}
+
+void
+g()
+{
+ foo<>();
+ bar<>();
+ int i = 42;
+ baz (1, i, 42);
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast3.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast3.C
new file mode 100644
index 0000000..1204458
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast3.C
@@ -0,0 +1,21 @@
+// PR c++/103049
+// P0849R8 - auto(x)
+// { dg-do compile { target c++23 } }
+// Test invalid use.
+
+void
+f ()
+{
+ char x[] = "foo";
+ +decltype(auto){x}; // { dg-error "invalid use of .decltype\\(auto\\)." }
+ +decltype(auto)(x); // { dg-error "invalid use of .decltype\\(auto\\)." }
+
+ +auto(); // { dg-error "invalid use of .auto." }
+ new auto(); // { dg-error "requires exactly one element" }
+ +auto{}; // { dg-error "invalid use of .auto." }
+ new auto{}; // { dg-error "requires exactly one element" }
+ +auto(1, 2); // { dg-error "invalid use of .auto." }
+ new auto(1, 2); // { dg-error "requires exactly one element" }
+ +auto{1, 2}; // { dg-error "too many initializers" }
+ new auto{1, 2}; // { dg-error "requires exactly one element" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast4.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast4.C
new file mode 100644
index 0000000..0e26bf2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast4.C
@@ -0,0 +1,26 @@
+// PR c++/103049
+// P0849R8 - auto(x)
+// { dg-do compile { target c++23 } }
+
+class cmdline_parser
+{
+ public:
+ cmdline_parser(char const*);
+
+ auto add_option(char const*, char const*) & -> cmdline_parser &;
+ auto add_option(char const*, char const*) && -> cmdline_parser &&;
+
+ void parse(int, char**);
+};
+
+int main(int argc, char *argv[])
+{
+ auto cmdline = cmdline_parser("driver");
+
+ cmdline.add_option("-h", "show help messages")
+ .add_option("-v", "show version");
+
+ auto internal = auto(cmdline).add_option("--logging-level", "set logging level to 1-3")
+ .add_option("--dump-full", "do not minimize dump");
+ internal.parse(argc, argv);
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast5.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast5.C
new file mode 100644
index 0000000..b29901f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast5.C
@@ -0,0 +1,39 @@
+// PR c++/103049
+// P0849R8 - auto(x)
+// { dg-do compile { target c++23 } }
+
+struct X {
+ X() = default;
+ X(const X&) = delete;
+};
+
+void
+g ()
+{
+ X x;
+ +X(x); // { dg-error "use of deleted function" }
+ +auto(x); // { dg-error "use of deleted function" }
+}
+
+class A;
+void f(A);
+
+class A {
+ int x;
+
+public:
+ A();
+
+ auto run() {
+ f(A(*this));
+ f(auto(*this));
+ }
+
+protected:
+ A(const A&);
+};
+
+void z () {
+ A a;
+ a.run ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/auto-fncast6.C b/gcc/testsuite/g++.dg/cpp23/auto-fncast6.C
new file mode 100644
index 0000000..6b7858d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/auto-fncast6.C
@@ -0,0 +1,14 @@
+// PR c++/103049
+// P0849R8 - auto(x)
+// { dg-do compile { target c++20 } }
+
+void f (int);
+
+void
+g ()
+{
+ auto a1 = auto(f); // { dg-error "only available with" "" { target c++20_only } }
+ auto a2 = auto{f}; // { dg-error "only available with" "" { target c++20_only } }
+ static_assert (__is_same_as (decltype (a1), void(*)(int)));
+ static_assert (__is_same_as (decltype (a2), void(*)(int)));
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C
index 290aaf8..025bbf3 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-2.C
@@ -6,7 +6,8 @@ void foo1(T& t) {
typename T::template C<void> tcv = t;
typename T::template C<auto> u = tcv; // { dg-error "not permitted" "" { target c++20 } }
T::template C<auto>::f (tcv, u); // { dg-error "incomplete|not permitted" }
- (typename T::template D<auto> (t)); // { dg-error "invalid|not permitted" }
+ (typename T::template D<auto> (t)); // { dg-error "invalid|not permitted|unable" }
+// { dg-warning "only available" "" { target c++17_down } .-1 }
}
struct T1 {
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C
index d612327..80a3884 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-pr84979-3.C
@@ -10,7 +10,8 @@ void foo1(T& t) {
typename T::template C<void> tcv = t;
typename T::template C<auto> u = tcv; // { dg-error "not permitted" "" { target c++20 } }
T::template C<auto>::f (tcv, u); // { dg-error "incomplete|not permitted" }
- (typename T::template D<auto> (t)); // { dg-error "invalid|not permitted" }
+ (typename T::template D<auto> (t)); // { dg-error "invalid|not permitted|no class" }
+// { dg-warning "only available" "" { target c++17_down } .-1 }
}
struct T1 {
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C
index 22696c3..0103e7a 100644
--- a/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-recursive-sat1.C
@@ -3,16 +3,21 @@
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)
+namespace ns
{
- return foo<N + 1>(t);
+ struct S { };
+
+ template<int N, typename T>
+ requires Foo<N, T>
+ int foo(T t)
+ {
+ return foo<N + 1>(t);
+ }
}
int main(int, char**)
{
- return foo<1>(1);
+ return foo<1>(ns::S{});
}
// { dg-prune-output "compilation terminated" }
diff --git a/gcc/testsuite/g++.dg/cpp2a/concepts-this1.C b/gcc/testsuite/g++.dg/cpp2a/concepts-this1.C
new file mode 100644
index 0000000..d717028
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/concepts-this1.C
@@ -0,0 +1,30 @@
+// PR c++/103198
+// { dg-do compile { target c++20 } }
+
+template<class T, class = void>
+struct A {
+ T val;
+
+ template<class U>
+ requires requires { val.x; }
+ void f(U);
+
+ static void g(int)
+ requires requires { val.x; };
+
+ void h(int)
+ requires requires { val.x; };
+};
+
+struct B { int x; };
+struct C { };
+
+int main() {
+ A<B>().f(0);
+ A<B>().g(0);
+ A<B>().h(0);
+
+ A<C>().f(0); // { dg-error "no match" }
+ A<C>().g(0); // { dg-error "no match" }
+ A<C>().h(0); // { dg-error "no match" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/fn-template23.C b/gcc/testsuite/g++.dg/cpp2a/fn-template23.C
new file mode 100644
index 0000000..b85d4c9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/fn-template23.C
@@ -0,0 +1,36 @@
+// PR c++/102670
+// { dg-do compile { target c++20 } }
+
+namespace ns {
+ struct S { };
+
+ template<int I>
+ constexpr int adl(const S &) {
+ return I;
+ }
+}
+
+namespace redirect {
+ template<class T, int I>
+ concept can_call_adl = requires(T t) {
+ adl<I>(t);
+ };
+
+ template<int I>
+ struct adl_fn {
+ template<can_call_adl<I> T>
+ constexpr decltype(auto) operator()(T t) const {
+ return adl<I>(t);
+ }
+ };
+
+ namespace {
+ template<int I>
+ constexpr inline adl_fn<I> adl{};
+ }
+}
+
+int main() {
+ static_assert(redirect::can_call_adl<ns::S, 3>);
+ redirect::adl<3>(ns::S{});
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/fn-template24.C b/gcc/testsuite/g++.dg/cpp2a/fn-template24.C
new file mode 100644
index 0000000..b444ac6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/fn-template24.C
@@ -0,0 +1,16 @@
+// PR c++/99911
+// { dg-do compile { target c++20 } }
+
+namespace N {
+ struct A { };
+ template<class T> void get(A);
+};
+
+template<class T>
+auto f() {
+ return []<class U>(U) { get<U>(T{}); };
+}
+
+int main() {
+ f<N::A>()(0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/fn-template25.C b/gcc/testsuite/g++.dg/cpp2a/fn-template25.C
new file mode 100644
index 0000000..5da409c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/fn-template25.C
@@ -0,0 +1,12 @@
+// { dg-do compile { target c++20 } }
+
+template<class T>
+void f() {
+ g<int>(T{}); // { dg-error "argument-dependent lookup" }
+ // { dg-bogus "no match" "" { target *-*-* } .-1 }
+}
+
+template<class T>
+void g(int); // { dg-message "declared here, later" }
+
+template void f<int>();
diff --git a/gcc/testsuite/g++.dg/gomp/masked-1.C b/gcc/testsuite/g++.dg/gomp/masked-1.C
new file mode 100644
index 0000000..1ea4a13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/gomp/masked-1.C
@@ -0,0 +1,14 @@
+// PR c++/103349
+// { dg-do compile { target c++11 } }
+
+int v;
+
+void
+foo (int x, int y)
+{
+ [=] ()
+ {
+#pragma omp masked
+ v = x + y;
+ } ();
+}
diff --git a/gcc/testsuite/g++.dg/pr102988.C b/gcc/testsuite/g++.dg/pr102988.C
new file mode 100644
index 0000000..05a1a8f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr102988.C
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fharden-conditional-branches -fchecking=1" } */
+
+/* DECL_BY_REFERENCE RESULT_DECL is read-only, we can't create a copy
+ of its (address) default def and set it. */
+
+void ll();
+struct k {
+ ~k();
+};
+k ice(k *a)
+{
+ k v;
+ if (&v!= a)
+ ll();
+ return v;
+}
diff --git a/gcc/testsuite/g++.dg/pr103326.C b/gcc/testsuite/g++.dg/pr103326.C
new file mode 100644
index 0000000..260e7da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr103326.C
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-require-effective-target c++11 }
+
+using x86_64_v16qi [[gnu::__vector_size__ (16)]] = char;
+
+template<typename T>
+void foo()
+{
+ constexpr x86_64_v16qi zero{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+}
+
+void foo2()
+{
+ foo<int>();
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr103266.C b/gcc/testsuite/g++.dg/torture/pr103266.C
new file mode 100644
index 0000000..d5c13f5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr103266.C
@@ -0,0 +1,23 @@
+// { dg-do run }
+/* { dg-additional-options "-std=c++14" } */
+ typedef unsigned int u32;
+ typedef unsigned char u8;
+
+ static u32 pu8to32(const u8 * p8) __attribute__((noinline));
+ static u32 pu8to32(const u8 * p8) {
+ u32 v;
+
+ __builtin_memcpy(&v, __builtin_assume_aligned(p8, 1), sizeof(u32));
+
+ return v;
+ }
+
+ int main(void) {
+ // dse1 throws this store away
+ u8 d[sizeof(u32)] = {
+ 0x07, 0x00, 0x00, 0x07,
+ };
+
+ if (pu8to32(d) != 0x07000007)
+ __builtin_trap();
+ }
diff --git a/gcc/testsuite/g++.dg/torture/pr103351.C b/gcc/testsuite/g++.dg/torture/pr103351.C
new file mode 100644
index 0000000..d0bf721
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr103351.C
@@ -0,0 +1,88 @@
+// { dg-do compile }
+// { dg-additional-options "-fcompare-debug" }
+
+template <int> struct __conditional;
+template <bool _Cond, typename, typename>
+using __conditional_t = typename __conditional<_Cond>::type;
+template <typename> struct __is_void_helper {};
+template <typename _Tp> _Tp *__addressof(_Tp &__r) {
+ return __builtin_addressof(__r);
+}
+template <typename _Tp> _Tp *addressof(_Tp &__r) { return __addressof(__r); }
+template <typename _Tp>
+using __make_not_void = __conditional_t<_Tp ::value, int, _Tp>;
+template <typename> struct pointer_traits;
+template <typename _Tp> struct pointer_traits<_Tp *> {
+ typedef _Tp *pointer;
+ typedef _Tp element_type;
+ static pointer pointer_to(element_type &__r) { return addressof(__r); }
+};
+namespace {
+template <typename> struct new_allocator;
+}
+template <typename> struct allocator_traits;
+template <typename> struct allocator;
+template <typename _Tp> struct allocator_traits<allocator<_Tp>> {
+ using pointer = _Tp *;
+ using const_pointer = _Tp *;
+};
+namespace __gnu_cxx {
+template <typename = char>
+struct __alloc_traits : allocator_traits<allocator<char>> {};
+} // namespace __gnu_cxx
+template <class> struct char_traits;
+template <typename _CharT, typename = _CharT>
+class Trans_NS___cxx11_basic_string;
+template <> struct char_traits<char> {
+ typedef char char_type;
+ static void assign(char_type, char_type);
+};
+template <typename, typename> struct Trans_NS___cxx11_basic_string {
+ typedef __gnu_cxx::__alloc_traits<> _Alloc_traits;
+ typedef char_traits<char> traits_type;
+ typedef _Alloc_traits::pointer pointer;
+ typedef _Alloc_traits::const_pointer const_pointer;
+ struct {
+ pointer _M_p;
+ } _M_dataplus;
+ char _M_local_buf[];
+ void _M_data(pointer __p) { _M_dataplus._M_p = __p; }
+ bool _M_is_local() {
+ const_pointer __trans_tmp_5 =
+ pointer_traits<const_pointer>::pointer_to(*_M_local_buf);
+ return _M_dataplus._M_p == __trans_tmp_5;
+ }
+ void operator=(Trans_NS___cxx11_basic_string __str) {
+ bool __trans_tmp_2;
+ if (__str._M_is_local()) {
+ Trans_NS___cxx11_basic_string *__trans_tmp_1;
+ if (__builtin_expect(__trans_tmp_1 != this, true))
+ size();
+ } else if (__trans_tmp_2)
+ __str._M_data(__str._M_local_buf);
+ __str.clear();
+ }
+ void size();
+ void clear() { traits_type::assign(_M_dataplus._M_p[0], char()); }
+};
+template <class, typename, int> struct Pool {
+ template <class T> struct PoolIterator {
+ bool operator!=(PoolIterator);
+ T *operator*();
+ void operator++();
+ };
+ template <class T> struct IterateWrapper {
+ PoolIterator<T> begin();
+ PoolIterator<T> end();
+ };
+};
+struct BaseConsist {
+ Trans_NS___cxx11_basic_string<char> name;
+};
+struct Vehicle : BaseConsist {};
+Pool<int, int, true>::IterateWrapper<Vehicle> __trans_tmp_4;
+Trans_NS___cxx11_basic_string<char> __trans_tmp_6;
+void FixOldVehicles() {
+ for (Vehicle *v : __trans_tmp_4)
+ v->name = __trans_tmp_6;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Waddress-7.C b/gcc/testsuite/g++.dg/warn/Waddress-7.C
new file mode 100644
index 0000000..efdafa5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Waddress-7.C
@@ -0,0 +1,76 @@
+/* PR c/33925 - missing -Waddress with the address of an inline function
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+struct A
+{
+ int mf ();
+ int mf_def () { return 0; }
+
+ static int smf ();
+ static int smf_def () { return 0; }
+
+ int mi;
+ static int smi;
+ static int smi_def;
+
+ __attribute__ ((weak)) static int wsmi;
+ __attribute__ ((weak)) static int wsmi_def;
+
+ int mia[];
+ static int smia[];
+ static int smia_def[];
+
+ __attribute__ ((weak)) static int wsmia[];
+ __attribute__ ((weak)) static int wsmia_def[];
+
+ void test_waddress (bool*);
+};
+
+
+/* __attribute__ ((weak)) static */ int A::smi_def = 0;
+/* __attribute__ ((weak)) static */ int A::smia_def[] = { 0 };
+
+/* __attribute__ ((weak)) static */ int A::wsmi_def = 0;
+/* __attribute__ ((weak)) static */ int A::wsmia_def[] = { 0 };
+
+
+
+void A::test_waddress (bool *p)
+{
+ if (mf) // { dg-error "cannot convert" }
+ p++;
+ if (mf_def) // { dg-error "cannot convert" }
+ p++;
+
+ if (smf) // { dg-warning "-Waddress" }
+ p++;
+ if (smf_def) // { dg-warning "-Waddress" }
+ p++;
+
+ if (&mi) // { dg-warning "-Waddress" }
+ p++;
+ if (&smi) // { dg-warning "-Waddress" }
+ p++;
+ if (&smi_def) // { dg-warning "-Waddress" }
+ p++;
+
+ if (&wsmi)
+ p++;
+
+ if (&wsmi_def) // { dg-warning "-Waddress" }
+ p++;
+
+ if (mia) // { dg-warning "-Waddress" }
+ p++;
+ if (smia) // { dg-warning "-Waddress" }
+ p++;
+ if (smia_def) // { dg-warning "-Waddress" }
+ p++;
+
+ if (wsmia)
+ p++;
+
+ if (wsmia_def) // { dg-warning "-Waddress" }
+ p++;
+}
diff --git a/gcc/testsuite/g++.dg/warn/Walways-true-2.C b/gcc/testsuite/g++.dg/warn/Walways-true-2.C
index 29a80e5..e951e95 100644
--- a/gcc/testsuite/g++.dg/warn/Walways-true-2.C
+++ b/gcc/testsuite/g++.dg/warn/Walways-true-2.C
@@ -9,7 +9,7 @@
extern int foo (int) __attribute__ ((weak));
-int i __attribute__ ((weak));
+extern int i __attribute__ ((weak));
void
bar (int a)
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-14.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-14.C
new file mode 100644
index 0000000..cebadf1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-14.C
@@ -0,0 +1,31 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized" }
+
+struct A {
+ int m;
+ int get() const { return m; }
+
+ A() : m{} { }
+ A(int) { }
+ A(const A &) { }
+ A(A *) { }
+};
+
+struct S {
+ A a, b;
+
+ S(int (*)[1]) : a() {}
+ S(int (*)[2]) : b(a.get()) {}
+ S(int (*)[3]) : b(a) {}
+ S(int (*)[4]) : a(&a) {}
+};
+
+struct R {
+ A a, b;
+
+ R(int (*)[1]) : a{} {}
+ R(int (*)[2]) : b{a.get()} {}
+ R(int (*)[3]) : b{a} {}
+ R(int (*)[4]) : a{&a} {}
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-15.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-15.C
new file mode 100644
index 0000000..89e9066
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-15.C
@@ -0,0 +1,118 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized -Winit-self" }
+// Largely copied from clang's test/SemaCXX/uninitialized.cpp.
+
+int x;
+struct U {
+ U() : b(a) { }
+ int &a = x;
+ int &b;
+};
+
+struct T {
+ T() : a(b), b(a) { } // { dg-warning "reference .T::b. is not yet bound" }
+ int &a, &b;
+};
+
+struct S {
+ S() : a(a) { } // { dg-warning ".S::a. is initialized with itself" }
+ int &a;
+};
+
+struct A {
+ int a;
+ int b;
+ A() { }
+ A(int (*)[1]) : b(a) { } // { dg-warning ".A::a. is used uninitialized" }
+ A(int (*)[2]) : a(b) { } // { dg-warning ".A::b. is used uninitialized" }
+};
+
+struct D {
+ int a;
+ int &b;
+ int &c = a;
+ int d = b;
+ D() : b(a) { }
+};
+
+struct E {
+ int a;
+ int get();
+ static int num();
+ E() { }
+ E(int) { }
+};
+
+struct F {
+ int a;
+ E e;
+ int b;
+ F(int (*)[1]) : a(e.get()) { } // { dg-warning "member .F::e. is used uninitialized" }
+ F(int (*)[2]) : a(e.num()) { }
+ F(int (*)[3]) : e(a) { } // { dg-warning "member .F::a. is used uninitialized" }
+ F(int (*)[4]) : a(4), e(a) { }
+ F(int (*)[5]) : e(b) { } // { dg-warning "member .F::b. is used uninitialized" }
+ F(int (*)[6]) : e(b), b(4) { } // { dg-warning "member .F::b. is used uninitialized" }
+};
+
+struct G {
+ G(const A&) { };
+};
+
+struct H {
+ A a1;
+ G g;
+ A a2;
+ H() : g(a1) { }
+ // ??? clang++ doesn't warn here
+ H(int) : g(a2) { } // { dg-warning "member .H::a2. is used uninitialized" }
+};
+
+struct I {
+ I(int *) { }
+};
+
+struct J : I {
+ int *a;
+ int *b;
+ int c;
+ J() : I((a = new int(5))), b(a), c(*a) { }
+};
+
+struct M { };
+
+struct N : public M {
+ int a;
+ int b;
+ N() : b(a) { } // { dg-warning "member .N::a. is used uninitialized" }
+};
+
+struct O {
+ int x = 42;
+ int get() { return x; }
+};
+
+struct P {
+ O o;
+ int x = o.get();
+ P() : x(o.get()) { }
+};
+
+struct Q {
+ int a;
+ int b;
+ int &c;
+ Q() :
+ a(c = 5), // "reference .Q::c. is not yet bound" but too complex for the FE
+ b(c), // "reference .Q::c. is not yet bound" but too complex for the FE
+ c(a) { }
+};
+
+struct R {
+ int a;
+ int b;
+ int c;
+ int d = a + b + c;
+ R() : a(c = 5), b(c), c(a) { }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-16.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-16.C
new file mode 100644
index 0000000..38f587b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-16.C
@@ -0,0 +1,12 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized" }
+
+struct S {
+ int a;
+ int b;
+ int c;
+ S() : a((b = 42)), c(b) { }
+ S(int) : a(((1, b) = 42)), c(b) { }
+ S(char) : a(((c++, b) = 42)), c(b) { } // "field .S::c. is used uninitialized" but too complex for the FE
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-17.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-17.C
new file mode 100644
index 0000000..80c37ac
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-17.C
@@ -0,0 +1,33 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized -Winit-self" }
+
+int
+foo (int *p)
+{
+ *p = 42;
+ return 5;
+}
+
+struct S {
+ int x;
+ int y;
+ int z;
+ S() : x(foo (&y)), z(y) { } // { dg-bogus "uninitialized" }
+};
+
+struct T {
+ int x;
+ int y;
+ int z;
+ T() : x(({ y = 30; 42; })), z(y) { } // { dg-bogus "uninitialized" }
+};
+
+struct A {
+ int x, y, z;
+ int f () { y = 1; return 2; }
+ A ():
+ x (f ()),
+ z (y) // { dg-bogus "uninitialized" }
+ { }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-18.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-18.C
new file mode 100644
index 0000000..29ae77a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-18.C
@@ -0,0 +1,22 @@
+// PR c++/96121
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized" }
+
+struct A {
+ A();
+ int i;
+};
+struct B {
+ B(A);
+ int i;
+};
+
+struct composed2 {
+ B b_;
+ A a_;
+ composed2() : b_(a_) {} // { dg-warning "member .composed2::a_. is used uninitialized" }
+};
+
+composed2 test() {
+ return composed2{};
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-19.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-19.C
new file mode 100644
index 0000000..e4d53d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-19.C
@@ -0,0 +1,50 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized" }
+// Test we warn when initializing a base class.
+
+struct A {
+ A(int) { }
+};
+
+struct B : public A {
+ int x;
+ B() : A(x) { } // { dg-warning "member .B::x. is used uninitialized" }
+};
+
+struct C : public A {
+ int x;
+ int y;
+ C() : A(y = 4), x(y) { }
+};
+
+struct D : public A {
+ int x;
+ D() : A{x} { } // { dg-warning "member .D::x. is used uninitialized" }
+};
+
+struct E : public A {
+ int x;
+ int y;
+ E() : A{y = 4}, x(y) { }
+};
+
+struct F {
+ F(int&) { }
+};
+
+struct G : F {
+ int x;
+ G() : F(x) { }
+};
+
+struct H {
+ H(int *) { }
+};
+
+struct I : H {
+ int x;
+ int arr[2];
+ I() : H(&x) { }
+ I(int) : H(arr) { }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-20.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-20.C
new file mode 100644
index 0000000..867c4da
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-20.C
@@ -0,0 +1,16 @@
+// PR c++/96121
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized" }
+// Test we warn with delegating constructors.
+
+struct A {
+ A(int);
+ A(int &, int);
+ A(int (*)[1]) : A(x) { } // { dg-warning "21:member .A::x. is used uninitialized" }
+ A(int (*)[2]) : A(x, x) { } // { dg-warning "24:member .A::x. is used uninitialized" }
+ A(int (*)[3]) : A(x, 0) { }
+ A(int (*)[4]) : A{x} { } // { dg-warning "21:member .A::x. is used uninitialized" }
+ A(int (*)[5]) : A{x, x} { } // { dg-warning "24:member .A::x. is used uninitialized" }
+ A(int (*)[6]) : A{x, 0} { }
+ int x;
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-21.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-21.C
new file mode 100644
index 0000000..57ca00a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-21.C
@@ -0,0 +1,20 @@
+// PR c++/19808
+// { dg-do compile }
+// { dg-options "-Wuninitialized" }
+
+struct A {
+ int a;
+ int b;
+ A(int) {}
+};
+
+struct S {
+ A a;
+ A a2;
+ S() :
+ /* We don't warn here, because we consider partial initialization
+ as initializing the whole object. */
+ a((a2.a = 42)),
+ a2(a2.a)
+ { }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-22.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-22.C
new file mode 100644
index 0000000..89686a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-22.C
@@ -0,0 +1,37 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized -Winit-self" }
+// Test that we don't warn when initializing a reference, unless it's
+// self-init.
+
+struct R {
+ int &r;
+};
+
+struct S {
+ R r;
+ int a;
+ int &b;
+ int c;
+};
+
+struct X {
+ S s;
+ X() : s{ { s.a }, 1, s.c, 3} { }
+};
+
+struct A {
+ int &r;
+ A() : r{r} { } // { dg-warning ".A::r. is initialized with itself" }
+};
+
+struct B {
+ int &r;
+ int a;
+ B() : r{a} { }
+};
+
+struct C {
+ R x;
+ C() : x{x.r} { } // { dg-warning "member .C::x. is used uninitialized" }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-23.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-23.C
new file mode 100644
index 0000000..7cb2a9e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-23.C
@@ -0,0 +1,24 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized" }
+// Test that we don't warn in an uninstantiated template.
+
+struct A {
+ int *fn() { return nullptr; }
+};
+
+template<typename T>
+struct B {
+ B() : p(a->fn()) { }
+ A *a;
+ int *p;
+};
+
+template<typename T>
+struct C {
+ C() : p(a->fn()) { } // { dg-warning "member .C<int>::a. is used uninitialized" }
+ A *a;
+ int *p;
+};
+
+C<int> c;
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-24.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-24.C
new file mode 100644
index 0000000..e5dd429
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-24.C
@@ -0,0 +1,89 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized -Winit-self" }
+
+int fint(int);
+int fintp(int *);
+int fintr(int &);
+int fintcr(const int &);
+
+int arr[10];
+
+struct S {
+ int x;
+ int y;
+ const int z = 42;
+ int *p;
+
+ S(int (*)[1]) : x(x) { } // { dg-warning "initialized with itself" }
+ S(int (*)[2]) : x(x + x) { } // { dg-warning "member .S::x. is used uninitialized" }
+ S(int (*)[3]) : x(static_cast<int>(y)) { } // { dg-warning "member .S::y. is used uninitialized" }
+ S(int (*)[4]) : x(static_cast<int>(x)) { } // { dg-warning "member .S::x. is used uninitialized" }
+ S(int (*)[5]) : x(fint(x)) { }
+ S(int (*)[6]) : x(fint(y)) { }
+
+ S(int (*)[7]) : x(sizeof(x)) { }
+ S(int (*)[8]) : x(sizeof(y)) { }
+ S(int (*)[9]) : p(&x) { }
+ S(int (*)[10]) : x(fintp(&y)) { }
+ S(int (*)[11]) : x(fintr(y)) { }
+ S(int (*)[12]) : x(fintcr(y)) { }
+ S(int (*)[26]) : x(((void)(__typeof(y)) 1, 1)) { }
+ S(int (*)[27]) : x(((void)(decltype(y)) 1, 1)) { }
+ S(int (*)[28]) : x(__alignof__(y)) { }
+ S(int (*)[29]) : x(noexcept(y)) { }
+
+ S(int (*)[13]) : x(0), y(x ? y : y) { }
+ S(int (*)[14]) : x(0), y(1 + (x ? y : y)) { }
+ S(int (*)[15]) : x(-y) { } // { dg-warning "member .S::y. is used uninitialized" }
+ S(int (*)[16]) : x(1 << y) { } // { dg-warning "member .S::y. is used uninitialized" }
+ S(int (*)[17]) : x(this->y) { } // { dg-warning "member .S::y. is used uninitialized" }
+ S(int (*)[18]) : x(arr[y]) { } // { dg-warning "member .S::y. is used uninitialized" }
+ S(int (*)[19]) : x(0), y(x ? x : y) { }
+ S(int (*)[20]) : x(0), y(y ? x : y) { }
+ S(int (*)[21]) : x(0), y(y ? x : x) { }
+ S(int (*)[22]) : x(0), y((fint(y), x)) { }
+ S(int (*)[23]) : x(0), y(x += y) { } // "member .S::y. is used uninitialized" but too complex for the FE
+ S(int (*)[24]) : x(y += 10) { } // "member .S::y. is used uninitialized" but too complex for the FE
+ S(int (*)[25]) : x(y++) { } // { dg-warning "member .S::y. is used uninitialized" }
+};
+
+// Same, but { }.
+struct R {
+ int x;
+ int y;
+ const int z = 42;
+ int *p;
+
+ R(int (*)[1]) : x{x} { } // { dg-warning "member .R::x. is used uninitialized" }
+ R(int (*)[2]) : x{x + x} { } // { dg-warning "member .R::x. is used uninitialized" }
+ R(int (*)[3]) : x{static_cast<int>(y)} { } // { dg-warning "member .R::y. is used uninitialized" }
+ R(int (*)[4]) : x{static_cast<int>(x)} { } // { dg-warning "member .R::x. is used uninitialized" }
+ R(int (*)[5]) : x{fint(x)} { }
+ R(int (*)[6]) : x{fint(y)} { }
+
+ R(int (*)[7]) : x{sizeof(x)} { }
+ R(int (*)[8]) : x{sizeof(y)} { }
+ R(int (*)[9]) : p{&x} { }
+ R(int (*)[10]) : x{fintp(&y)} { }
+ R(int (*)[11]) : x{fintr(y)} { }
+ R(int (*)[12]) : x{fintcr(y)} { }
+ R(int (*)[26]) : x{((void)(__typeof(y)) 1, 1)} { }
+ R(int (*)[27]) : x{((void)(decltype(y)) 1, 1)} { }
+ R(int (*)[28]) : x{__alignof__(y)} { }
+ R(int (*)[29]) : x{noexcept(y)} { }
+
+ R(int (*)[13]) : x{0}, y{x ? y : y} { }
+ R(int (*)[14]) : x{0}, y{1 + (x ? y : y)} { }
+ R(int (*)[15]) : x{-y} { } // { dg-warning "member .R::y. is used uninitialized" }
+ R(int (*)[16]) : x{1 << y} { } // { dg-warning "member .R::y. is used uninitialized" }
+ R(int (*)[17]) : x{this->y} { } // { dg-warning "member .R::y. is used uninitialized" }
+ R(int (*)[18]) : x{arr[y]} { } // { dg-warning "member .R::y. is used uninitialized" }
+ R(int (*)[19]) : x{0}, y{x ? x : y} { }
+ R(int (*)[20]) : x{0}, y{y ? x : y} { }
+ R(int (*)[21]) : x{0}, y{y ? x : x} { }
+ R(int (*)[22]) : x{0}, y{(fint(y), x)} { }
+ R(int (*)[23]) : x{0}, y{x += y} { } // "member .R::y. is used uninitialized" but too complex for the FE
+ R(int (*)[24]) : x{y += 10} { } // "member .R::y. is used uninitialized" but too complex for the FE
+ R(int (*)[25]) : x{y++} { } // { dg-warning "member .R::y. is used uninitialized" }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-25.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-25.C
new file mode 100644
index 0000000..fb652f9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-25.C
@@ -0,0 +1,12 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wall" }
+
+struct A {
+ A *a;
+};
+
+struct B : A {
+ int i;
+ B() : A{a} {}
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-26.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-26.C
new file mode 100644
index 0000000..a887d12
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-26.C
@@ -0,0 +1,22 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized" }
+// Anonymous union/struct.
+// ??? The diagnostic should be improved to say 'b' instead of
+// "<anonymous>".
+
+struct S {
+ __extension__ struct {
+ int a;
+ int b;
+ };
+ S() : a(b) { } // { dg-warning "is used uninitialized" }
+};
+
+struct U {
+ union {
+ int a;
+ int b;
+ };
+ U() : a(b) { } // { dg-warning "is used uninitialized" }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-27.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-27.C
new file mode 100644
index 0000000..24e6b9b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-27.C
@@ -0,0 +1,20 @@
+// PR c++/19808
+// { dg-do compile }
+// { dg-options "-Wall" }
+
+enum E { red };
+
+struct C {
+ C(int *, unsigned);
+};
+
+template <unsigned U> struct D : C {
+ D(int, int, E) : C(e, U) {}
+ int e[2];
+};
+
+void
+g ()
+{
+ D<1>(0, 0, red);
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-28.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-28.C
new file mode 100644
index 0000000..7dbbf87
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-28.C
@@ -0,0 +1,59 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized" }
+
+struct S {
+ int i, j, k, l;
+ S() : i(j), // { dg-warning "member .S::j. is used uninitialized" }
+ j(1),
+ k(l + 1), // { dg-warning "member .S::l. is used uninitialized" }
+ l(2) { }
+};
+
+struct A {
+ int a, b, c;
+ A() : a(b // { dg-warning "member .A::b. is used uninitialized" }
+ + c) { } // { dg-warning "member .A::c. is used uninitialized" }
+};
+
+struct B {
+ int &r;
+ int *p;
+ int a;
+ B() : r(a), p(&a), a(1) { }
+};
+
+struct C {
+ const int &r1, &r2;
+ C () : r1(r2), // { dg-warning "reference .C::r2. is not yet bound to a value when used here" }
+ r2(r1) { }
+};
+
+struct D {
+ int a = 1;
+ int b = 2;
+ D() : a(b + 1), b(a + 1) { } // { dg-warning "member .D::b. is used uninitialized" }
+};
+
+struct E {
+ int a = 1;
+ E() : a(a + 1) { } // { dg-warning "member .E::a. is used uninitialized" }
+};
+
+struct F {
+ int a = 1;
+ int b;
+ F() : b(a + 1) { }
+};
+
+struct bar {
+ bar() {}
+ bar(bar&) {}
+};
+
+class foo {
+ bar first;
+ bar second;
+public:
+ foo() : first(second) {} // { dg-warning "member .foo::second. is used uninitialized" }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-29.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-29.C
new file mode 100644
index 0000000..bc74299
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-29.C
@@ -0,0 +1,59 @@
+// PR c++/19808
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wuninitialized" }
+
+struct S {
+ int i, j, k, l;
+ S() : i{j}, // { dg-warning "member .S::j. is used uninitialized" }
+ j{1},
+ k{l + 1}, // { dg-warning "member .S::l. is used uninitialized" }
+ l{2} { }
+};
+
+struct A {
+ int a, b, c;
+ A() : a{b // { dg-warning "member .A::b. is used uninitialized" }
+ + c} { } // { dg-warning "member .A::c. is used uninitialized" }
+};
+
+struct B {
+ int &r;
+ int *p;
+ int a;
+ B() : r{a}, p{&a}, a{1} { }
+};
+
+struct C {
+ const int &r1, &r2;
+ C () : r1{r2}, // { dg-warning "reference .C::r2. is not yet bound to a value when used here" }
+ r2{r1} { }
+};
+
+struct D {
+ int a = 1;
+ int b = 2;
+ D() : a{b + 1}, b{a + 1} { } // { dg-warning "member .D::b. is used uninitialized" }
+};
+
+struct E {
+ int a = 1;
+ E() : a{a + 1} { } // { dg-warning "member .E::a. is used uninitialized" }
+};
+
+struct F {
+ int a = 1;
+ int b;
+ F() : b{a + 1} { }
+};
+
+struct bar {
+ bar() {}
+ bar(bar&) {}
+};
+
+class foo {
+ bar first;
+ bar second;
+public:
+ foo() : first{second} {} // { dg-warning "member .foo::second. is used uninitialized" }
+};
diff --git a/gcc/testsuite/g++.dg/warn/Wuninitialized-30.C b/gcc/testsuite/g++.dg/warn/Wuninitialized-30.C
new file mode 100644
index 0000000..ba0f76e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wuninitialized-30.C
@@ -0,0 +1,13 @@
+// PR c++/19808
+// { dg-do compile }
+// { dg-options "-Wuninitialized" }
+
+class diagnostic_event {
+public:
+ virtual int get_stack_depth();
+};
+struct event_range {
+ event_range(diagnostic_event &initial_event)
+ : m_stack_depth(initial_event.get_stack_depth()) {}
+ int m_stack_depth;
+};
diff --git a/gcc/testsuite/g++.target/i386/pr101180.C b/gcc/testsuite/g++.target/i386/pr101180.C
new file mode 100644
index 0000000..4830708
--- /dev/null
+++ b/gcc/testsuite/g++.target/i386/pr101180.C
@@ -0,0 +1,25 @@
+// PR c++/101180
+// { dg-do compile { target c++11 } }
+
+#pragma GCC target "avx"
+template <typename> struct A {};
+#pragma GCC push_options
+#pragma GCC target "avx,avx2,bmi,bmi2,fma,f16c"
+template <typename T> using B = A<T>;
+template <typename> struct C;
+template <> struct C<float> {
+ __attribute__((always_inline)) float operator()(long) { return .0f; }
+};
+long d;
+template <typename T> void e(B<T>) {
+ T{C<T>()(d)};
+}
+template <typename T, typename FromT> void f(T d, FromT) {
+ e(d);
+}
+int g;
+void h() {
+ A<float> i;
+ f(i, g);
+}
+#pragma GCC pop_options
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr103288-1.c b/gcc/testsuite/gcc.c-torture/compile/pr103288-1.c
new file mode 100644
index 0000000..88d1c67
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr103288-1.c
@@ -0,0 +1,6 @@
+
+int ui_5;
+long func_14_uli_8;
+void func_14() {
+ ui_5 &= (func_14_uli_8 ? 60 : ui_5) ? 5 : 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr103314-1.c b/gcc/testsuite/gcc.c-torture/compile/pr103314-1.c
new file mode 100644
index 0000000..f4a6313
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr103314-1.c
@@ -0,0 +1,6 @@
+/* { dg-options "" } */
+int main() {
+ int t = 1;
+ unsigned c = 0, d1 = t ? 1 ^ c ^ 1 >> (-1) : 0; /* { dg-warning "is negative" } */
+ return d1;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr103317-1.c b/gcc/testsuite/gcc.c-torture/compile/pr103317-1.c
new file mode 100644
index 0000000..f9d145e
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr103317-1.c
@@ -0,0 +1,13 @@
+int a, b;
+char c;
+void
+d (void)
+{
+ char e = c;
+ if (b)
+ if (c < 16 - 11)
+ e = 16 - 11;
+ if (e > 8)
+ e = 8;
+ a = e;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr103052.c b/gcc/testsuite/gcc.c-torture/execute/pr103052.c
new file mode 100644
index 0000000..bef8674
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr103052.c
@@ -0,0 +1,35 @@
+static void js_error(void);
+static int top;
+static void js_throw(void)
+{
+ __builtin_exit(0);
+}
+
+// LOCATION A -- if js_pop is here, the bug is present
+static void js_pop(void)
+{
+ if (++top > 100)
+ js_error();
+}
+
+static void jsC_error(const char *v)
+{
+ if (v[0] == 0)
+ js_error();
+ js_throw();
+}
+static void checkfutureword(const char *exp)
+{
+ if (!__builtin_strcmp(exp, "const"))
+ jsC_error("boom");
+}
+static void js_error(void) {
+ checkfutureword("foo");
+ checkfutureword("bar");
+ js_pop();
+}
+int main(void)
+{
+ checkfutureword("const");
+ __builtin_abort ();
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr103255.c b/gcc/testsuite/gcc.c-torture/execute/pr103255.c
new file mode 100644
index 0000000..d74b054
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr103255.c
@@ -0,0 +1,41 @@
+/* PR tree-optimization/103255 */
+
+struct H
+{
+ unsigned a;
+ unsigned b;
+ unsigned c;
+};
+
+#if __SIZEOF_POINTER__ >= 4
+#define ADDR 0x400000
+#else
+#define ADDR 0x4000
+#endif
+#define OFF 0x20
+
+int
+main ()
+{
+ struct H *h = 0;
+ unsigned long o;
+ volatile int t = 1;
+
+ for (o = OFF; o <= OFF; o += 0x1000)
+ {
+ struct H *u;
+ u = (struct H *) (ADDR + o);
+ if (t)
+ {
+ h = u;
+ break;
+ }
+ }
+
+ if (h == 0)
+ return 0;
+ unsigned *tt = &h->b;
+ if ((__SIZE_TYPE__) tt != (ADDR + OFF + __builtin_offsetof (struct H, b)))
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Walways-true-2.c b/gcc/testsuite/gcc.dg/Walways-true-2.c
index 7f0bb7b..ae3262b 100644
--- a/gcc/testsuite/gcc.dg/Walways-true-2.c
+++ b/gcc/testsuite/gcc.dg/Walways-true-2.c
@@ -9,7 +9,7 @@
extern int foo (int) __attribute__ ((weak));
-int i __attribute__ ((weak));
+extern int i __attribute__ ((weak));
void
bar (int a)
diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-10.c b/gcc/testsuite/gcc.dg/Warray-parameter-10.c
new file mode 100644
index 0000000..378f8af
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-parameter-10.c
@@ -0,0 +1,20 @@
+/* PR c/102759 - ICE calling a function taking an argument redeclared
+ without a prototype.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+void f (void)
+{
+ void gia (int[2]);
+ void g ();
+}
+
+/* Redeclaring the g(int[]) above without a prototype loses it. */
+void gia ();
+void g (int[2]);
+
+void h (void )
+{
+ gia (gia);
+ gia (g);
+}
diff --git a/gcc/testsuite/gcc.dg/Warray-parameter-11.c b/gcc/testsuite/gcc.dg/Warray-parameter-11.c
new file mode 100644
index 0000000..8ca1b55
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Warray-parameter-11.c
@@ -0,0 +1,24 @@
+/* PR c/101702 - ICE on invalid function redeclaration
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+typedef __INTPTR_TYPE__ intptr_t;
+
+#define copysign(x, y) __builtin_copysign (x, y)
+
+void f0 (double[!copysign (~2, 3)]);
+
+void f1 (double[!copysign (~2, 3)]);
+void f1 (double[1]); // { dg-warning "-Warray-parameter" }
+
+void f2 (int[(int)+1.0]);
+void f2 (int[(int)+1.1]);
+
+/* Also verify that equivalent expressions don't needlessly cause false
+ positives or negatives. */
+struct S { int a[1]; };
+extern struct S *sp;
+
+void f3 (int[(intptr_t)((char*)sp->a - (char*)sp)]);
+void f3 (int[(intptr_t)((char*)&sp->a[0] - (char*)sp)]);
+void f3 (int[(intptr_t)((char*)&sp->a[1] - (char*)sp)]); // { dg-warning "-Warray-parameter" }
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c
new file mode 100644
index 0000000..ee2693d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-82.c
@@ -0,0 +1,29 @@
+/* Verify that notes after warnings for array and VLA parameters show
+ the array form.
+ { dg-do compile }
+ { dg-options "-Wall" } */
+
+void fia5 (int[5]);
+
+void gia3_fia5 (void)
+{
+ int a[3];
+ fia5 (a); // { dg-warning "-Wstringop-overflow" }
+ // { dg-message "argument 1 of type 'int\\\[5]'" "note" { target *-*-* } .-1 }
+}
+
+
+/* The type of the argument would ideall be 'int[n]' but the variable
+ bound is lost/cleared by free-lang-data and never makes it into
+ the middle end. An (inferior) alternative would be 'int[*]' but
+ the pretty printer doesn't know how to format the star. A better
+ solution might be to introduce a new notation, like 'int[$1]',
+ where the $1 refers to the VLA argument bound. */
+void fvla (int n, int[n]);
+
+void gia3_fvla (void)
+{
+ int a[3];
+ fvla (sizeof a, a); // { dg-warning "-Wstringop-overflow" }
+ // { dg-message "argument 2 of type 'int\\\[]'" "note" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/gcc.dg/Wstringop-overflow-84.c b/gcc/testsuite/gcc.dg/Wstringop-overflow-84.c
new file mode 100644
index 0000000..2c0f507
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wstringop-overflow-84.c
@@ -0,0 +1,15 @@
+/* PR middle-end/102960 - ICE: in sign_mask, at wide-int.h:855 in GCC 10.3.0
+ { dg-do compile }
+ { dg-options "-Og -Wall" } */
+
+void f (int i)
+{
+ const char *s;
+ if (i)
+ s = &"abcd"[i];
+
+ __builtin_printf ("%s", s);
+}
+
+/* The use of s in the call to sprintf should result in:
+ { dg-prune-output "-Wmaybe-uninitialized" } */
diff --git a/gcc/testsuite/gcc.dg/analyzer/capacity-1.c b/gcc/testsuite/gcc.dg/analyzer/capacity-1.c
index 9ea41f7..2d12483 100644
--- a/gcc/testsuite/gcc.dg/analyzer/capacity-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/capacity-1.c
@@ -1,3 +1,5 @@
+/* { dg-require-effective-target alloca } */
+
#include <stdlib.h>
#include "analyzer-decls.h"
@@ -53,7 +55,7 @@ test_malloc (void)
void
test_alloca (size_t sz)
{
- void *p = alloca (sz);
+ void *p = __builtin_alloca (sz);
__analyzer_dump_capacity (p); /* { dg-warning "capacity: 'INIT_VAL\\(sz_\[^\n\r\]*\\)'" } */
}
diff --git a/gcc/testsuite/gcc.dg/analyzer/capacity-3.c b/gcc/testsuite/gcc.dg/analyzer/capacity-3.c
index 41e282c..c099ff5 100644
--- a/gcc/testsuite/gcc.dg/analyzer/capacity-3.c
+++ b/gcc/testsuite/gcc.dg/analyzer/capacity-3.c
@@ -1,10 +1,12 @@
+/* { dg-require-effective-target alloca } */
+
#include <stdlib.h>
#include "analyzer-decls.h"
static void __attribute__((noinline))
__analyzer_callee_1 (size_t inner_sz)
{
- void *p = alloca (inner_sz);
+ void *p = __builtin_alloca (inner_sz);
__analyzer_dump_capacity (p); /* { dg-warning "capacity: 'INIT_VAL\\(outer_sz_\[^\n\r\]*\\)'" } */
}
diff --git a/gcc/testsuite/gcc.dg/analyzer/explode-1.c b/gcc/testsuite/gcc.dg/analyzer/explode-1.c
index f48408e..9b95afd 100644
--- a/gcc/testsuite/gcc.dg/analyzer/explode-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/explode-1.c
@@ -12,7 +12,7 @@ void test (void)
{
void *p0, *p1, *p2, *p3, *p4, *p5, *p6, *p7, *p8;
void **pp;
- while (get ()) /* { dg-warning "leak" } */
+ while (get ())
{
switch (get ())
{
@@ -47,7 +47,7 @@ void test (void)
{
default:
case 0:
- *pp = malloc (16);
+ *pp = malloc (16); /* { dg-warning "leak" } */
break;
case 1:
free (*pp);
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr102695.c b/gcc/testsuite/gcc.dg/analyzer/pr102695.c
new file mode 100644
index 0000000..2ca9882
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr102695.c
@@ -0,0 +1,44 @@
+extern void* malloc (__SIZE_TYPE__);
+
+const char* write_strchr_literal (int x)
+{
+ char *p = __builtin_strchr ("123", x);
+ *p = 0; /* { dg-warning "dereference of NULL 'p'" "null deref" } */
+ /* { dg-warning "write to string literal" "string literal" { target *-*-* } .-1 } */
+ return p;
+}
+
+const char* write_strchr_const_array (int x)
+{
+ static const char a[] = "123";
+ char *p = __builtin_strchr (a, x);
+ *p = 0; /* { dg-warning "dereference of NULL 'p'" "null deref" } */
+ /* { dg-warning "write to 'const' object 'a'" "write to const" { target *-*-* } .-1 } */
+ return a;
+}
+
+char* write_function (void)
+{
+ char *p = (char*)malloc /* forgot arguments */;
+ p[1] = 'a'; /* { dg-warning "write to function 'malloc'" } */
+ __builtin_strcpy (p, "123"); /* { dg-warning "write to function 'malloc'" } */
+ return p;
+}
+
+char* write_label (void)
+{
+ char *p = (char*)&&L;
+ *p = 0; /* { dg-warning "write to label 'L'" } */
+L:
+ return p;
+}
+
+struct A { const int i; };
+
+extern /* not const */ struct A a;
+
+void write_const_member (void)
+{
+ char *p = (char*)&a.i;
+ *p = 0; // missing warning
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr103217.c b/gcc/testsuite/gcc.dg/analyzer/pr103217.c
new file mode 100644
index 0000000..a0ef8bf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/pr103217.c
@@ -0,0 +1,42 @@
+extern char *strdup (const char *__s)
+ __attribute__ ((__nothrow__ , __leaf__, __malloc__, __nonnull__ (1)));
+
+extern void abort (void)
+ __attribute__ ((__nothrow__ , __leaf__, __noreturn__));
+
+extern int getopt (int ___argc, char *const *___argv, const char *__shortopts)
+ __attribute__ ((__nothrow__ , __leaf__, __nonnull__ (2, 3)));
+extern char *optarg;
+
+extern void free (void *__ptr)
+ __attribute__ ((__nothrow__ , __leaf__));
+
+#define NULL ((void *)0)
+
+char *xstrdup(const char *src) {
+ char *val = strdup(src);
+ if (!val)
+ abort();
+ return val;
+}
+
+int main(int argc, char *argv[]) {
+ char *one = NULL, *two = NULL;
+ int rc;
+
+ while ((rc = getopt(argc, argv, "a:b:")) != -1) {
+ switch (rc) {
+ case 'a':
+ free(one);
+ one = xstrdup(optarg);
+ break;
+ case 'b':
+ free(two);
+ two = xstrdup(optarg);
+ break;
+ }
+ }
+ free(one);
+ free(two);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/analyzer/pr94858-1.c b/gcc/testsuite/gcc.dg/analyzer/pr94858-1.c
index f7be1c6..d33c174 100644
--- a/gcc/testsuite/gcc.dg/analyzer/pr94858-1.c
+++ b/gcc/testsuite/gcc.dg/analyzer/pr94858-1.c
@@ -1,3 +1,5 @@
+/* { dg-additional-options "-Wno-analyzer-too-complex" } */
+
#include <stdlib.h>
typedef short hashNx;
diff --git a/gcc/testsuite/gcc.dg/analyzer/strchr-1.c b/gcc/testsuite/gcc.dg/analyzer/strchr-1.c
new file mode 100644
index 0000000..dfe1bc9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/analyzer/strchr-1.c
@@ -0,0 +1,26 @@
+#include <string.h>
+#include "analyzer-decls.h"
+
+const char* test_literal (int x)
+{
+ char *p = __builtin_strchr ("123", x);
+ if (p)
+ {
+ __analyzer_eval (*p == x); /* { dg-message "UNKNOWN" } */
+ /* TODO: this ought to be TRUE, but it's unclear that it's
+ worth stashing this constraint. */
+ }
+ return p;
+}
+
+void test_2 (const char *s, int c)
+{
+ char *p = __builtin_strchr (s, c); /* { dg-message "when '__builtin_strchr' returns NULL"} */
+ *p = 'A'; /* { dg-warning "dereference of NULL 'p'" "null deref" } */
+}
+
+void test_3 (const char *s, int c)
+{
+ char *p = strchr (s, c); /* { dg-message "when 'strchr' returns NULL"} */
+ *p = 'A'; /* { dg-warning "dereference of NULL 'p'" "null deref" } */
+}
diff --git a/gcc/testsuite/gcc.dg/devnull-dump.c b/gcc/testsuite/gcc.dg/devnull-dump.c
new file mode 100644
index 0000000..378e090
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/devnull-dump.c
@@ -0,0 +1,7 @@
+/* { dg-do assemble } */
+/* { dg-options "-fdump-ipa-clones -o /dev/null" } */
+
+int main()
+{
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/lto/semantic-interposition-1_0.c b/gcc/testsuite/gcc.dg/lto/semantic-interposition-1_0.c
new file mode 100644
index 0000000..db84274
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/semantic-interposition-1_0.c
@@ -0,0 +1,13 @@
+/* { dg-lto-do link } */
+/* { dg-require-effective-target shared } */
+/* { dg-extra-ld-options { -shared } } */
+/* { dg-lto-options {{-O2 -flto -fpic -fdump-ipa-inline-details --shared}} } */
+extern int ret1();
+
+int
+test()
+{
+ return ret1();
+}
+/* { dg-final { scan-wpa-ipa-dump "Inlined 1 calls" "inline" } } */
+
diff --git a/gcc/testsuite/gcc.dg/lto/semantic-interposition-1_1.c b/gcc/testsuite/gcc.dg/lto/semantic-interposition-1_1.c
new file mode 100644
index 0000000..9a74177
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/lto/semantic-interposition-1_1.c
@@ -0,0 +1,5 @@
+/* { dg-options "-O2 -flto -fpic -fno-semantic-interposition" } */
+int ret1()
+{
+ return 1;
+}
diff --git a/gcc/testsuite/gcc.dg/pr103248.c b/gcc/testsuite/gcc.dg/pr103248.c
new file mode 100644
index 0000000..da6232d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr103248.c
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target fixed_point } */
+/* { dg-options "-fnon-call-exceptions" } */
+
+_Accum sa;
+int c;
+
+void div_csa() { c /= sa; }
diff --git a/gcc/testsuite/gcc.dg/pr103254.c b/gcc/testsuite/gcc.dg/pr103254.c
new file mode 100644
index 0000000..62d2415
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr103254.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O3" } */
+/* { dg-timeout 10 } */
+
+short int i;
+
+void
+foo (void)
+{
+ for (i = 1; i < 2; i += 4)
+ {
+ int j;
+
+ for (j = 0; j < 5; j += 4)
+ {
+ int k;
+
+ for (k = 0; k < 68; k += 4)
+ {
+ i &= j;
+ j &= i;
+ }
+ }
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/pr103277.c b/gcc/testsuite/gcc.dg/pr103277.c
new file mode 100644
index 0000000..5c206f9
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr103277.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fbranch-probabilities -fno-ipa-pure-const" } */
+
+__attribute__ ((returns_twice)) void
+bar (void)
+{
+}
+
+void
+foo (int cond)
+{
+ if (cond)
+ bar ();
+} /* { dg-message "profile count data" } */
diff --git a/gcc/testsuite/gcc.dg/pr25530.c b/gcc/testsuite/gcc.dg/pr25530.c
index b846ab3..771b36b9 100644
--- a/gcc/testsuite/gcc.dg/pr25530.c
+++ b/gcc/testsuite/gcc.dg/pr25530.c
@@ -8,4 +8,4 @@ f (unsigned t)
return (t / 2) * 2;
}
-/* { dg-final { scan-tree-dump "\& -2" "optimized" } } */
+/* { dg-final { scan-tree-dump "\& -2|4294967294" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/signbit-2.c b/gcc/testsuite/gcc.dg/signbit-2.c
index d8501e9..b609f67 100644
--- a/gcc/testsuite/gcc.dg/signbit-2.c
+++ b/gcc/testsuite/gcc.dg/signbit-2.c
@@ -19,5 +19,6 @@ void fun2(int32_t *x, int n)
x[i] = (-x[i]) >> 30;
}
-/* { dg-final { scan-tree-dump {\s+>\s+\{ 0, 0, 0(, 0)+ \}} optimized } } */
+/* { dg-final { scan-tree-dump {\s+>\s+\{ 0(, 0)+ \}} optimized { target vect_int } } } */
+/* { dg-final { scan-tree-dump {\s+>\s+0} optimized { target { ! vect_int } } } } */
/* { dg-final { scan-tree-dump-not {\s+>>\s+31} optimized } } */
diff --git a/gcc/testsuite/gcc.dg/torture/20211118-1.c b/gcc/testsuite/gcc.dg/torture/20211118-1.c
new file mode 100644
index 0000000..67ef684
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/20211118-1.c
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+
+unsigned p[3];
+void __attribute__((noipa))
+bar (float *q, int n, int m)
+{
+ for (int i = 0; i < m; ++i)
+ {
+ if (i == n)
+ {
+ unsigned a = p[1];
+ p[1] = a + 1;
+ *q = 1.;
+ }
+ q++;
+ }
+}
+
+int main()
+{
+#if __SIZEOF_FLOAT__ == __SIZEOF_INT__
+ bar ((float *)p, 1, 3);
+ if (((float *)p)[1] != 1.)
+ __builtin_abort ();
+#endif
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c
index 1070230..707d539 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-3.c
@@ -4,7 +4,6 @@
/* { dg-require-effective-target int128 } */
/* { dg-require-effective-target fenv } */
/* { dg-options "-frounding-math" } */
-/* { dg-xfail-run-if "see PR80556 c63" { x86_64-*-darwin* i68?-*-darwin* } { "*" } { "" } } */
#include <fenv.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c
index 3facf32..09600f9 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert-timode-4.c
@@ -4,7 +4,6 @@
/* { dg-require-effective-target int128 } */
/* { dg-require-effective-target fenv } */
/* { dg-options "-frounding-math" } */
-/* { dg-xfail-run-if "see PR80556 c63" { x86_64-*-darwin* i68?-*-darwin* } { "*" } { "" } } */
#include <fenv.h>
#include <stdlib.h>
diff --git a/gcc/testsuite/gcc.dg/tree-prof/merge_block.c b/gcc/testsuite/gcc.dg/tree-prof/merge_block.c
index 5da5ddf..e8a8873 100644
--- a/gcc/testsuite/gcc.dg/tree-prof/merge_block.c
+++ b/gcc/testsuite/gcc.dg/tree-prof/merge_block.c
@@ -1,5 +1,5 @@
-/* { dg-options "-O2 -fno-ipa-pure-const -fdump-tree-optimized-blocks-details -fno-early-inlining" } */
+/* { dg-options "-O2 -fno-ipa-pure-const -fdump-tree-optimized-blocks-details -fno-early-inlining -fno-ipa-modref" } */
int a[8];
int t()
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c
index 707e630..a55231b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/if-to-switch-3.c
@@ -1,5 +1,6 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized" } */
+/* Supplying case-values-threshold makes the testcase less target dependent. */
+/* { dg-options "-O2 -fdump-tree-iftoswitch-optimized --param case-values-threshold=4" } */
int IsMySuperRandomChar(int aChar)
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-15.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-15.c
new file mode 100644
index 0000000..06881f2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-15.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-modref1" } */
+int test (int *a)
+{
+ int i;
+ for (i=0; a[i];i++);
+ return i+a[i];
+}
+/* { dg-final { scan-tree-dump "access: Parm 0" "modref1"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-4.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-4.c
new file mode 100644
index 0000000..81aa7dc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-4.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-dse2-details" } */
+struct a {int a,b,c;};
+__attribute__ ((noinline))
+void
+kill_me (struct a *a)
+{
+ a->a=0;
+ a->b=0;
+ a->c=0;
+}
+__attribute__ ((noinline))
+void
+my_pleasure (struct a *a)
+{
+ a->a=1;
+ a->c=2;
+}
+void
+set (struct a *a)
+{
+ kill_me (a);
+ my_pleasure (a);
+ a->b=1;
+}
+/* { dg-final { scan-tree-dump "Deleted dead store: kill_me" "dse2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-6.c b/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-6.c
new file mode 100644
index 0000000..d1e45a8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/modref-dse-6.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+int
+main()
+{
+ int a,b;
+ __attribute__ ((noinline))
+ void kill_me()
+ {
+ a=1234;
+ b=2234;
+ }
+ a=0;
+ b=1234;
+ __attribute__ ((noinline))
+ int reta()
+ {
+ return a;
+ }
+ return reta();
+}
+/* { dg-final { scan-tree-dump-not "kill_me" "optimized" } } */
+/* { dg-final { scan-tree-dump-not "1234" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr103218-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr103218-1.c
new file mode 100644
index 0000000..f086f07
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr103218-1.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+/* PR tree-optimization/103218 */
+
+/* These first two are removed during forwprop1 */
+signed char f(signed char a)
+{
+ signed char t = a < 0;
+ int tt = (unsigned char)(t << 7);
+ return tt;
+}
+signed char f0(signed char a)
+{
+ unsigned char t = a < 0;
+ int tt = (unsigned char)(t << 7);
+ return tt;
+}
+
+/* This one is removed during phiopt. */
+signed char f1(signed char a)
+{
+ if (a < 0)
+ return 1u<<7;
+ return 0;
+}
+
+/* These three examples should remove "a < 0" by optimized. */
+/* { dg-final { scan-tree-dump-times "< 0" 0 "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr103220-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr103220-1.c
new file mode 100644
index 0000000..f2ef3f1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr103220-1.c
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+unsigned char f(unsigned char a)
+{
+ signed char d = (signed char) a;
+ signed char e = d & ~1;
+ unsigned char t = e;
+ t &= ~2;
+ return t;
+}
+/* The above should reduce down to just & 252 rather than keping
+ the two &s there. */
+/* { dg-final { scan-tree-dump-times "& 252" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "& -2" 0 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "& 253" 0 "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr103220-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr103220-2.c
new file mode 100644
index 0000000..25d7412
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr103220-2.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+signed char f(unsigned char a)
+{
+ unsigned char b = a & 127;
+ signed char c = (signed char) b;
+ signed char d = (signed char) a;
+ signed char e = d & -128;
+ signed char h = c | e;
+ return h;
+}
+/* The above should reduce down to just return with a cast.
+ removing the two &s there and |'s. */
+/* { dg-final { scan-tree-dump-times "& 127" 0 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "& -128" 0 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "\\\| " 0 "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr103228-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr103228-1.c
new file mode 100644
index 0000000..a753981
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr103228-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+int f(int a, int b)
+{
+ b|=1u;
+ b|=2;
+ return b;
+}
+/* { dg-final { scan-tree-dump-times "\\\| 3" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "\\\| 1" 0 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "\\\| 2" 0 "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr103257-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr103257-1.c
new file mode 100644
index 0000000..89f4f44
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr103257-1.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+void link_error(void);
+unsigned b, c;
+static short a(short e, short f) { return e * f; }
+int main() {
+ if (a(1 ^ ((0, 0) ^ 1 && b) <= b, c))
+ link_error ();
+ c = 0;
+}
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr55177-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr55177-1.c
new file mode 100644
index 0000000..de1a264
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr55177-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+extern int x;
+
+void foo(void)
+{
+ int a = __builtin_bswap32(x);
+ a &= 0x5a5b5c5d;
+ x = __builtin_bswap32(a);
+}
+
+/* { dg-final { scan-tree-dump-times "__builtin_bswap32" 0 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "& 1566333786" 1 "optimized"} } */
+/* { dg-final { scan-tree-dump-times "& 1515936861" 0 "optimized"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-18.c
new file mode 100644
index 0000000..da19806
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-18.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fstrict-aliasing -fdump-tree-lim2-details" } */
+
+unsigned p;
+
+void foo (float *q)
+{
+ for (int i = 0; i < 256; ++i)
+ {
+ if (p)
+ {
+ unsigned a = p;
+ *(q++) = 1.;
+ p = a + 1;
+ }
+ }
+}
+
+/* { dg-final { scan-tree-dump-times "Executing store motion" 1 "lim2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp116.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp116.c
index d9d7b23..9e68a77 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp116.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp116.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
int
f (int m1, int m2, int c)
@@ -9,4 +9,4 @@ f (int m1, int m2, int c)
return e ? m1 : m2;
}
-/* { dg-final { scan-tree-dump-times "\\? c_\[0-9\]\\(D\\) : 0" 1 "vrp1" } } */
+/* { dg-final { scan-tree-dump-times "\\? c_\[0-9\]\\(D\\) : 0" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-double.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-double.c
index 462063a..b77c847 100644
--- a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-double.c
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-double.c
@@ -1,10 +1,11 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_complex_add_double } */
/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-additional-options "-fdump-tree-vect-details" } */
#define TYPE double
#define N 16
#include "complex-mla-template.c"
-/* { dg-final { scan-tree-dump "Found COMPLEX_FMA_CONJ" "slp1" } } */
-/* { dg-final { scan-tree-dump "Found COMPLEX_FMA" "slp1" } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_FMA_CONJ" "vect" } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_FMA" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-float.c
index a88adc8..cd68fd1 100644
--- a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-float.c
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mla-float.c
@@ -1,10 +1,10 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_complex_add_float } */
-/* { dg-additional-options "-fno-tree-loop-vectorize" } */
+/* { dg-additional-options "-fdump-tree-vect-details" } */
/* { dg-add-options arm_v8_3a_fp16_complex_neon } */
#define TYPE float
#define N 16
#include "complex-mla-template.c"
-/* { dg-final { scan-tree-dump "Found COMPLEX_FMA_CONJ" "slp1" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump "Found COMPLEX_FMA" "slp1" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_FMA_CONJ" "vect" } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_FMA" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-double.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-double.c
index a434fd1..9d98394 100644
--- a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-double.c
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-double.c
@@ -1,12 +1,11 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_complex_add_double } */
/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-additional-options "-fdump-tree-vect-details" } */
#define TYPE double
#define N 16
#include "complex-mls-template.c"
-/* { dg-final { scan-tree-dump "Found COMPLEX_ADD_ROT270" "slp1" } } */
-/* { dg-final { scan-tree-dump "Found COMPLEX_FMA" "slp1" } } */
-/* { dg-final { scan-tree-dump "Found COMPLEX_FMS_CONJ" "slp1" } } */
-/* { dg-final { scan-tree-dump "Found COMPLEX_FMS" "slp1" } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_FMS_CONJ" "vect" } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_FMS" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-float.c
index b7ccbbd..cf540a0 100644
--- a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-float.c
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mls-float.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_complex_add_float } */
-/* { dg-additional-options "-fno-tree-loop-vectorize" } */
+/* { dg-additional-options "-fdump-tree-vect-details" } */
/* { dg-add-options arm_v8_3a_complex_neon } */
#define TYPE float
#define N 16
#include "complex-mls-template.c"
-/* { dg-final { scan-tree-dump "Found COMPLEX_FMS_CONJ" "slp1" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump "Found COMPLEX_FMS" "slp1" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_FMS_CONJ" "vect" } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_FMS" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-double.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-double.c
index f7e9386..dcac519 100644
--- a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-double.c
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-double.c
@@ -1,10 +1,11 @@
/* { dg-do compile } */
/* { dg-require-effective-target vect_complex_add_double } */
/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-additional-options "-fdump-tree-vect-details" } */
#define TYPE double
#define N 16
#include "complex-mul-template.c"
-/* { dg-final { scan-tree-dump "Found COMPLEX_MUL_CONJ" "slp1" } } */
-/* { dg-final { scan-tree-dump "Found COMPLEX_MUL" slp1" } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_MUL_CONJ" "vect" } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_MUL" "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-float.c b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-float.c
index 0dc9c52..27280ae 100644
--- a/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-float.c
+++ b/gcc/testsuite/gcc.dg/vect/complex/fast-math-bb-slp-complex-mul-float.c
@@ -7,5 +7,5 @@
#define N 16
#include "complex-mul-template.c"
-/* { dg-final { scan-tree-dump "Found COMPLEX_MUL_CONJ" "slp1" { xfail *-*-* } } } */
-/* { dg-final { scan-tree-dump "Found COMPLEX_MUL" "slp1" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_MUL_CONJ" "slp1" } } */
+/* { dg-final { scan-tree-dump "Found COMPLEX_MUL" "slp1" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr103253.c b/gcc/testsuite/gcc.dg/vect/pr103253.c
new file mode 100644
index 0000000..abe3f09
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr103253.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target fopenmp } */
+/* { dg-additional-options "-O2 -fexceptions -fopenmp -fno-delete-dead-exceptions -fno-trapping-math" } */
+
+double
+do_work (double do_work_pri)
+{
+ int i;
+
+#pragma omp simd
+ for (i = 0; i < 17; ++i)
+ do_work_pri = (!i ? 0.5 : i) * 2.0;
+
+ return do_work_pri;
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-stexp-3.c b/gcc/testsuite/gcc.dg/vla-stexp-3.c
new file mode 100644
index 0000000..e663de1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-stexp-3.c
@@ -0,0 +1,11 @@
+/* PR91038 */
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+
+void bar(void)
+{
+ ({ int N = 2; int (*x)[9][N] = 0; x; })[1];
+ ({ int N = 2; int (*x)[9][N] = 0; x; })[0]; // should not ice
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-stexp-4.c b/gcc/testsuite/gcc.dg/vla-stexp-4.c
new file mode 100644
index 0000000..612b5a8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-stexp-4.c
@@ -0,0 +1,94 @@
+/* PR29970, PR91038 */
+/* { dg-do run } */
+/* { dg-options "-O0 -Wunused-variable" } */
+
+int foo3b(void) // should not return 0
+{
+ int n = 0;
+ return sizeof *({ n = 10; int x[n]; &x; });
+}
+
+int foo4(void) // should not ICE
+{
+ return (*({
+ int n = 20;
+ char (*x)[n][n] = __builtin_malloc(n * n);
+ (*x)[12][1] = 1;
+ x;
+ }))[12][1];
+}
+
+int foo5(void) // should return 1, returns 0
+{
+ int n = 0;
+ return (*({
+ n = 20;
+ char (*x)[n][n] = __builtin_malloc(n * n);
+ (*x)[12][1] = 1;
+ (*x)[0][1] = 0;
+ x;
+ }))[12][1];
+}
+
+int foo5c(void) // should return 400
+{
+ int n = 0;
+ return sizeof(*({
+ n = 20;
+ char (*x)[n][n] = __builtin_malloc(n * n);
+ (*x)[12][1] = 1;
+ (*x)[0][1] = 0;
+ x;
+ }));
+}
+
+int foo5b(void) // should return 1, returns 0
+{
+ int n = 0; /* { dg-warning "unused variable" } */
+ return (*({
+ int n = 20;
+ char (*x)[n][n] = __builtin_malloc(n * n);
+ (*x)[12][1] = 1;
+ (*x)[0][1] = 0;
+ x;
+ }))[12][1];
+}
+
+int foo5a(void) // should return 1, returns 0
+{
+ return (*({
+ int n = 20;
+ char (*x)[n][n] = __builtin_malloc(n * n);
+ (*x)[12][1] = 1;
+ (*x)[0][1] = 0;
+ x;
+ }))[12][1];
+}
+
+
+
+
+int main()
+{
+ if (sizeof(int[10]) != foo3b())
+ __builtin_abort();
+
+ if (1 != foo4())
+ __builtin_abort();
+
+ if (400 != foo5c())
+ __builtin_abort();
+
+ if (1 != foo5a())
+ __builtin_abort();
+
+ if (1 != foo5b()) // -O0
+ __builtin_abort();
+
+ if (1 != foo5())
+ __builtin_abort();
+
+ return 0;
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-stexp-5.c b/gcc/testsuite/gcc.dg/vla-stexp-5.c
new file mode 100644
index 0000000..d6a7f2b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-stexp-5.c
@@ -0,0 +1,30 @@
+/* PR29970 */
+/* { dg-do run } */
+/* { dg-options "-Wunused-variable" } */
+
+
+
+
+int foo2a(void) // should not ICE
+{
+ return ({ int n = 20; struct { int x[n];} x; x.x[12] = 1; sizeof(x); });
+}
+
+
+int foo2b(void) // should not ICE
+{
+ return sizeof *({ int n = 20; struct { int x[n];} x; x.x[12] = 1; &x; });
+}
+
+int main()
+{
+ if (sizeof(struct { int x[20]; }) != foo2a())
+ __builtin_abort();
+
+ if (sizeof(struct { int x[20]; }) != foo2b())
+ __builtin_abort();
+
+ return 0;
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-stexp-6.c b/gcc/testsuite/gcc.dg/vla-stexp-6.c
new file mode 100644
index 0000000..3d96d38
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-stexp-6.c
@@ -0,0 +1,94 @@
+/* PR29970, PR91038 */
+/* { dg-do run } */
+/* { dg-options "-O2 -Wunused-variable" } */
+
+int foo3b(void) // should not return 0
+{
+ int n = 0;
+ return sizeof *({ n = 10; int x[n]; &x; });
+}
+
+int foo4(void) // should not ICE
+{
+ return (*({
+ int n = 20;
+ char (*x)[n][n] = __builtin_malloc(n * n);
+ (*x)[12][1] = 1;
+ x;
+ }))[12][1];
+}
+
+int foo5(void) // should return 1, returns 0
+{
+ int n = 0;
+ return (*({
+ n = 20;
+ char (*x)[n][n] = __builtin_malloc(n * n);
+ (*x)[12][1] = 1;
+ (*x)[0][1] = 0;
+ x;
+ }))[12][1];
+}
+
+int foo5c(void) // should return 400
+{
+ int n = 0;
+ return sizeof(*({
+ n = 20;
+ char (*x)[n][n] = __builtin_malloc(n * n);
+ (*x)[12][1] = 1;
+ (*x)[0][1] = 0;
+ x;
+ }));
+}
+
+int foo5b(void) // should return 1, returns 0
+{
+ int n = 0; /* { dg-warning "unused variable" } */
+ return (*({
+ int n = 20;
+ char (*x)[n][n] = __builtin_malloc(n * n);
+ (*x)[12][1] = 1;
+ (*x)[0][1] = 0;
+ x;
+ }))[12][1];
+}
+
+int foo5a(void) // should return 1, returns 0
+{
+ return (*({
+ int n = 20;
+ char (*x)[n][n] = __builtin_malloc(n * n);
+ (*x)[12][1] = 1;
+ (*x)[0][1] = 0;
+ x;
+ }))[12][1];
+}
+
+
+
+
+int main()
+{
+ if (sizeof(int[10]) != foo3b())
+ __builtin_abort();
+
+ if (1 != foo4())
+ __builtin_abort();
+
+ if (400 != foo5c())
+ __builtin_abort();
+
+ if (1 != foo5a())
+ __builtin_abort();
+
+ if (1 != foo5b()) // -O0
+ __builtin_abort();
+
+ if (1 != foo5())
+ __builtin_abort();
+
+ return 0;
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-stexp-7.c b/gcc/testsuite/gcc.dg/vla-stexp-7.c
new file mode 100644
index 0000000..3091b91
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-stexp-7.c
@@ -0,0 +1,44 @@
+/* PR91038 */
+/* { dg-do run } */
+/* { dg-options "-O2 -Wunused-variable" } */
+
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+
+struct lbm {
+
+ int D;
+ const int* DQ;
+
+} D2Q9 = { 2,
+ (const int*)&(const int[9][2]){
+ { 0, 0 },
+ { 1, 0 }, { 0, 1 }, { -1, 0 }, { 0, -1 },
+ { 1, 1 }, { -1, 1 }, { -1, -1 }, { 1, -1 },
+ }
+};
+
+void zouhe_left(void)
+{
+ __auto_type xx = (*({ int N = 2; struct lbm __x = D2Q9; ((const int(*)[9][N])__x.DQ); }));
+
+ if (1 != xx[1][0])
+ __builtin_abort();
+
+ if (2 != ARRAY_SIZE(xx[1]))
+ __builtin_abort();
+
+ if (1 != (*({ int N = 2; struct lbm __x = D2Q9; ((const int(*)[9][N])__x.DQ); }))[1][0])
+ __builtin_abort();
+
+ if (2 != ARRAY_SIZE(*({ int N = 2; struct lbm __x = D2Q9; ((const int(*)[9][N])__x.DQ); })[1]))
+ __builtin_abort();
+}
+
+int main()
+{
+ zouhe_left();
+ return 0;
+}
+
+
diff --git a/gcc/testsuite/gcc.dg/vla-stexp-8.c b/gcc/testsuite/gcc.dg/vla-stexp-8.c
new file mode 100644
index 0000000..5b475eb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-stexp-8.c
@@ -0,0 +1,47 @@
+/* PR29970, PR91038 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -Wunused-variable" } */
+
+
+int foo0(void)
+{
+ int c = *(*(*({ int n = 10; int (*x)[n][n] = __builtin_malloc(sizeof *x); x; }) + 5) + 5);
+ return c;
+}
+
+int foo1(void)
+{
+ int c = *(5 + *(5 + *({ int n = 10; int (*x)[n][n] = __builtin_malloc(sizeof *x); x; })));
+ return c;
+}
+
+int bar2(void)
+{
+ int c = (*({ int n = 10; struct { int y[n]; int z; }* x = __builtin_malloc(sizeof *x); x; })).z;
+ return c;
+}
+
+int bar3(void)
+{
+ int n = 2; /* { dg-warning "unused variable" } */
+ int c = (*({ int n = 3; /* { dg-warning "unused variable" } */
+ ({ int n = 10; int (*x)[n][n] = __builtin_malloc(sizeof *x); x; }); }))[5][5];
+ return c;
+}
+
+int bar3b(void)
+{
+ int n = 2; /* { dg-warning "unused variable" } */
+ int c = (*({ int n = 3; /* { dg-warning "unused variable" } */
+ ({ int n = 10; int (*x)[n][n] = __builtin_malloc(sizeof *x); x; }); }))[0][0];
+ return c;
+}
+
+int bar4(void)
+{
+ int n = 2; /* { dg-warning "unused variable" } */
+ int c = *(5 + *( 5 + *({ int n = 3; /* { dg-warning "unused variable" } */
+ ({ int n = 10; int (*x)[n][n] = __builtin_malloc(sizeof *x); x; }); })));
+ return c;
+}
+
diff --git a/gcc/testsuite/gcc.dg/vla-stexp-9.c b/gcc/testsuite/gcc.dg/vla-stexp-9.c
new file mode 100644
index 0000000..3593a79
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vla-stexp-9.c
@@ -0,0 +1,53 @@
+/* PR91038 */
+/* { dg-do run } */
+/* { dg-options "-O2 -Wunused-variable" } */
+
+
+
+void foo(void)
+{
+ if (2 * sizeof(int) != sizeof((*({ int N = 2; int (*x)[9][N] = 0; x; })[1])))
+ __builtin_abort();
+}
+
+void bar(void)
+{
+ if (2 * sizeof(int) != sizeof((*({ int N = 2; int (*x)[9][N] = 0; x; })[0])))
+ __builtin_abort();
+}
+
+void bar0(void)
+{
+ if (2 * 9 * sizeof(int) != sizeof((*({ int N = 2; int (*x)[9][N] = 0; x; }))))
+ __builtin_abort();
+}
+
+void bar11(void)
+{
+ sizeof(*((*({ int N = 2; int (*x)[9][N] = 0; x; }) + 0)));
+}
+
+void bar12(void)
+{
+ if (2 * sizeof(int) != sizeof(*((*({ int N = 2; int (*x)[9][N] = 0; x; }) ))))
+ __builtin_abort();
+}
+
+void bar1(void)
+{
+ if (2 * sizeof(int) != sizeof(*((*({ int N = 2; int (*x)[9][N] = 0; x; }) + 0))))
+ __builtin_abort();
+}
+
+
+
+
+int main()
+{
+ foo();
+ bar0();
+ bar12();
+ bar1();
+ bar();
+}
+
diff --git a/gcc/testsuite/gcc.dg/weak/weak-3.c b/gcc/testsuite/gcc.dg/weak/weak-3.c
index a719848..5fdf029 100644
--- a/gcc/testsuite/gcc.dg/weak/weak-3.c
+++ b/gcc/testsuite/gcc.dg/weak/weak-3.c
@@ -55,7 +55,7 @@ void * foo1e (void)
extern void * ffoo1f (void);
void * foo1f (void)
{
- if (ffoo1f) /* { dg-warning "" } */
+ if (ffoo1f) /* { dg-warning "-Waddress" } */
ffoo1f ();
return 0;
}
@@ -68,7 +68,9 @@ void * ffoox1g (void) { return (void *)0; }
extern void * ffoo1g (void) __attribute__((weak, alias ("ffoox1g")));
void * foo1g (void)
{
- if (ffoo1g)
+ /* ffoo1g is a weak alias for a symbol defined in this file, expect
+ a -Waddress for the test (which is folded to true). */
+ if (ffoo1g) // { dg-warning "-Waddress" }
ffoo1g ();
return 0;
}
diff --git a/gcc/testsuite/gcc.target/aarch64/pr103311.c b/gcc/testsuite/gcc.target/aarch64/pr103311.c
new file mode 100644
index 0000000..7bcc7db
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/pr103311.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target arm_v8_3a_complex_neon_ok } */
+/* { dg-add-options arm_v8_3a_complex_neon } */
+/* { dg-additional-options "-std=c99" } */
+
+_Complex double y;
+
+void
+cbknu (_Complex double f)
+{
+ const _Complex double cone = 1.0e0;
+
+ f = f * cone;
+ y = f * cone;
+}
+
diff --git a/gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c b/gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c
index 3a1cfce..dc9e9be 100644
--- a/gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c
+++ b/gcc/testsuite/gcc.target/aarch64/shrn-combine-10.c
@@ -6,7 +6,7 @@
uint32x4_t foo (uint64x2_t a, uint64x2_t b)
{
- return vrshrn_high_n_u64 (vrshrn_n_u64 (a, 32), b, 32);
+ return vshrn_high_n_u64 (vshrn_n_u64 (a, 32), b, 32);
}
/* { dg-final { scan-assembler-times {\tuzp2\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_5.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_5.c
new file mode 100644
index 0000000..4bae7e0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_5.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_1.c"
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #0\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #2\.0} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */
+
+/* { dg-final { scan-assembler-not {\tmov\tz} } } */
+/* { dg-final { scan-assembler-not {\tmovprfx\t} } } */
+/* { dg-final { scan-assembler-not {\tsel\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_5_run.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_5_run.c
new file mode 100644
index 0000000..1aa2eb4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_5_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_1_run.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_6.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_6.c
new file mode 100644
index 0000000..912db00
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_6.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_2.c"
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #0\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #2\.0} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d\n} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tmov\tz} } } */
+/* { dg-final { scan-assembler-not {\tsel\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_6_run.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_6_run.c
new file mode 100644
index 0000000..19f6edd
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_6_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_2_run.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_7.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_7.c
new file mode 100644
index 0000000..30f07f6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_7.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_3.c"
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #0\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #2\.0} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.h, p[0-7], z[0-9]+\.h, z[0-9]+\.h\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.h, p[0-7], z[0-9]+\.h, z[0-9]+\.h\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.h, p[0-7], z[0-9]+\.h, z[0-9]+\.h\n} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tmovprfx\t} } } */
+/* { dg-final { scan-assembler-not {\tmov\tz} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_7_run.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_7_run.c
new file mode 100644
index 0000000..3e647ed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_7_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_3_run.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_8.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_8.c
new file mode 100644
index 0000000..a590d38
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_8.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_4.c"
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #0\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #2\.0} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmaxnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/z, z[0-9]+\.s\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.d, p[0-7]/z, z[0-9]+\.d\n} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tmov\tz} } } */
+/* { dg-final { scan-assembler-not {\tsel\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_8_run.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_8_run.c
new file mode 100644
index 0000000..d421e54
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fmaxnm_8_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fmaxnm_4_run.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_5.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_5.c
new file mode 100644
index 0000000..290c4be
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_5.c
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_1.c"
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #0\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #2\.0} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */
+
+/* { dg-final { scan-assembler-not {\tmov\tz} } } */
+/* { dg-final { scan-assembler-not {\tmovprfx\t} } } */
+/* { dg-final { scan-assembler-not {\tsel\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_5_run.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_5_run.c
new file mode 100644
index 0000000..76baf6a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_5_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_1_run.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_6.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_6.c
new file mode 100644
index 0000000..cc9db99
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_6.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_2.c"
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #0\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #2\.0} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d\n} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tmov\tz} } } */
+/* { dg-final { scan-assembler-not {\tsel\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_6_run.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_6_run.c
new file mode 100644
index 0000000..dbafea1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_6_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_2_run.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_7.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_7.c
new file mode 100644
index 0000000..347a1a3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_7.c
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_3.c"
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #0\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #2\.0} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.h, p[0-7], z[0-9]+\.h, z[0-9]+\.h\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.h, p[0-7], z[0-9]+\.h, z[0-9]+\.h\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tsel\tz[0-9]+\.h, p[0-7], z[0-9]+\.h, z[0-9]+\.h\n} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tmovprfx\t} } } */
+/* { dg-final { scan-assembler-not {\tmov\tz} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_7_run.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_7_run.c
new file mode 100644
index 0000000..6617095
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_7_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_3_run.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_8.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_8.c
new file mode 100644
index 0000000..20d6cb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_8.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#define FN(X) __builtin_fmin##X
+#include "cond_fmaxnm_4.c"
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #0\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #0\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, #1\.0\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, #1\.0\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.h, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.s, #2\.0} 1 } } */
+/* { dg-final { scan-assembler-times {\tfmov\tz[0-9]+\.d, #2\.0} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.h, p[0-7]/m, z[0-9]+\.h, z[0-9]+\.h\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.s, p[0-7]/m, z[0-9]+\.s, z[0-9]+\.s\n} 1 } } */
+/* { dg-final { scan-assembler-times {\tfminnm\tz[0-9]+\.d, p[0-7]/m, z[0-9]+\.d, z[0-9]+\.d\n} 1 } } */
+
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.s, p[0-7]/z, z[0-9]+\.s\n} 3 } } */
+/* { dg-final { scan-assembler-times {\tmovprfx\tz[0-9]+\.d, p[0-7]/z, z[0-9]+\.d\n} 3 } } */
+
+/* { dg-final { scan-assembler-not {\tmov\tz} } } */
+/* { dg-final { scan-assembler-not {\tsel\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_8_run.c b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_8_run.c
new file mode 100644
index 0000000..4fb6497
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/sve/cond_fminnm_8_run.c
@@ -0,0 +1,4 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2 -ftree-vectorize" } */
+
+#include "cond_fminnm_4_run.c"
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c
index ca2f140..e228393 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcph-1a.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -O2" } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
#include <immintrin.h>
@@ -22,4 +22,11 @@ avx512f_test (void)
res = _mm512_fcmul_round_pch (x1, x2, 8);
res1 = _mm512_mask_fcmul_round_pch (res1, m16, x1, x2, 8);
res2 = _mm512_maskz_fcmul_round_pch (m16, x1, x2, 11);
+
+ res = _mm512_cmul_pch (x1, x2);
+ res1 = _mm512_mask_cmul_pch (res1, m16, x1, x2);
+ res2 = _mm512_maskz_cmul_pch (m16, x1, x2);
+ res = _mm512_cmul_round_pch (x1, x2, 8);
+ res1 = _mm512_mask_cmul_round_pch (res1, m16, x1, x2, 8);
+ res2 = _mm512_maskz_cmul_round_pch (m16, x1, x2, 11);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c
index 872d91a..92f58c5 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfcmulcsh-1a.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -O2" } */
-/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
#include <immintrin.h>
@@ -22,4 +22,11 @@ avx512f_test (void)
res = _mm_fcmul_round_sch (x1, x2, 8);
res1 = _mm_mask_fcmul_round_sch (res1, m8, x1, x2, 8);
res2 = _mm_maskz_fcmul_round_sch (m8, x1, x2, 11);
+
+ res = _mm_cmul_sch (x1, x2);
+ res1 = _mm_mask_cmul_sch (res1, m8, x1, x2);
+ res2 = _mm_maskz_cmul_sch (m8, x1, x2);
+ res = _mm_cmul_round_sch (x1, x2, 8);
+ res1 = _mm_mask_cmul_round_sch (res1, m8, x1, x2, 8);
+ res2 = _mm_maskz_cmul_round_sch (m8, x1, x2, 11);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c
index f31cbca..4135cd2 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcph-1a.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -O2" } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rn-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\{rz-sae\}\[^\{\n\]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\[^\n\r]*%zmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
#include <immintrin.h>
@@ -22,4 +22,11 @@ avx512f_test (void)
res = _mm512_fmul_round_pch (x1, x2, 8);
res1 = _mm512_mask_fmul_round_pch (res1, m16, x1, x2, 8);
res2 = _mm512_maskz_fmul_round_pch (m16, x1, x2, 11);
+
+ res = _mm512_mul_pch (x1, x2);
+ res1 = _mm512_mask_mul_pch (res1, m16, x1, x2);
+ res2 = _mm512_maskz_mul_pch (m16, x1, x2);
+ res = _mm512_mul_round_pch (x1, x2, 8);
+ res1 = _mm512_mask_mul_round_pch (res1, m16, x1, x2, 8);
+ res2 = _mm512_maskz_mul_round_pch (m16, x1, x2, 11);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c
index 5d48874..cdca385 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16-vfmulcsh-1a.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512fp16 -O2" } */
-/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\{\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rn-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcsh\[ \\t\]+\{rz-sae\}\[^\{\n\]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
#include <immintrin.h>
@@ -22,4 +22,11 @@ avx512f_test (void)
res = _mm_fmul_round_sch (x1, x2, 8);
res1 = _mm_mask_fmul_round_sch (res1, m8, x1, x2, 8);
res2 = _mm_maskz_fmul_round_sch (m8, x1, x2, 11);
+
+ res = _mm_mul_sch (x1, x2);
+ res1 = _mm_mask_mul_sch (res1, m8, x1, x2);
+ res2 = _mm_maskz_mul_sch (m8, x1, x2);
+ res = _mm_mul_round_sch (x1, x2, 8);
+ res1 = _mm_mask_mul_round_sch (res1, m8, x1, x2, 8);
+ res2 = _mm_maskz_mul_round_sch (m8, x1, x2, 11);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c
index 4e48e9c..370f9ee 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfcmulcph-1a.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -mavx512fp16 -mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfcmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
#include <immintrin.h>
@@ -25,4 +25,12 @@ avx512f_test (void)
res2 = _mm_fcmul_pch (x4, x5);
res2 = _mm_mask_fcmul_pch (res2, m8, x4, x5);
res2 = _mm_maskz_fcmul_pch (m8, x4, x5);
+
+ res1 = _mm256_cmul_pch (x1, x2);
+ res1 = _mm256_mask_cmul_pch (res1, m8, x1, x2);
+ res1 = _mm256_maskz_cmul_pch (m8, x1, x2);
+
+ res2 = _mm_cmul_pch (x4, x5);
+ res2 = _mm_mask_cmul_pch (res2, m8, x4, x5);
+ res2 = _mm_maskz_cmul_pch (m8, x4, x5);
}
diff --git a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c
index 54e58c6..dce9088 100644
--- a/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c
+++ b/gcc/testsuite/gcc.target/i386/avx512fp16vl-vfmulcph-1a.c
@@ -1,11 +1,11 @@
/* { dg-do compile } */
/* { dg-options "-mavx512f -mavx512fp16 -mavx512vl -O2" } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 1 } } */
-/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 1 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+\[^\{\n\]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\[^\n\r]*%ymm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}(?:\n|\[ \\t\]+#)" 2 } } */
+/* { dg-final { scan-assembler-times "vfmulcph\[ \\t\]+%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\[^\n\r]*%xmm\[0-9\]+\{%k\[0-9\]\}\{z\}\[^\n\r]*(?:\n|\[ \\t\]+#)" 2 } } */
#include <immintrin.h>
@@ -25,4 +25,12 @@ avx512f_test (void)
res2 = _mm_fmul_pch (x4, x5);
res2 = _mm_mask_fmul_pch (res2, m8, x4, x5);
res2 = _mm_maskz_fmul_pch (m8, x4, x5);
+
+ res1 = _mm256_mul_pch (x1, x2);
+ res1 = _mm256_mask_mul_pch (res1, m8, x1, x2);
+ res1 = _mm256_maskz_mul_pch (m8, x1, x2);
+
+ res2 = _mm_mul_pch (x4, x5);
+ res2 = _mm_mask_mul_pch (res2, m8, x4, x5);
+ res2 = _mm_maskz_mul_pch (m8, x4, x5);
}
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-1.c b/gcc/testsuite/gcc.target/i386/harden-sls-1.c
new file mode 100644
index 0000000..6f70dc9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void foo (void);
+
+void
+bar (void)
+{
+ foo ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]+_?foo" } } */
+/* { dg-final { scan-assembler-not {int3} } } */
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-2.c b/gcc/testsuite/gcc.target/i386/harden-sls-2.c
new file mode 100644
index 0000000..a7c5907
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-2.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk-extern -mharden-sls=all" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void (*fptr) (void);
+
+void
+foo (void)
+{
+ fptr ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-times "int3" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-3.c b/gcc/testsuite/gcc.target/i386/harden-sls-3.c
new file mode 100644
index 0000000..1a6056b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-3.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=thunk -mharden-sls=all" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void (*fptr) (void);
+
+void
+foo (void)
+{
+ fptr ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]+_?__x86_indirect_thunk_(r|e)ax" } } */
+/* { dg-final { scan-assembler-times "int3" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-4.c b/gcc/testsuite/gcc.target/i386/harden-sls-4.c
new file mode 100644
index 0000000..f70dd13
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-4.c
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mindirect-branch=keep -mharden-sls=all" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void (*fptr) (void);
+
+void
+foo (void)
+{
+ fptr ();
+}
+
+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*_?fptr" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler "movl\[ \t\]+fptr\\(%rip\\), %eax" { target x32 } } } */
+/* { dg-final { scan-assembler "jmp\[ \t\]+\\*%rax" { target x32 } } } */
+/* { dg-final { scan-assembler-times "int3" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/harden-sls-5.c b/gcc/testsuite/gcc.target/i386/harden-sls-5.c
new file mode 100644
index 0000000..613c44c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/harden-sls-5.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-indirect-branch-register -mfunction-return=keep -mindirect-branch=thunk-extern -mharden-sls=return" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+typedef void (*dispatch_t)(long offset);
+
+dispatch_t dispatch;
+
+int
+male_indirect_jump (long offset)
+{
+ dispatch(offset);
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "ret" 1 } } */
+/* { dg-final { scan-assembler-times "int3" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c
new file mode 100644
index 0000000..db2f341
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-1.c
@@ -0,0 +1,14 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -ffixed-rax -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rdi -ffixed-rsi -mindirect-branch-cs-prefix -mindirect-branch=thunk-extern" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void (*fptr) (void);
+
+void
+foo (void)
+{
+ fptr ();
+}
+
+/* { dg-final { scan-assembler-times "jmp\[ \t\]+_?__x86_indirect_thunk_r\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\tcs" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c
new file mode 100644
index 0000000..adfc39a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/indirect-thunk-cs-prefix-2.c
@@ -0,0 +1,15 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-O2 -ffixed-rax -ffixed-rbx -ffixed-rcx -ffixed-rdx -ffixed-rdi -ffixed-rsi -mindirect-branch-cs-prefix -mindirect-branch=thunk-extern" } */
+/* { dg-additional-options "-fno-pic" { target { ! *-*-darwin* } } } */
+
+extern void (*bar) (void);
+
+int
+foo (void)
+{
+ bar ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "call\[ \t\]+_?__x86_indirect_thunk_r\[0-9\]+" 1 } } */
+/* { dg-final { scan-assembler-times "\tcs" 1 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr101180.c b/gcc/testsuite/gcc.target/i386/pr101180.c
new file mode 100644
index 0000000..1ac4cb5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr101180.c
@@ -0,0 +1,12 @@
+/* PR c++/101180 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -mno-avx -mno-crc32" } */
+
+#include <x86intrin.h>
+
+__attribute__((target ("avx"))) __attribute__((target ("crc32"))) void
+foo (__m256 *p, unsigned int *q)
+{
+ __m256 c = _mm256_and_ps (p[0], p[1]);
+ *q = __crc32b (*q, 0x55);
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr102543.c b/gcc/testsuite/gcc.target/i386/pr102543.c
new file mode 100644
index 0000000..893eb9a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102543.c
@@ -0,0 +1,35 @@
+/* PR target/102543 */
+/* { dg-do compile } */
+/* { dg-options "-Ofast -march=skylake-avx512 -fdump-tree-optimized" } */
+/* { dg-final { scan-tree-dump-not "MEM\\\[" "optimized" } } */
+
+struct a
+{
+ int a[100];
+};
+typedef struct a misaligned_t __attribute__ ((aligned (8)));
+typedef struct a aligned_t __attribute__ ((aligned (32)));
+
+__attribute__ ((used))
+__attribute__ ((noinline))
+void
+t(void *a, int misaligned, aligned_t *d)
+{
+ int i,v;
+ for (i=0;i<100;i++)
+ {
+ if (misaligned)
+ v=((misaligned_t *)a)->a[i];
+ else
+ v=((aligned_t *)a)->a[i];
+ d->a[i]+=v;
+ }
+}
+struct b {int v; misaligned_t m;aligned_t aa;} b;
+aligned_t d;
+int
+main()
+{
+ t(&b.m, 1, &d);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr103069-2.c b/gcc/testsuite/gcc.target/i386/pr103069-2.c
index 8ac824c..b3f2235 100644
--- a/gcc/testsuite/gcc.target/i386/pr103069-2.c
+++ b/gcc/testsuite/gcc.target/i386/pr103069-2.c
@@ -1,5 +1,5 @@
-/* PR target/103068 */
-/* { dg-do compile } */
+/* PR target/103069 */
+/* { dg-do run } */
/* { dg-additional-options "-O2 -march=x86-64 -mtune=generic" } */
#include <stdlib.h>
@@ -37,13 +37,14 @@ FUNC_ATOMIC_RELAX (char, xor)
#define TEST_ATOMIC_FETCH_LOGIC(TYPE, OP) \
{ \
TYPE a = 11, b = 101, res, exp; \
+ TYPE c = 11, d = 101; \
res = relax_##TYPE##_##OP##_fetch (&a, b); \
- exp = f_##TYPE##_##OP##_fetch (&a, b); \
+ exp = f_##TYPE##_##OP##_fetch (&c, d); \
if (res != exp) \
abort (); \
- a = 21, b = 92; \
+ a = c = 21, b = d = 92; \
res = relax_##TYPE##_fetch_##OP (&a, b); \
- exp = f_##TYPE##_fetch_##OP (&a, b); \
+ exp = f_##TYPE##_fetch_##OP (&c, d); \
if (res != exp) \
abort (); \
}
diff --git a/gcc/testsuite/gcc.target/i386/pr103275.c b/gcc/testsuite/gcc.target/i386/pr103275.c
new file mode 100644
index 0000000..c93413f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr103275.c
@@ -0,0 +1,83 @@
+/* { dg-do compile { target ia32 } } */
+/* { dg-options "-O2 -march=tigerlake -fPIC" } */
+/* { dg-final { scan-assembler-not {(?n)kmovd.*@gotntpoff} } } */
+
+typedef unsigned short uint16_t;
+typedef int int32_t;
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+
+typedef uint32_t in_addr_t;
+struct in_addr { in_addr_t s_addr; };
+
+extern __thread const uint16_t * __libc_tsd_CTYPE_B __attribute__ ((tls_model ("initial-exec")));
+extern __thread int __libc_errno __attribute__ ((tls_model ("initial-exec")));
+
+extern unsigned long strtoul (const char*, char**, int);
+extern uint32_t __bswap_32 (in_addr_t);
+int
+inet_aton_end (const char *cp, struct in_addr *addr, const char **endp)
+{
+ static const in_addr_t max[4] = { 0xffffffff, 0xffffff, 0xffff, 0xff };
+ in_addr_t val;
+ char c;
+ union iaddr
+ {
+ uint8_t bytes[4];
+ uint32_t word;
+ } res;
+ uint8_t *pp = res.bytes;
+ int digit;
+
+ int saved_errno = __libc_errno;
+ __libc_errno = 0;
+ res.word = 0;
+ c = *cp;
+
+ for (;;)
+ {
+ if (c < '0' || c > '9')
+ goto ret_0;
+ {
+ char *endp;
+ unsigned long ul = strtoul (cp, &endp, 0);
+ if (ul == 0x7fffffffL && __libc_errno == 34)
+ goto ret_0;
+ if (ul > 0xfffffffful)
+ goto ret_0;
+ val = ul;
+ digit = cp != endp;
+ cp = endp;
+ }
+ c = *cp;
+ if (c == '.')
+ {
+ if (pp > res.bytes + 2 || val > 0xff)
+ goto ret_0;
+ *pp++ = val;
+ c = *++cp;
+ }
+ else
+ break;
+ }
+
+ if (!(__libc_tsd_CTYPE_B[(int)c] & 8192))
+ goto ret_0;
+
+ if (!digit)
+ goto ret_0;
+
+ if (val > max[pp - res.bytes])
+ goto ret_0;
+
+ if (addr != 0)
+ addr->s_addr = res.word | __bswap_32 (val);
+ *endp = cp;
+
+ __libc_errno = saved_errno;
+ return 1;
+
+ ret_0:
+ __libc_errno = saved_errno;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/mips/frame-header-1.c b/gcc/testsuite/gcc.target/mips/frame-header-1.c
index 971656d..55efc0b 100644
--- a/gcc/testsuite/gcc.target/mips/frame-header-1.c
+++ b/gcc/testsuite/gcc.target/mips/frame-header-1.c
@@ -8,7 +8,7 @@
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* { dg-final { scan-assembler "\taddiu\t\\\$sp,\\\$sp,-24" } } */
-NOMIPS16 void __attribute__((noinline))
+NOMIPS16 void __attribute__((noinline)) __attribute__((noipa))
bar (int* a)
{
*a = 1;
diff --git a/gcc/testsuite/gcc.target/mips/frame-header-2.c b/gcc/testsuite/gcc.target/mips/frame-header-2.c
index 0e86bc9..31aa27e 100644
--- a/gcc/testsuite/gcc.target/mips/frame-header-2.c
+++ b/gcc/testsuite/gcc.target/mips/frame-header-2.c
@@ -8,7 +8,7 @@
/* { dg-skip-if "code quality test" { *-*-* } { "-O0" } { "" } } */
/* { dg-final { scan-assembler "\taddiu\t\\\$sp,\\\$sp,-8" } } */
-NOMIPS16 void __attribute__((noinline))
+NOMIPS16 void __attribute__((noinline)) __attribute__((noipa))
bar (int* a)
{
*a = 1;
diff --git a/gcc/testsuite/gcc.target/mips/octeon-bbit-1.c b/gcc/testsuite/gcc.target/mips/octeon-bbit-1.c
index f91c68b..8adbb26 100644
--- a/gcc/testsuite/gcc.target/mips/octeon-bbit-1.c
+++ b/gcc/testsuite/gcc.target/mips/octeon-bbit-1.c
@@ -22,7 +22,9 @@ f2 (int i)
foo ();
}
-NOMIPS16 void
+/* f3 and f4 are equivalent and may be subject to ICF. The attribute
+ is supposed to prevent that. */
+NOMIPS16 void __attribute__ ((noipa))
f3 (int i)
{
if (i % 2)
diff --git a/gcc/testsuite/gcc.target/powerpc/pr102976.c b/gcc/testsuite/gcc.target/powerpc/pr102976.c
new file mode 100644
index 0000000..5a4320f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/pr102976.c
@@ -0,0 +1,14 @@
+/* { dg-require-effective-target power10_ok } */
+/* { dg-options "-O2 -mdejagnu-cpu=power10" } */
+
+#include <altivec.h>
+void
+bug (__vector_pair *dst)
+{
+ register vector unsigned char vec0 asm ("vs44");
+ register vector unsigned char vec1 asm ("vs32");
+ __builtin_vsx_build_pair (dst, vec0, vec1);
+}
+
+/* { dg-final { scan-assembler-times {(?p)\mxxlor \d+,44,44\M} 1 } } */
+/* { dg-final { scan-assembler-times {(?p)\mxxlor \d+,32,32\M} 1 } } */
diff --git a/gcc/testsuite/gcc.target/s390/20211119.c b/gcc/testsuite/gcc.target/s390/20211119.c
new file mode 100644
index 0000000..b9d2163
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/20211119.c
@@ -0,0 +1,12 @@
+/* { dg-do run { target { s390_useable_hw } } } */
+/* { dg-options "-Os -march=z10" } */
+signed char a;
+int b = -925974181, c;
+unsigned *d = &b;
+int *e = &c;
+int main() {
+ *e = ((217 ^ a) > 585) < *d;
+ if (c != 1)
+ __builtin_abort();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.target/s390/mul-wide.c b/gcc/testsuite/gcc.target/s390/mul-wide.c
new file mode 100644
index 0000000..8a2092e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/mul-wide.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -m64 -fdump-tree-optimized" } */
+
+__int128 foo(long long a, long long b)
+{
+ return (__int128)a * (__int128)b;
+}
+
+/* { dg-final { scan-tree-dump " w\\* " "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/s390/umul-wide.c b/gcc/testsuite/gcc.target/s390/umul-wide.c
new file mode 100644
index 0000000..33a74e5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/umul-wide.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -m64 -fdump-tree-optimized" } */
+
+unsigned __int128 foo(unsigned long long a, unsigned long long b)
+{
+ return (unsigned __int128)a * (unsigned __int128)b;
+}
+
+/* { dg-final { scan-tree-dump " w\\* " "optimized" } } */
diff --git a/gcc/testsuite/gfortran.dg/dec_math_5.f90 b/gcc/testsuite/gfortran.dg/dec_math_5.f90
new file mode 100644
index 0000000..dee2de4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_math_5.f90
@@ -0,0 +1,104 @@
+! { dg-do run }
+! { dg-additional-options "-std=gnu" }
+! { dg-require-effective-target fortran_real_10 }
+! { dg-require-effective-target fortran_real_16 }
+
+program p
+ implicit none
+ integer, parameter :: ep = selected_real_kind (17) ! real(10)
+ real(4) :: a1, e1 = 1.e-5
+ real(8) :: b1, e2 = 1.e-14
+ real(ep) :: c1, e3 = 1.e-17
+ real(16) :: d1, e4 = 1.e-30
+
+ a1 = 1; a1 = atand(a1)
+ b1 = 1; b1 = atand(b1)
+ c1 = 1; c1 = atand(c1)
+ d1 = 1; d1 = atand(d1)
+! print '(4(F15.11))', a1, b1, c1, d1
+ if (abs(a1 - 45) > e1) stop 1
+ if (abs(b1 - 45) > e2) stop 2
+ if (abs(c1 - 45) > e3) stop 3
+ if (abs(d1 - 45) > e4) stop 4
+
+ a1 = 0.5; a1 = asind(a1)
+ b1 = 0.5; b1 = asind(b1)
+ c1 = 0.5; c1 = asind(c1)
+ d1 = 0.5; d1 = asind(d1)
+ if (abs(a1 - 30) > e1) stop 5
+ if (abs(b1 - 30) > e2) stop 6
+ if (abs(c1 - 30) > e3) stop 7
+ if (abs(d1 - 30) > e4) stop 8
+
+ a1 = 0.5; a1 = acosd(a1)
+ b1 = 0.5; b1 = acosd(b1)
+ c1 = 0.5; c1 = acosd(c1)
+ d1 = 0.5; d1 = acosd(d1)
+ if (abs(a1 - 60) > e1) stop 9
+ if (abs(b1 - 60) > e2) stop 10
+ if (abs(c1 - 60) > e3) stop 11
+ if (abs(d1 - 60) > e4) stop 12
+
+ a1 = 45; a1 = tand(a1)
+ b1 = 45; b1 = tand(b1)
+ c1 = 45; c1 = tand(c1)
+ d1 = 45; d1 = tand(d1)
+ if (abs(a1 - 1) > e1) stop 13
+ if (abs(b1 - 1) > e2) stop 14
+ if (abs(c1 - 1) > e3) stop 15
+ if (abs(d1 - 1) > e4) stop 16
+
+ a1 = 60; a1 = tand(a1)
+ b1 = 60; b1 = tand(b1)
+ c1 = 60; c1 = tand(c1)
+ d1 = 60; d1 = tand(d1)
+ if (abs(a1 - sqrt (3._4) ) > e1) stop 17
+ if (abs(b1 - sqrt (3._8) ) > e2) stop 18
+ if (abs(c1 - sqrt (3._ep)) > e3) stop 19
+ if (abs(d1 - sqrt (3._16)) > e4) stop 20
+
+ a1 = 45; a1 = cotand(a1)
+ b1 = 45; b1 = cotand(b1)
+ c1 = 45; c1 = cotand(c1)
+ d1 = 45; d1 = cotand(d1)
+ if (abs(a1 - 1) > e1) stop 21
+ if (abs(b1 - 1) > e2) stop 22
+ if (abs(c1 - 1) > e3) stop 23
+ if (abs(d1 - 1) > e4) stop 24
+
+ a1 = 30; a1 = cotand(a1)
+ b1 = 30; b1 = cotand(b1)
+ c1 = 30; c1 = cotand(c1)
+ d1 = 30; d1 = cotand(d1)
+ if (abs(a1 - sqrt (3._4) ) > e1) stop 25
+ if (abs(b1 - sqrt (3._8) ) > e2) stop 26
+ if (abs(c1 - sqrt (3._ep)) > e3) stop 27
+ if (abs(d1 - sqrt (3._16)) > e4) stop 28
+
+ a1 = 1; a1 = atan2d(a1, a1)
+ b1 = 1; b1 = atan2d(b1, b1)
+ c1 = 1; c1 = atan2d(c1, c1)
+ d1 = 1; d1 = atan2d(d1, d1)
+ if (abs(a1 - 45) > e1) stop 29
+ if (abs(b1 - 45) > e2) stop 30
+ if (abs(c1 - 45) > e3) stop 31
+ if (abs(d1 - 45) > e4) stop 32
+
+ a1 = 30; a1 = sind(a1)
+ b1 = 30; b1 = sind(b1)
+ c1 = 30; c1 = sind(c1)
+ d1 = 30; d1 = sind(d1)
+ if (abs(a1 - 0.5) > e1) stop 33
+ if (abs(b1 - 0.5) > e2) stop 34
+ if (abs(c1 - 0.5) > e3) stop 35
+ if (abs(d1 - 0.5) > e4) stop 36
+
+ a1 = 60; a1 = cosd(a1)
+ b1 = 60; b1 = cosd(b1)
+ c1 = 60; c1 = cosd(c1)
+ d1 = 60; d1 = cosd(d1)
+ if (abs(a1 - 0.5) > e1) stop 37
+ if (abs(b1 - 0.5) > e2) stop 38
+ if (abs(c1 - 0.5) > e3) stop 39
+ if (abs(d1 - 0.5) > e4) stop 40
+end program p
diff --git a/gcc/testsuite/gfortran.dg/pr101329.f90 b/gcc/testsuite/gfortran.dg/pr101329.f90
new file mode 100644
index 0000000..b82210d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr101329.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! PR fortran/101329 - ICE: Invalid expression in gfc_element_size
+
+program p
+ use iso_c_binding
+ implicit none
+ integer(c_int), pointer :: ip4
+ integer(c_int64_t), pointer :: ip8
+ print *, c_sizeof (c_null_ptr) ! valid
+ print *, c_sizeof (null ()) ! { dg-error "is not interoperable" }
+ print *, c_sizeof (null (ip4)) ! { dg-error "is not interoperable" }
+ print *, c_sizeof (null (ip8)) ! { dg-error "is not interoperable" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr103286.f90 b/gcc/testsuite/gfortran.dg/pr103286.f90
new file mode 100644
index 0000000..1c18b71
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr103286.f90
@@ -0,0 +1,11 @@
+! { dg-do compile }
+! { dg-options "std=gnu" }
+! PR fortran/103286 - ICE in resolve_select
+
+program p
+ select case (.true.) ! { dg-warning "Extension: Conversion" }
+ case (1_8)
+ case (:0) ! { dg-error "Logical range in CASE statement" }
+ case (2:) ! { dg-error "Logical range in CASE statement" }
+ end select
+end
diff --git a/gcc/testsuite/jit.dg/all-non-failing-tests.h b/gcc/testsuite/jit.dg/all-non-failing-tests.h
index 84ef54a..a7fddf9 100644
--- a/gcc/testsuite/jit.dg/all-non-failing-tests.h
+++ b/gcc/testsuite/jit.dg/all-non-failing-tests.h
@@ -265,6 +265,13 @@
#undef create_code
#undef verify_code
+/* test-reflection.c */
+#define create_code create_code_reflection
+#define verify_code verify_code_reflection
+#include "test-reflection.c"
+#undef create_code
+#undef verify_code
+
/* test-string-literal.c */
#define create_code create_code_string_literal
#define verify_code verify_code_string_literal
@@ -434,6 +441,9 @@ const struct testcase testcases[] = {
{"reading_struct ",
create_code_reading_struct ,
verify_code_reading_struct },
+ {"reflection",
+ create_code_reflection ,
+ verify_code_reflection },
{"string_literal",
create_code_string_literal,
verify_code_string_literal},
diff --git a/gcc/testsuite/jit.dg/test-reflection.c b/gcc/testsuite/jit.dg/test-reflection.c
new file mode 100644
index 0000000..112a245
--- /dev/null
+++ b/gcc/testsuite/jit.dg/test-reflection.c
@@ -0,0 +1,95 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libgccjit.h"
+
+#include "harness.h"
+
+void
+create_code (gcc_jit_context *ctxt, void *user_data)
+{
+ /* Do nothing. */
+}
+
+void
+verify_code (gcc_jit_context *ctxt, gcc_jit_result *result)
+{
+ /* Get the built-in functions. */
+ gcc_jit_function *builtin_sin =
+ gcc_jit_context_get_builtin_function (ctxt, "sin");
+
+ CHECK_VALUE (gcc_jit_function_get_param_count(builtin_sin), 1);
+
+ gcc_jit_type *double_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_DOUBLE);
+ CHECK_VALUE (gcc_jit_function_get_return_type(builtin_sin), double_type);
+ CHECK (!gcc_jit_type_is_integral(double_type));
+
+ gcc_jit_type *bool_type =
+ gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL);
+ CHECK (gcc_jit_type_is_bool(bool_type));
+ CHECK (!gcc_jit_type_is_integral(bool_type));
+
+ gcc_jit_type *aligned_bool_type =
+ gcc_jit_type_get_aligned(gcc_jit_context_get_type (ctxt, GCC_JIT_TYPE_BOOL), 8);
+ CHECK (gcc_jit_type_is_bool(aligned_bool_type));
+ CHECK (bool_type != aligned_bool_type);
+ CHECK_VALUE (gcc_jit_type_unqualified(aligned_bool_type), bool_type);
+
+ CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_const(bool_type)), bool_type);
+ CHECK_VALUE (gcc_jit_type_unqualified(gcc_jit_type_get_volatile(bool_type)), bool_type);
+
+ gcc_jit_type *int64 =
+ gcc_jit_context_get_int_type(ctxt, 8, 1);
+ CHECK (gcc_jit_type_is_integral(int64));
+ gcc_jit_type *uint64 =
+ gcc_jit_context_get_int_type(ctxt, 8, 0);
+ CHECK (gcc_jit_type_is_integral(uint64));
+ gcc_jit_type *int8 =
+ gcc_jit_context_get_int_type(ctxt, 1, 1);
+ CHECK (gcc_jit_type_is_integral(int8));
+ gcc_jit_type *uint8 =
+ gcc_jit_context_get_int_type(ctxt, 1, 0);
+ CHECK (gcc_jit_type_is_integral(uint8));
+
+ CHECK (!gcc_jit_type_dyncast_vector(double_type));
+ gcc_jit_type *vec_type = gcc_jit_type_get_vector (double_type, 4);
+ gcc_jit_vector_type *vector_type = gcc_jit_type_dyncast_vector(vec_type);
+ CHECK (vector_type);
+ CHECK (vec_type != double_type);
+ CHECK_VALUE (gcc_jit_vector_type_get_element_type(vector_type), double_type);
+ CHECK_VALUE (gcc_jit_vector_type_get_num_units(vector_type), 4);
+
+ CHECK (!gcc_jit_type_is_pointer(double_type));
+ CHECK_VALUE (gcc_jit_type_is_pointer(gcc_jit_type_get_pointer(double_type)), double_type);
+
+ gcc_jit_type* params[2] = {int8, uint64};
+ gcc_jit_type *function_ptr_type = gcc_jit_context_new_function_ptr_type(ctxt, NULL, int64, 2, params, 0);
+ CHECK (!gcc_jit_type_dyncast_function_ptr_type (int64));
+ gcc_jit_function_type *function_type = gcc_jit_type_dyncast_function_ptr_type (function_ptr_type);
+ CHECK (function_type);
+ int param_count = gcc_jit_function_type_get_param_count(function_type);
+ CHECK_VALUE (param_count, 2);
+ gcc_jit_type *return_type = gcc_jit_function_type_get_return_type(function_type);
+ CHECK_VALUE (return_type, int64);
+ gcc_jit_type *param1 = gcc_jit_function_type_get_param_type(function_type, 0);
+ CHECK_VALUE (param1, int8);
+ gcc_jit_type *param2 = gcc_jit_function_type_get_param_type(function_type, 1);
+ CHECK_VALUE (param2, uint64);
+
+ gcc_jit_field *field1 = gcc_jit_context_new_field (ctxt, NULL, uint64, "field1");
+ gcc_jit_field *field2 = gcc_jit_context_new_field (ctxt, NULL, double_type, "field2");
+ gcc_jit_field *fields[2] = { field1, field2 };
+ gcc_jit_struct *struct_type = gcc_jit_context_new_struct_type (ctxt, NULL, "testStruct", 2, fields);
+ CHECK_VALUE (gcc_jit_struct_get_field_count(struct_type), 2);
+ CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 0), field1);
+ CHECK_VALUE (gcc_jit_struct_get_field(struct_type, 1), field2);
+ CHECK (!gcc_jit_type_is_struct(double_type));
+ gcc_jit_struct *struct_ty = gcc_jit_type_is_struct(gcc_jit_struct_as_type(struct_type));
+ CHECK_VALUE (struct_ty, struct_type);
+
+ CHECK (!gcc_jit_type_dyncast_array(double_type));
+ gcc_jit_type* array_type = gcc_jit_context_new_array_type(ctxt, NULL, double_type, 1);
+ CHECK_VALUE (gcc_jit_type_dyncast_array(array_type), double_type);
+}
+
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index c928d99..155034c 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -3632,8 +3632,10 @@ proc check_effective_target_vect_complex_add_float { } {
proc check_effective_target_vect_complex_add_double { } {
return [check_cached_effective_target_indexed vect_complex_add_double {
expr {
- ([check_effective_target_aarch64_sve2]
- && [check_effective_target_aarch64_little_endian])
+ (([check_effective_target_arm_v8_3a_complex_neon_ok]
+ && [check_effective_target_aarch64_little_endian])
+ || ([check_effective_target_aarch64_sve2]
+ && [check_effective_target_aarch64_little_endian]))
}}]
}
diff --git a/gcc/tree-eh.c b/gcc/tree-eh.c
index 3eff07f..916da85 100644
--- a/gcc/tree-eh.c
+++ b/gcc/tree-eh.c
@@ -2474,10 +2474,16 @@ operation_could_trap_helper_p (enum tree_code op,
return false;
case RDIV_EXPR:
- if (honor_snans)
+ if (fp_operation)
+ {
+ if (honor_snans)
+ return true;
+ return flag_trapping_math;
+ }
+ /* Fixed point operations also use RDIV_EXPR. */
+ if (!TREE_CONSTANT (divisor) || fixed_zerop (divisor))
return true;
- gcc_assert (fp_operation);
- return flag_trapping_math;
+ return false;
case LT_EXPR:
case LE_EXPR:
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 02bbc87..cd6a0b2 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -2755,7 +2755,7 @@ ref_maybe_used_by_call_p_1 (gcall *call, ao_ref *ref, bool tbaa_p)
callee = gimple_call_fndecl (call);
- if (!gimple_call_chain (call) && callee != NULL_TREE)
+ if (callee != NULL_TREE)
{
struct cgraph_node *node = cgraph_node::get (callee);
/* We can not safely optimize based on summary of calle if it does
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index dbf02c4..e3e6f09 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -1626,6 +1626,10 @@ sort_phi_args (const void *a_, const void *b_)
return -1;
else if (ha > hb)
return 1;
+ else if (a->first->dest_idx < b->first->dest_idx)
+ return -1;
+ else if (a->first->dest_idx > b->first->dest_idx)
+ return 1;
else
return 0;
}
diff --git a/gcc/tree-ssa-dse.c b/gcc/tree-ssa-dse.c
index ce0083a..9531d89 100644
--- a/gcc/tree-ssa-dse.c
+++ b/gcc/tree-ssa-dse.c
@@ -88,6 +88,7 @@ static void delete_dead_or_redundant_call (gimple_stmt_iterator *, const char *)
/* Bitmap of blocks that have had EH statements cleaned. We should
remove their dead edges eventually. */
static bitmap need_eh_cleanup;
+static bitmap need_ab_cleanup;
/* STMT is a statement that may write into memory. Analyze it and
initialize WRITE to describe how STMT affects memory.
@@ -209,6 +210,26 @@ normalize_ref (ao_ref *copy, ao_ref *ref)
return true;
}
+/* Update LIVE_BYTES tracking REF for write to WRITE:
+ Verify we have the same base memory address, the write
+ has a known size and overlaps with REF. */
+static void
+clear_live_bytes_for_ref (sbitmap live_bytes, ao_ref *ref, ao_ref write)
+{
+ HOST_WIDE_INT start, size;
+
+ if (valid_ao_ref_for_dse (&write)
+ && operand_equal_p (write.base, ref->base, OEP_ADDRESS_OF)
+ && known_eq (write.size, write.max_size)
+ /* normalize_ref modifies write and for that reason write is not
+ passed by reference. */
+ && normalize_ref (&write, ref)
+ && (write.offset - ref->offset).is_constant (&start)
+ && write.size.is_constant (&size))
+ bitmap_clear_range (live_bytes, start / BITS_PER_UNIT,
+ size / BITS_PER_UNIT);
+}
+
/* Clear any bytes written by STMT from the bitmap LIVE_BYTES. The base
address written by STMT must match the one found in REF, which must
have its base address previously initialized.
@@ -220,20 +241,21 @@ static void
clear_bytes_written_by (sbitmap live_bytes, gimple *stmt, ao_ref *ref)
{
ao_ref write;
+
+ if (gcall *call = dyn_cast <gcall *> (stmt))
+ {
+ bool interposed;
+ modref_summary *summary = get_modref_function_summary (call, &interposed);
+
+ if (summary && !interposed)
+ for (auto kill : summary->kills)
+ if (kill.get_ao_ref (as_a <gcall *> (stmt), &write))
+ clear_live_bytes_for_ref (live_bytes, ref, write);
+ }
if (!initialize_ao_ref_for_dse (stmt, &write))
return;
- /* Verify we have the same base memory address, the write
- has a known size and overlaps with REF. */
- HOST_WIDE_INT start, size;
- if (valid_ao_ref_for_dse (&write)
- && operand_equal_p (write.base, ref->base, OEP_ADDRESS_OF)
- && known_eq (write.size, write.max_size)
- && normalize_ref (&write, ref)
- && (write.offset - ref->offset).is_constant (&start)
- && write.size.is_constant (&size))
- bitmap_clear_range (live_bytes, start / BITS_PER_UNIT,
- size / BITS_PER_UNIT);
+ clear_live_bytes_for_ref (live_bytes, ref, write);
}
/* REF is a memory write. Extract relevant information from it and
@@ -737,7 +759,8 @@ dse_optimize_redundant_stores (gimple *stmt)
(ao_ref_base_alias_set (&lhs_ref),
earlier_base_set)))
delete_dead_or_redundant_assignment (&gsi, "redundant",
- need_eh_cleanup);
+ need_eh_cleanup,
+ need_ab_cleanup);
}
else if (is_gimple_call (use_stmt))
{
@@ -1006,8 +1029,10 @@ delete_dead_or_redundant_call (gimple_stmt_iterator *gsi, const char *type)
/* Delete a dead store at GSI, which is a gimple assignment. */
void
-delete_dead_or_redundant_assignment (gimple_stmt_iterator *gsi, const char *type,
- bitmap need_eh_cleanup)
+delete_dead_or_redundant_assignment (gimple_stmt_iterator *gsi,
+ const char *type,
+ bitmap need_eh_cleanup,
+ bitmap need_ab_cleanup)
{
gimple *stmt = gsi_stmt (*gsi);
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -1022,6 +1047,8 @@ delete_dead_or_redundant_assignment (gimple_stmt_iterator *gsi, const char *type
/* Remove the dead store. */
basic_block bb = gimple_bb (stmt);
+ if (need_ab_cleanup && stmt_can_make_abnormal_goto (stmt))
+ bitmap_set_bit (need_ab_cleanup, bb->index);
if (gsi_remove (gsi, true) && need_eh_cleanup)
bitmap_set_bit (need_eh_cleanup, bb->index);
@@ -1111,7 +1138,8 @@ dse_optimize_call (gimple_stmt_iterator *gsi, sbitmap live_bytes)
if (store_status != DSE_STORE_DEAD)
return false;
}
- delete_dead_or_redundant_assignment (gsi, "dead", need_eh_cleanup);
+ delete_dead_or_redundant_assignment (gsi, "dead", need_eh_cleanup,
+ need_ab_cleanup);
return true;
}
@@ -1275,7 +1303,8 @@ dse_optimize_stmt (function *fun, gimple_stmt_iterator *gsi, sbitmap live_bytes)
update_stmt (stmt);
}
else
- delete_dead_or_redundant_assignment (gsi, "dead", need_eh_cleanup);
+ delete_dead_or_redundant_assignment (gsi, "dead", need_eh_cleanup,
+ need_ab_cleanup);
}
namespace {
@@ -1312,6 +1341,7 @@ pass_dse::execute (function *fun)
{
unsigned todo = 0;
need_eh_cleanup = BITMAP_ALLOC (NULL);
+ need_ab_cleanup = BITMAP_ALLOC (NULL);
auto_sbitmap live_bytes (param_dse_max_object_size);
renumber_gimple_stmt_uids (fun);
@@ -1389,8 +1419,14 @@ pass_dse::execute (function *fun)
gimple_purge_all_dead_eh_edges (need_eh_cleanup);
todo |= TODO_cleanup_cfg;
}
+ if (!bitmap_empty_p (need_ab_cleanup))
+ {
+ gimple_purge_all_dead_abnormal_call_edges (need_ab_cleanup);
+ todo |= TODO_cleanup_cfg;
+ }
BITMAP_FREE (need_eh_cleanup);
+ BITMAP_FREE (need_ab_cleanup);
return todo;
}
diff --git a/gcc/tree-ssa-dse.h b/gcc/tree-ssa-dse.h
index 337579a..051620c 100644
--- a/gcc/tree-ssa-dse.h
+++ b/gcc/tree-ssa-dse.h
@@ -32,6 +32,6 @@ dse_store_status dse_classify_store (ao_ref *, gimple *, bool, sbitmap,
bool * = NULL, tree = NULL);
void delete_dead_or_redundant_assignment (gimple_stmt_iterator *, const char *,
- bitmap = NULL);
+ bitmap = NULL, bitmap = NULL);
#endif /* GCC_TREE_SSA_DSE_H */
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 4b187c2..682406d 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1183,14 +1183,10 @@ move_computations_worker (basic_block bb)
COND_EXPR, t, arg0, arg1);
todo |= TODO_cleanup_cfg;
}
- if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_lhs (new_stmt)))
- && (!ALWAYS_EXECUTED_IN (bb)
- || (ALWAYS_EXECUTED_IN (bb) != level
- && !flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level))))
- {
- tree lhs = gimple_assign_lhs (new_stmt);
- SSA_NAME_RANGE_INFO (lhs) = NULL;
- }
+ if (!ALWAYS_EXECUTED_IN (bb)
+ || (ALWAYS_EXECUTED_IN (bb) != level
+ && !flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level)))
+ reset_flow_sensitive_info (gimple_assign_lhs (new_stmt));
gsi_insert_on_edge (loop_preheader_edge (level), new_stmt);
remove_phi_node (&bsi, false);
}
@@ -1253,14 +1249,10 @@ move_computations_worker (basic_block bb)
gsi_remove (&bsi, false);
if (gimple_has_lhs (stmt)
&& TREE_CODE (gimple_get_lhs (stmt)) == SSA_NAME
- && INTEGRAL_TYPE_P (TREE_TYPE (gimple_get_lhs (stmt)))
&& (!ALWAYS_EXECUTED_IN (bb)
|| !(ALWAYS_EXECUTED_IN (bb) == level
|| flow_loop_nested_p (ALWAYS_EXECUTED_IN (bb), level))))
- {
- tree lhs = gimple_get_lhs (stmt);
- SSA_NAME_RANGE_INFO (lhs) = NULL;
- }
+ reset_flow_sensitive_info (gimple_get_lhs (stmt));
/* In case this is a stmt that is not unconditionally executed
when the target loop header is executed and the stmt may
invoke undefined integer or pointer overflow rewrite it to
@@ -1919,10 +1911,13 @@ first_mem_ref_loc (class loop *loop, im_mem_ref *ref)
}
}
if (lsm_flag) <--
- MEM = lsm; <--
+ MEM = lsm; <-- (X)
+
+ In case MEM and TMP_VAR are NULL the function will return the then
+ block so the caller can insert (X) and other related stmts.
*/
-static void
+static basic_block
execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag,
edge preheader, hash_set <basic_block> *flag_bbs,
edge &append_cond_position, edge &last_cond_fallthru)
@@ -2017,10 +2012,13 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag,
NULL_TREE, NULL_TREE);
gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
- gsi = gsi_start_bb (then_bb);
/* Insert actual store. */
- stmt = gimple_build_assign (unshare_expr (mem), tmp_var);
- gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
+ if (mem)
+ {
+ gsi = gsi_start_bb (then_bb);
+ stmt = gimple_build_assign (unshare_expr (mem), tmp_var);
+ gsi_insert_after (&gsi, stmt, GSI_CONTINUE_LINKING);
+ }
edge e1 = single_succ_edge (new_bb);
edge e2 = make_edge (new_bb, then_bb,
@@ -2068,6 +2066,8 @@ execute_sm_if_changed (edge ex, tree mem, tree tmp_var, tree flag,
update_stmt (phi);
}
}
+
+ return then_bb;
}
/* When REF is set on the location, set flag indicating the store. */
@@ -2125,7 +2125,8 @@ struct sm_aux
static void
execute_sm (class loop *loop, im_mem_ref *ref,
- hash_map<im_mem_ref *, sm_aux *> &aux_map, bool maybe_mt)
+ hash_map<im_mem_ref *, sm_aux *> &aux_map, bool maybe_mt,
+ bool use_other_flag_var)
{
gassign *load;
struct fmt_data fmt_data;
@@ -2154,7 +2155,7 @@ execute_sm (class loop *loop, im_mem_ref *ref,
|| (! flag_store_data_races && ! always_stored)))
multi_threaded_model_p = true;
- if (multi_threaded_model_p)
+ if (multi_threaded_model_p && !use_other_flag_var)
aux->store_flag
= execute_sm_if_changed_flag_set (loop, ref, &aux->flag_bbs);
else
@@ -2190,7 +2191,7 @@ execute_sm (class loop *loop, im_mem_ref *ref,
lim_data->tgt_loop = loop;
gsi_insert_before (&gsi, load, GSI_SAME_STMT);
- if (multi_threaded_model_p)
+ if (aux->store_flag)
{
load = gimple_build_assign (aux->store_flag, boolean_false_node);
lim_data = init_lim_data (load);
@@ -2563,6 +2564,140 @@ hoist_memory_references (class loop *loop, bitmap mem_refs,
unsigned i;
bitmap_iterator bi;
+ /* There's a special case we can use ordered re-materialization for
+ conditionally excuted stores which is when all stores in the loop
+ happen in the same basic-block. In that case we know we'll reach
+ all stores and thus can simply process that BB and emit a single
+ conditional block of ordered materializations. See PR102436. */
+ basic_block single_store_bb = NULL;
+ EXECUTE_IF_SET_IN_BITMAP (&memory_accesses.all_refs_stored_in_loop[loop->num],
+ 0, i, bi)
+ {
+ bool fail = false;
+ ref = memory_accesses.refs_list[i];
+ for (auto loc : ref->accesses_in_loop)
+ if (!gimple_vdef (loc.stmt))
+ ;
+ else if (!single_store_bb)
+ {
+ single_store_bb = gimple_bb (loc.stmt);
+ bool conditional = false;
+ for (edge e : exits)
+ if (!dominated_by_p (CDI_DOMINATORS, e->src, single_store_bb))
+ {
+ /* Conditional as seen from e. */
+ conditional = true;
+ break;
+ }
+ if (!conditional)
+ {
+ fail = true;
+ break;
+ }
+ }
+ else if (single_store_bb != gimple_bb (loc.stmt))
+ {
+ fail = true;
+ break;
+ }
+ if (fail)
+ {
+ single_store_bb = NULL;
+ break;
+ }
+ }
+ if (single_store_bb)
+ {
+ /* Analyze the single block with stores. */
+ auto_bitmap fully_visited;
+ auto_bitmap refs_not_supported;
+ auto_bitmap refs_not_in_seq;
+ auto_vec<seq_entry> seq;
+ bitmap_copy (refs_not_in_seq, mem_refs);
+ int res = sm_seq_valid_bb (loop, single_store_bb, NULL_TREE,
+ seq, refs_not_in_seq, refs_not_supported,
+ false, fully_visited);
+ if (res != 1)
+ {
+ /* Unhandled refs can still fail this. */
+ bitmap_clear (mem_refs);
+ return;
+ }
+
+ /* We cannot handle sm_other since we neither remember the
+ stored location nor the value at the point we execute them. */
+ for (unsigned i = 0; i < seq.length (); ++i)
+ {
+ unsigned new_i;
+ if (seq[i].second == sm_other
+ && seq[i].from != NULL_TREE)
+ seq[i].from = NULL_TREE;
+ else if ((seq[i].second == sm_ord
+ || (seq[i].second == sm_other
+ && seq[i].from != NULL_TREE))
+ && !sm_seq_push_down (seq, i, &new_i))
+ {
+ bitmap_set_bit (refs_not_supported, seq[new_i].first);
+ seq[new_i].second = sm_other;
+ seq[new_i].from = NULL_TREE;
+ }
+ }
+ bitmap_and_compl_into (mem_refs, refs_not_supported);
+ if (bitmap_empty_p (mem_refs))
+ return;
+
+ /* Prune seq. */
+ while (seq.last ().second == sm_other
+ && seq.last ().from == NULL_TREE)
+ seq.pop ();
+
+ hash_map<im_mem_ref *, sm_aux *> aux_map;
+
+ /* Execute SM but delay the store materialization for ordered
+ sequences on exit. */
+ bool first_p = true;
+ EXECUTE_IF_SET_IN_BITMAP (mem_refs, 0, i, bi)
+ {
+ ref = memory_accesses.refs_list[i];
+ execute_sm (loop, ref, aux_map, true, !first_p);
+ first_p = false;
+ }
+
+ /* Get at the single flag variable we eventually produced. */
+ im_mem_ref *ref
+ = memory_accesses.refs_list[bitmap_first_set_bit (mem_refs)];
+ sm_aux *aux = *aux_map.get (ref);
+
+ /* Materialize ordered store sequences on exits. */
+ edge e;
+ FOR_EACH_VEC_ELT (exits, i, e)
+ {
+ edge append_cond_position = NULL;
+ edge last_cond_fallthru = NULL;
+ edge insert_e = e;
+ /* Construct the single flag variable control flow and insert
+ the ordered seq of stores in the then block. With
+ -fstore-data-races we can do the stores unconditionally. */
+ if (aux->store_flag)
+ insert_e
+ = single_pred_edge
+ (execute_sm_if_changed (e, NULL_TREE, NULL_TREE,
+ aux->store_flag,
+ loop_preheader_edge (loop),
+ &aux->flag_bbs, append_cond_position,
+ last_cond_fallthru));
+ execute_sm_exit (loop, insert_e, seq, aux_map, sm_ord,
+ append_cond_position, last_cond_fallthru);
+ gsi_commit_one_edge_insert (insert_e, NULL);
+ }
+
+ for (hash_map<im_mem_ref *, sm_aux *>::iterator iter = aux_map.begin ();
+ iter != aux_map.end (); ++iter)
+ delete (*iter).second;
+
+ return;
+ }
+
/* To address PR57359 before actually applying store-motion check
the candidates found for validity with regards to reordering
relative to other stores which we until here disambiguated using
@@ -2701,7 +2836,8 @@ hoist_memory_references (class loop *loop, bitmap mem_refs,
EXECUTE_IF_SET_IN_BITMAP (mem_refs, 0, i, bi)
{
ref = memory_accesses.refs_list[i];
- execute_sm (loop, ref, aux_map, bitmap_bit_p (refs_not_supported, i));
+ execute_sm (loop, ref, aux_map, bitmap_bit_p (refs_not_supported, i),
+ false);
}
/* Materialize ordered store sequences on exits. */
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index c4a6492..6131824 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -2723,7 +2723,16 @@ convert_mult_to_widen (gimple *stmt, gimple_stmt_iterator *gsi)
from_unsigned1 = from_unsigned2 = false;
}
else
- return false;
+ {
+ /* Expand can synthesize smul_widen_optab if the target
+ supports umul_widen_optab. */
+ op = umul_widen_optab;
+ handler = find_widening_optab_handler_and_mode (op, to_mode,
+ from_mode,
+ &actual_mode);
+ if (handler == CODE_FOR_nothing)
+ return false;
+ }
}
/* Ensure that the inputs to the handler are in the correct precison
@@ -3224,6 +3233,10 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2,
fma_deferring_state *state, tree mul_cond = NULL_TREE)
{
tree mul_result = gimple_get_lhs (mul_stmt);
+ /* If there isn't a LHS then this can't be an FMA. There can be no LHS
+ if the statement was left just for the side-effects. */
+ if (!mul_result)
+ return false;
tree type = TREE_TYPE (mul_result);
gimple *use_stmt, *neguse_stmt;
use_operand_p use_p;
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 6b22f6b..2fa7069 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -1381,6 +1381,9 @@ value_replacement (basic_block cond_bb, basic_block middle_bb,
}
}
+ if (!single_pred_p (middle_bb))
+ return 0;
+
/* Now optimize (x != 0) ? x + y : y to just x + y. */
gsi = gsi_last_nondebug_bb (middle_bb);
if (gsi_end_p (gsi))
@@ -1777,6 +1780,9 @@ minmax_replacement (basic_block cond_bb, basic_block middle_bb,
gimple *assign = last_and_only_stmt (middle_bb);
tree lhs, op0, op1, bound;
+ if (!single_pred_p (middle_bb))
+ return false;
+
if (!assign
|| gimple_code (assign) != GIMPLE_ASSIGN)
return false;
diff --git a/gcc/tree-ssa-strlen.c b/gcc/tree-ssa-strlen.c
index c0ec7d2..536f796 100644
--- a/gcc/tree-ssa-strlen.c
+++ b/gcc/tree-ssa-strlen.c
@@ -193,6 +193,8 @@ struct laststmt_struct
} laststmt;
static int get_stridx_plus_constant (strinfo *, unsigned HOST_WIDE_INT, tree);
+static bool get_range_strlen_dynamic (tree, gimple *s, c_strlen_data *,
+ bitmap, range_query *, unsigned *);
/* Sets MINMAX to either the constant value or the range VAL is in
and returns either the constant value or VAL on success or null
@@ -1087,6 +1089,76 @@ dump_strlen_info (FILE *fp, gimple *stmt, range_query *rvals)
}
}
+/* Helper of get_range_strlen_dynamic(). See below. */
+
+static bool
+get_range_strlen_phi (tree src, gphi *phi,
+ c_strlen_data *pdata, bitmap visited,
+ range_query *rvals, unsigned *pssa_def_max)
+{
+ if (!bitmap_set_bit (visited, SSA_NAME_VERSION (src)))
+ return true;
+
+ if (*pssa_def_max == 0)
+ return false;
+
+ --*pssa_def_max;
+
+ /* Iterate over the PHI arguments and determine the minimum and maximum
+ length/size of each and incorporate them into the overall result. */
+ for (unsigned i = 0; i != gimple_phi_num_args (phi); ++i)
+ {
+ tree arg = gimple_phi_arg_def (phi, i);
+ if (arg == gimple_phi_result (phi))
+ continue;
+
+ c_strlen_data argdata = { };
+ if (!get_range_strlen_dynamic (arg, phi, &argdata, visited, rvals,
+ pssa_def_max))
+ {
+ pdata->maxlen = build_all_ones_cst (size_type_node);
+ continue;
+ }
+
+ /* Set the DECL of an unterminated array this argument refers to
+ if one hasn't been found yet. */
+ if (!pdata->decl && argdata.decl)
+ pdata->decl = argdata.decl;
+
+ if (!argdata.minlen
+ || (integer_zerop (argdata.minlen)
+ && (!argdata.maxbound
+ || integer_all_onesp (argdata.maxbound))
+ && integer_all_onesp (argdata.maxlen)))
+ {
+ /* Set the upper bound of the length to unbounded. */
+ pdata->maxlen = build_all_ones_cst (size_type_node);
+ continue;
+ }
+
+ /* Adjust the minimum and maximum length determined so far and
+ the upper bound on the array size. */
+ if (!pdata->minlen
+ || tree_int_cst_lt (argdata.minlen, pdata->minlen))
+ pdata->minlen = argdata.minlen;
+
+ if (!pdata->maxlen
+ || (argdata.maxlen
+ && TREE_CODE (argdata.maxlen) == INTEGER_CST
+ && tree_int_cst_lt (pdata->maxlen, argdata.maxlen)))
+ pdata->maxlen = argdata.maxlen;
+
+ if (!pdata->maxbound
+ || TREE_CODE (pdata->maxbound) != INTEGER_CST
+ || (argdata.maxbound
+ && tree_int_cst_lt (pdata->maxbound, argdata.maxbound)
+ && !integer_all_onesp (argdata.maxbound)))
+ pdata->maxbound = argdata.maxbound;
+ }
+
+ return true;
+}
+
/* Attempt to determine the length of the string SRC. On success, store
the length in *PDATA and return true. Otherwise, return false.
VISITED is a bitmap of visited PHI nodes. RVALS points to the valuation
@@ -1095,7 +1167,7 @@ dump_strlen_info (FILE *fp, gimple *stmt, range_query *rvals)
static bool
get_range_strlen_dynamic (tree src, gimple *stmt,
- c_strlen_data *pdata, bitmap *visited,
+ c_strlen_data *pdata, bitmap visited,
range_query *rvals, unsigned *pssa_def_max)
{
int idx = get_stridx (src, stmt);
@@ -1104,72 +1176,9 @@ get_range_strlen_dynamic (tree src, gimple *stmt,
if (TREE_CODE (src) == SSA_NAME)
{
gimple *def_stmt = SSA_NAME_DEF_STMT (src);
- if (gimple_code (def_stmt) == GIMPLE_PHI)
- {
- if (!*visited)
- *visited = BITMAP_ALLOC (NULL);
-
- if (!bitmap_set_bit (*visited, SSA_NAME_VERSION (src)))
- return true;
-
- if (*pssa_def_max == 0)
- return false;
-
- --*pssa_def_max;
-
- /* Iterate over the PHI arguments and determine the minimum
- and maximum length/size of each and incorporate them into
- the overall result. */
- gphi *phi = as_a <gphi *> (def_stmt);
- for (unsigned i = 0; i != gimple_phi_num_args (phi); ++i)
- {
- tree arg = gimple_phi_arg_def (phi, i);
- if (arg == gimple_phi_result (def_stmt))
- continue;
-
- c_strlen_data argdata = { };
- if (get_range_strlen_dynamic (arg, phi, &argdata, visited,
- rvals, pssa_def_max))
- {
- /* Set the DECL of an unterminated array this argument
- refers to if one hasn't been found yet. */
- if (!pdata->decl && argdata.decl)
- pdata->decl = argdata.decl;
-
- if (!argdata.minlen
- || (integer_zerop (argdata.minlen)
- && (!argdata.maxbound
- || integer_all_onesp (argdata.maxbound))
- && integer_all_onesp (argdata.maxlen)))
- {
- /* Set the upper bound of the length to unbounded. */
- pdata->maxlen = build_all_ones_cst (size_type_node);
- continue;
- }
-
- /* Adjust the minimum and maximum length determined
- so far and the upper bound on the array size. */
- if (!pdata->minlen
- || tree_int_cst_lt (argdata.minlen, pdata->minlen))
- pdata->minlen = argdata.minlen;
- if (!pdata->maxlen
- || (argdata.maxlen
- && tree_int_cst_lt (pdata->maxlen, argdata.maxlen)))
- pdata->maxlen = argdata.maxlen;
- if (!pdata->maxbound
- || TREE_CODE (pdata->maxbound) != INTEGER_CST
- || (argdata.maxbound
- && tree_int_cst_lt (pdata->maxbound,
- argdata.maxbound)
- && !integer_all_onesp (argdata.maxbound)))
- pdata->maxbound = argdata.maxbound;
- }
- else
- pdata->maxlen = build_all_ones_cst (size_type_node);
- }
-
- return true;
- }
+ if (gphi *phi = dyn_cast<gphi *>(def_stmt))
+ return get_range_strlen_phi (src, phi, pdata, visited, rvals,
+ pssa_def_max);
}
/* Return success regardless of the result and handle *PDATA
@@ -1286,11 +1295,11 @@ void
get_range_strlen_dynamic (tree src, gimple *stmt, c_strlen_data *pdata,
range_query *rvals)
{
- bitmap visited = NULL;
+ auto_bitmap visited;
tree maxbound = pdata->maxbound;
unsigned limit = param_ssa_name_def_chain_limit;
- if (!get_range_strlen_dynamic (src, stmt, pdata, &visited, rvals, &limit))
+ if (!get_range_strlen_dynamic (src, stmt, pdata, visited, rvals, &limit))
{
/* On failure extend the length range to an impossible maximum
(a valid MAXLEN must be less than PTRDIFF_MAX - 1). Other
@@ -1305,9 +1314,6 @@ get_range_strlen_dynamic (tree src, gimple *stmt, c_strlen_data *pdata,
MAXBOUND to SIZE_MAX. Otherwise leave it null (if it is null). */
if (maxbound && pdata->maxbound == maxbound)
pdata->maxbound = build_all_ones_cst (size_type_node);
-
- if (visited)
- BITMAP_FREE (visited);
}
/* Invalidate string length information for strings whose length might
@@ -5831,7 +5837,7 @@ printf_strlen_execute (function *fun, bool warn_only)
walker.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
if (dump_file && (dump_flags & TDF_DETAILS))
- walker.ptr_qry.dump (dump_file);
+ walker.ptr_qry.dump (dump_file, true);
ssa_ver_to_stridx.release ();
strinfo_pool.release ();
diff --git a/gcc/tree-vect-slp-patterns.c b/gcc/tree-vect-slp-patterns.c
index 53fbe51..0350441 100644
--- a/gcc/tree-vect-slp-patterns.c
+++ b/gcc/tree-vect-slp-patterns.c
@@ -809,14 +809,20 @@ vect_validate_multiplication (slp_tree_to_load_perm_map_t *perm_cache,
if (linear_loads_p (perm_cache, left_op[index2]) == PERM_EVENODD)
return true;
}
- else if (kind == PERM_EVENODD)
+ else if (kind == PERM_EVENODD && !neg_first)
{
- if ((kind = linear_loads_p (perm_cache, left_op[index2])) == PERM_EVENODD)
+ if ((kind = linear_loads_p (perm_cache, left_op[index2])) != PERM_EVENEVEN)
return false;
return true;
}
- else if (!neg_first)
- *conj_first_operand = true;
+ else if (kind == PERM_EVENEVEN && neg_first)
+ {
+ if ((kind = linear_loads_p (perm_cache, left_op[index2])) != PERM_EVENODD)
+ return false;
+
+ *conj_first_operand = true;
+ return true;
+ }
else
return false;
@@ -962,7 +968,7 @@ complex_mul_pattern::matches (complex_operation_t op,
{
auto vals = SLP_TREE_CHILDREN (l0node[0]);
/* Check if it's a multiply, otherwise no idea what this is. */
- if (!vect_match_expression_p (vals[1], MULT_EXPR))
+ if (!(mul0 = vect_match_expression_p (vals[1], MULT_EXPR)))
return IFN_LAST;
/* Check if the ADD is linear, otherwise it's not valid complex FMA. */
@@ -979,6 +985,8 @@ complex_mul_pattern::matches (complex_operation_t op,
if (left_op.length () != 2
|| right_op.length () != 2
+ || !mul0
+ || !mul1
|| linear_loads_p (perm_cache, left_op[1]) == PERM_ODDEVEN)
return IFN_LAST;
@@ -993,7 +1001,7 @@ complex_mul_pattern::matches (complex_operation_t op,
if (!vect_validate_multiplication (perm_cache, left_op, PERM_EVENEVEN)
|| vect_normalize_conj_loc (left_op))
return IFN_LAST;
- if (!mul0)
+ if (add0)
ifn = IFN_COMPLEX_FMA;
else
ifn = IFN_COMPLEX_MUL;
@@ -1005,7 +1013,7 @@ complex_mul_pattern::matches (complex_operation_t op,
false))
return IFN_LAST;
- if(!mul0)
+ if(add0)
ifn = IFN_COMPLEX_FMA_CONJ;
else
ifn = IFN_COMPLEX_MUL_CONJ;
@@ -1204,7 +1212,9 @@ complex_fms_pattern::matches (complex_operation_t op,
/* If these nodes don't have any children then they're
not ones we're interested in. */
- if (left_op.length () != 2 || right_op.length () != 2)
+ if (left_op.length () != 2
+ || right_op.length () != 2
+ || !vect_match_expression_p (l0node[1], MULT_EXPR))
return IFN_LAST;
bool is_neg = vect_normalize_conj_loc (left_op);
diff --git a/gcc/tree.c b/gcc/tree.c
index f2c829f..62d9d78 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4781,6 +4781,7 @@ stabilize_reference (tree ref)
TREE_READONLY (result) = TREE_READONLY (ref);
TREE_SIDE_EFFECTS (result) = TREE_SIDE_EFFECTS (ref);
TREE_THIS_VOLATILE (result) = TREE_THIS_VOLATILE (ref);
+ protected_set_expr_location (result, EXPR_LOCATION (ref));
return result;
}
diff --git a/gcc/varasm.c b/gcc/varasm.c
index 09316c6..8c7aba2 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -7625,6 +7625,8 @@ decl_binds_to_current_def_p (const_tree decl)
at link-time with an entirely different definition, provided that the
replacement has the same type. For example, functions declared
with __attribute__((weak)) on most systems are replaceable.
+ If SEMANTIC_INTERPOSITION_P is false allow interposition only on
+ symbols explicitly declared weak.
COMDAT functions are not replaceable, since all definitions of the
function must be equivalent. It is important that COMDAT functions
@@ -7632,12 +7634,12 @@ decl_binds_to_current_def_p (const_tree decl)
instantiations is not penalized. */
bool
-decl_replaceable_p (tree decl)
+decl_replaceable_p (tree decl, bool semantic_interposition_p)
{
gcc_assert (DECL_P (decl));
if (!TREE_PUBLIC (decl) || DECL_COMDAT (decl))
return false;
- if (!flag_semantic_interposition
+ if (!semantic_interposition_p
&& !DECL_WEAK (decl))
return false;
return !decl_binds_to_current_def_p (decl);
diff --git a/gcc/varasm.h b/gcc/varasm.h
index 442ca6a..4ab9dc5 100644
--- a/gcc/varasm.h
+++ b/gcc/varasm.h
@@ -38,7 +38,7 @@ extern void mark_decl_referenced (tree);
extern void notice_global_symbol (tree);
extern void set_user_assembler_name (tree, const char *);
extern void process_pending_assemble_externals (void);
-extern bool decl_replaceable_p (tree);
+extern bool decl_replaceable_p (tree, bool);
extern bool decl_binds_to_current_def_p (const_tree);
extern enum tls_model decl_default_tls_model (const_tree);
diff --git a/gcc/varpool.c b/gcc/varpool.c
index 4830df5..fd0d53b 100644
--- a/gcc/varpool.c
+++ b/gcc/varpool.c
@@ -372,7 +372,8 @@ varpool_node::ctor_useable_for_folding_p (void)
*/
if ((!DECL_INITIAL (real_node->decl)
|| (DECL_WEAK (decl) && !DECL_COMDAT (decl)))
- && (DECL_EXTERNAL (decl) || decl_replaceable_p (decl)))
+ && ((DECL_EXTERNAL (decl) && !in_other_partition)
+ || decl_replaceable_p (decl, semantic_interposition)))
return false;
/* Variables declared `const' with an initializer are considered
@@ -511,8 +512,8 @@ varpool_node::get_availability (symtab_node *ref)
/* If the variable can be overwritten, return OVERWRITABLE. Takes
care of at least one notable extension - the COMDAT variables
used to share template instantiations in C++. */
- if (decl_replaceable_p (decl)
- || DECL_EXTERNAL (decl))
+ if (decl_replaceable_p (decl, semantic_interposition)
+ || (DECL_EXTERNAL (decl) && !in_other_partition))
return AVAIL_INTERPOSABLE;
return AVAIL_AVAILABLE;
}
@@ -779,6 +780,7 @@ varpool_node::create_alias (tree alias, tree decl)
alias_node = varpool_node::get_create (alias);
alias_node->alias = true;
alias_node->definition = true;
+ alias_node->semantic_interposition = flag_semantic_interposition;
alias_node->alias_target = decl;
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (alias)) != NULL)
alias_node->weakref = alias_node->transparent_alias = true;