summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorAlexander Monakov <amonakov@ispras.ru>2016-11-09 16:58:17 +0300
committerAlexander Monakov <amonakov@ispras.ru>2016-11-09 16:58:17 +0300
commit333610c1ceadf0febb112e8f9a3f405d25a0345a (patch)
tree29ee0b1fc30f8a28e916e1c06f982933a73f4f2b /gcc
parent16ca0e4e4bc093bfb2c08b167ce1f2116e37758b (diff)
parent421721dfaaddd54b376a5ac48e15ce6c7704bde3 (diff)
downloadgcc-amonakov/gomp-nvptx.tar.gz
Merge remote-tracking branch 'origin/trunk' into gomp-nvptx-branch-merge-trunkamonakov/gomp-nvptx
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog1386
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in5
-rw-r--r--gcc/ada/ChangeLog10
-rw-r--r--gcc/ada/adaint.c1
-rw-r--r--gcc/ada/gcc-interface/misc.c1
-rw-r--r--gcc/alias.c17
-rw-r--r--gcc/asan.c315
-rw-r--r--gcc/asan.h69
-rw-r--r--gcc/c-family/ChangeLog38
-rw-r--r--gcc/c-family/c-cppbuiltin.c6
-rw-r--r--gcc/c-family/c-opts.c29
-rw-r--r--gcc/c-family/c-pretty-print.c13
-rw-r--r--gcc/c-family/c-warn.c9
-rw-r--r--gcc/c-family/c.opt13
-rw-r--r--gcc/c/ChangeLog6
-rw-r--r--gcc/c/c-decl.c43
-rw-r--r--gcc/ccmp.c21
-rw-r--r--gcc/cfgexpand.c18
-rw-r--r--gcc/cfgrtl.c8
-rw-r--r--gcc/cfgrtl.h2
-rw-r--r--gcc/combine.c96
-rw-r--r--gcc/common.opt30
-rw-r--r--gcc/compare-elim.c2
-rw-r--r--gcc/config.gcc29
-rw-r--r--gcc/config/aarch64/aarch64-simd.md20
-rw-r--r--gcc/config/aarch64/aarch64.c47
-rw-r--r--gcc/config/aarch64/aarch64.md51
-rw-r--r--gcc/config/aarch64/driver-aarch64.c44
-rw-r--r--gcc/config/aarch64/t-aarch642
-rw-r--r--gcc/config/alpha/alpha-passes.def2
-rw-r--r--gcc/config/alpha/alpha.c117
-rw-r--r--gcc/config/arc/arc.c8
-rw-r--r--gcc/config/arc/arc.h31
-rw-r--r--gcc/config/arc/arc.md35
-rw-r--r--gcc/config/arc/constraints.md3
-rw-r--r--gcc/config/arc/fpu.md6
-rw-r--r--gcc/config/arc/fpx.md26
-rw-r--r--gcc/config/arm/arm-arches.def4
-rw-r--r--gcc/config/arm/arm-c.c3
-rw-r--r--gcc/config/arm/arm-cores.def2
-rw-r--r--gcc/config/arm/arm-protos.h1
-rw-r--r--gcc/config/arm/arm-tables.opt6
-rw-r--r--gcc/config/arm/arm-tune.md11
-rw-r--r--gcc/config/arm/arm.c1301
-rw-r--r--gcc/config/arm/arm.h9
-rw-r--r--gcc/config/arm/arm.opt8
-rw-r--r--gcc/config/arm/arm_neon.h28
-rw-r--r--gcc/config/arm/arm_neon_builtins.def4
-rw-r--r--gcc/config/arm/bpabi.h8
-rw-r--r--gcc/config/arm/freebsd.h8
-rw-r--r--gcc/config/arm/linux-eabi.h6
-rw-r--r--gcc/config/arm/linux-elf.h2
-rw-r--r--gcc/config/arm/neon.md11
-rw-r--r--gcc/config/arm/symbian.h6
-rw-r--r--gcc/config/arm/unknown-elf.h4
-rw-r--r--gcc/config/bfin/bfin.c7
-rw-r--r--gcc/config/c6x/c6x.c9
-rw-r--r--gcc/config/frv/frv.c2
-rw-r--r--gcc/config/i386/i386.c128
-rw-r--r--gcc/config/ia64/ia64.c4
-rw-r--r--gcc/config/m32c/m32c.c4
-rw-r--r--gcc/config/m68k/m68k.md26
-rw-r--r--gcc/config/microblaze/linux.h1
-rw-r--r--gcc/config/mips/mips.c61
-rw-r--r--gcc/config/mn10300/mn10300.c2
-rw-r--r--gcc/config/nvptx/nvptx.c2
-rw-r--r--gcc/config/pa/pa.h16
-rw-r--r--gcc/config/pa/pa.md30
-rw-r--r--gcc/config/pa/pa64-hpux.h2
-rw-r--r--gcc/config/rl78/rl78.c18
-rw-r--r--gcc/config/rs6000/rs6000-protos.h5
-rw-r--r--gcc/config/rs6000/rs6000.c196
-rw-r--r--gcc/config/rs6000/rs6000.h36
-rw-r--r--gcc/config/rs6000/rs6000.md14
-rw-r--r--gcc/config/rs6000/vector.md10
-rw-r--r--gcc/config/rs6000/vsx.md145
-rw-r--r--gcc/config/rs6000/xcoff.h14
-rw-r--r--gcc/config/s390/s390.c7
-rw-r--r--gcc/config/sh/sh-mem.cc8
-rw-r--r--gcc/config/sh/sh.md18
-rw-r--r--gcc/config/sparc/sparc.c12
-rw-r--r--gcc/config/sparc/sparc.md28
-rw-r--r--gcc/config/spu/spu.h3
-rw-r--r--gcc/config/vax/vax.h2
-rw-r--r--gcc/config/xtensa/xtensa-protos.h1
-rw-r--r--gcc/config/xtensa/xtensa.c126
-rw-r--r--gcc/config/xtensa/xtensa.h6
-rw-r--r--gcc/config/xtensa/xtensa.md2
-rwxr-xr-xgcc/configure15
-rw-r--r--gcc/configure.ac16
-rw-r--r--gcc/cp/ChangeLog169
-rw-r--r--gcc/cp/call.c282
-rw-r--r--gcc/cp/class.c108
-rw-r--r--gcc/cp/constexpr.c4
-rw-r--r--gcc/cp/cp-objcp-common.c64
-rw-r--r--gcc/cp/cp-objcp-common.h8
-rw-r--r--gcc/cp/cp-tree.h34
-rw-r--r--gcc/cp/cvt.c77
-rw-r--r--gcc/cp/decl.c11
-rw-r--r--gcc/cp/error.c7
-rw-r--r--gcc/cp/init.c12
-rw-r--r--gcc/cp/lambda.c3
-rw-r--r--gcc/cp/mangle.c84
-rw-r--r--gcc/cp/method.c215
-rw-r--r--gcc/cp/name-lookup.c36
-rw-r--r--gcc/cp/optimize.c13
-rw-r--r--gcc/cp/parser.c45
-rw-r--r--gcc/cp/pt.c133
-rw-r--r--gcc/cp/rtti.c8
-rw-r--r--gcc/cp/tree.c51
-rw-r--r--gcc/cp/typeck.c58
-rw-r--r--gcc/cse.c4
-rw-r--r--gcc/dbgcnt.def1
-rw-r--r--gcc/defaults.h4
-rw-r--r--gcc/doc/invoke.texi100
-rw-r--r--gcc/doc/sourcebuild.texi15
-rw-r--r--gcc/doc/tm.texi34
-rw-r--r--gcc/doc/tm.texi.in8
-rw-r--r--gcc/dojump.c1
-rw-r--r--gcc/dse.c17
-rw-r--r--gcc/dwarf2asm.c2
-rw-r--r--gcc/dwarf2cfi.c51
-rw-r--r--gcc/dwarf2out.c2299
-rw-r--r--gcc/dwarf2out.h18
-rw-r--r--gcc/emit-rtl.c17
-rw-r--r--gcc/except.c2
-rw-r--r--gcc/expr.c33
-rw-r--r--gcc/expr.h3
-rw-r--r--gcc/final.c7
-rw-r--r--gcc/fold-const-call.c4
-rw-r--r--gcc/fold-const.c93
-rw-r--r--gcc/fortran/ChangeLog174
-rw-r--r--gcc/fortran/arith.c18
-rw-r--r--gcc/fortran/check.c121
-rw-r--r--gcc/fortran/class.c3
-rw-r--r--gcc/fortran/decl.c10
-rw-r--r--gcc/fortran/error.c20
-rw-r--r--gcc/fortran/expr.c54
-rw-r--r--gcc/fortran/frontend-passes.c6
-rw-r--r--gcc/fortran/gfortran.h2
-rw-r--r--gcc/fortran/gfortran.texi27
-rw-r--r--gcc/fortran/interface.c28
-rw-r--r--gcc/fortran/invoke.texi15
-rw-r--r--gcc/fortran/io.c50
-rw-r--r--gcc/fortran/ioparm.def1
-rw-r--r--gcc/fortran/iresolve.c8
-rw-r--r--gcc/fortran/lang.opt4
-rw-r--r--gcc/fortran/match.c6
-rw-r--r--gcc/fortran/parse.c4
-rw-r--r--gcc/fortran/primary.c58
-rw-r--r--gcc/fortran/resolve.c114
-rw-r--r--gcc/fortran/symbol.c2
-rw-r--r--gcc/fortran/trans-array.c8
-rw-r--r--gcc/fortran/trans-common.c4
-rw-r--r--gcc/fortran/trans-expr.c8
-rw-r--r--gcc/fortran/trans-io.c3
-rw-r--r--gcc/fortran/trans-stmt.c57
-rw-r--r--gcc/fortran/trans-types.c24
-rw-r--r--gcc/fwprop.c2
-rw-r--r--gcc/gimple-pretty-print.c6
-rw-r--r--gcc/gimple-ssa-store-merging.c369
-rw-r--r--gcc/gimple-ssa-strength-reduction.c233
-rw-r--r--gcc/gimple.c3
-rw-r--r--gcc/gimplify.c238
-rw-r--r--gcc/go/gofrontend/MERGE2
-rw-r--r--gcc/go/gofrontend/escape.cc63
-rw-r--r--gcc/go/gofrontend/expressions.cc700
-rw-r--r--gcc/go/gofrontend/expressions.h86
-rw-r--r--gcc/go/gofrontend/runtime.cc4
-rw-r--r--gcc/go/gofrontend/runtime.def24
-rw-r--r--gcc/incpath.c5
-rw-r--r--gcc/internal-fn.c151
-rw-r--r--gcc/internal-fn.def4
-rw-r--r--gcc/ipa-comdats.c2
-rw-r--r--gcc/ipa-cp.c59
-rw-r--r--gcc/ipa-prop.c94
-rw-r--r--gcc/ipa-prop.h1
-rw-r--r--gcc/ira.c135
-rw-r--r--gcc/jump.c4
-rw-r--r--gcc/langhooks-def.h5
-rw-r--r--gcc/langhooks.c9
-rw-r--r--gcc/langhooks.h6
-rw-r--r--gcc/loop-invariant.c18
-rw-r--r--gcc/lto/ChangeLog6
-rw-r--r--gcc/lto/lto.c4
-rw-r--r--gcc/match.pd12
-rw-r--r--gcc/optabs.c5
-rw-r--r--gcc/opts.c27
-rw-r--r--gcc/params.def6
-rw-r--r--gcc/params.h2
-rw-r--r--gcc/po/ChangeLog12
-rw-r--r--gcc/po/es.po1261
-rw-r--r--gcc/postreload.c4
-rw-r--r--gcc/print-rtl.c48
-rw-r--r--gcc/print-rtl.h1
-rw-r--r--gcc/profile.c14
-rw-r--r--gcc/reg-notes.def5
-rw-r--r--gcc/reload.c48
-rw-r--r--gcc/reload1.c19
-rw-r--r--gcc/reorg.c23
-rw-r--r--gcc/rtl-tests.c15
-rw-r--r--gcc/rtl.h5
-rw-r--r--gcc/rtlanal.c45
-rw-r--r--gcc/sanitizer.def6
-rw-r--r--gcc/sanopt.c3
-rw-r--r--gcc/sel-sched-ir.c12
-rw-r--r--gcc/selftest-rtl.h45
-rw-r--r--gcc/selftest-run-tests.c7
-rw-r--r--gcc/selftest.h1
-rw-r--r--gcc/target.def47
-rw-r--r--gcc/targhooks.c8
-rw-r--r--gcc/targhooks.h2
-rw-r--r--gcc/testsuite/ChangeLog606
-rw-r--r--gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c1
-rw-r--r--gcc/testsuite/c-c++-common/asan/inc.c3
-rw-r--r--gcc/testsuite/c-c++-common/asan/null-deref-1.c4
-rw-r--r--gcc/testsuite/c-c++-common/builtin-shuffle-1.c22
-rw-r--r--gcc/testsuite/g++.dg/asan/use-after-scope-1.C21
-rw-r--r--gcc/testsuite/g++.dg/asan/use-after-scope-2.C40
-rw-r--r--gcc/testsuite/g++.dg/asan/use-after-scope-3.C22
-rw-r--r--gcc/testsuite/g++.dg/asan/use-after-scope-4.C36
-rw-r--r--gcc/testsuite/g++.dg/asan/use-after-scope-types-1.C17
-rw-r--r--gcc/testsuite/g++.dg/asan/use-after-scope-types-2.C17
-rw-r--r--gcc/testsuite/g++.dg/asan/use-after-scope-types-3.C17
-rw-r--r--gcc/testsuite/g++.dg/asan/use-after-scope-types-4.C17
-rw-r--r--gcc/testsuite/g++.dg/asan/use-after-scope-types-5.C17
-rw-r--r--gcc/testsuite/g++.dg/asan/use-after-scope-types.h30
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/addressof3.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-inhctor1.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor11.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor11a.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor15.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor15a.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor22.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C1
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor3a.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/inh-ctor9.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr77948-1.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr77948-2.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr77948-3.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr77948-4.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr77948-5.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr77948-6.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/feat-cxx11.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C4
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp1y/pr67980.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor1.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C33
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor24.C27
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor25.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor26.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor27.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor28.C7
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor29.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor30.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor31.C15
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor32.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor33.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor34.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor35.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/inh-ctor35a.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/launder3.C38
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/launder4.C40
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/launder5.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/launder5.cc12
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/launder5.h16
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/launder6.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/launder6.cc14
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/launder6.h16
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type1.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type11.C3
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type12.C23
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type2.C10
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type3.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type4.C16
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type5.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type6.C13
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type7.C14
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type8.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/noexcept-type9.C18
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/using1.C23
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/constexpr-var-1.C2
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C27
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C9
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/ref-2.C4
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C56
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/ref-4.C11
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C17
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C17
-rw-r--r--gcc/testsuite/g++.dg/eh/spec2.C6
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon1.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/anon2.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/pragma-override1.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/visibility/pragma-override2.C2
-rw-r--r--gcc/testsuite/g++.dg/init/new15.C2
-rw-r--r--gcc/testsuite/g++.dg/ipa/inline-1.C2
-rw-r--r--gcc/testsuite/g++.dg/ipa/inline-2.C2
-rw-r--r--gcc/testsuite/g++.dg/ipa/pr78188.C20
-rw-r--r--gcc/testsuite/g++.dg/lto/20080908-1_0.C2
-rw-r--r--gcc/testsuite/g++.dg/opt/pr64411.C (renamed from gcc/testsuite/gcc.target/i386/pr64411.C)5
-rw-r--r--gcc/testsuite/g++.dg/opt/pr65105-4.C (renamed from gcc/testsuite/gcc.target/i386/pr65105-4.C)6
-rw-r--r--gcc/testsuite/g++.dg/opt/pr71529.C22
-rw-r--r--gcc/testsuite/g++.dg/pr78229.C24
-rw-r--r--gcc/testsuite/g++.dg/tc1/dr20.C2
-rw-r--r--gcc/testsuite/g++.dg/template/func2.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr77822.C30
-rw-r--r--gcc/testsuite/g++.dg/torture/pr77919-2.C10
-rw-r--r--gcc/testsuite/g++.dg/torture/pr78189.C41
-rw-r--r--gcc/testsuite/g++.dg/torture/pr78224.C51
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/inline-1.C2
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/inline-2.C2
-rw-r--r--gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-2.C66
-rw-r--r--gcc/testsuite/g++.dg/warn/Wshadow-compatible-local-1.C63
-rw-r--r--gcc/testsuite/g++.dg/warn/Wshadow-local-1.C35
-rw-r--r--gcc/testsuite/g++.dg/warn/Wshadow-local-2.C63
-rw-r--r--gcc/testsuite/g++.old-deja/g++.eh/spec7.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.law/except1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/vbase5.C2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20001226-1.c1
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr78162.c10
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/pr78170.c39
-rw-r--r--gcc/testsuite/gcc.dg/Wshadow-compatible-local-1.c36
-rw-r--r--gcc/testsuite/gcc.dg/Wshadow-local-1.c22
-rw-r--r--gcc/testsuite/gcc.dg/Wshadow-local-2.c49
-rw-r--r--gcc/testsuite/gcc.dg/Wshadow-local-3.c9
-rw-r--r--gcc/testsuite/gcc.dg/Wtrampolines.c2
-rw-r--r--gcc/testsuite/gcc.dg/addr_equal-1.c1
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-1.c18
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-2.c47
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-3.c20
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-4.c16
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-5.c27
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-6.c15
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-7.c15
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-9.c20
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-goto-1.c47
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-goto-2.c25
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-switch-1.c25
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-switch-2.c33
-rw-r--r--gcc/testsuite/gcc.dg/asan/use-after-scope-switch-3.c36
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/include.c10
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/trad.exp2
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/pr71855.c2
-rw-r--r--gcc/testsuite/gcc.dg/debug/dwarf2/prod-options.c2
-rw-r--r--gcc/testsuite/gcc.dg/divmod-1-simode.c25
-rw-r--r--gcc/testsuite/gcc.dg/divmod-1.c32
-rw-r--r--gcc/testsuite/gcc.dg/divmod-2-simode.c25
-rw-r--r--gcc/testsuite/gcc.dg/divmod-2.c32
-rw-r--r--gcc/testsuite/gcc.dg/divmod-3-simode.c23
-rw-r--r--gcc/testsuite/gcc.dg/divmod-3.c30
-rw-r--r--gcc/testsuite/gcc.dg/divmod-4-simode.c23
-rw-r--r--gcc/testsuite/gcc.dg/divmod-4.c30
-rw-r--r--gcc/testsuite/gcc.dg/divmod-5.c19
-rw-r--r--gcc/testsuite/gcc.dg/divmod-6-simode.c26
-rw-r--r--gcc/testsuite/gcc.dg/divmod-6.c33
-rw-r--r--gcc/testsuite/gcc.dg/divmod-7.c21
-rw-r--r--gcc/testsuite/gcc.dg/ipa/pr78121.c16
-rw-r--r--gcc/testsuite/gcc.dg/ipa/vrp7.c32
-rw-r--r--gcc/testsuite/gcc.dg/lto/pr60449_0.c1
-rw-r--r--gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr35691-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr35691-2.c12
-rw-r--r--gcc/testsuite/gcc.dg/pr65779.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr70405.c1
-rw-r--r--gcc/testsuite/gcc.dg/pr77834.c18
-rw-r--r--gcc/testsuite/gcc.dg/pr77860.c13
-rw-r--r--gcc/testsuite/gcc.dg/pr78148.c31
-rw-r--r--gcc/testsuite/gcc.dg/pr78185.c28
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_1.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_2.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_4.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_5.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_6.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_7.c2
-rw-r--r--gcc/testsuite/gcc.dg/store_merging_8.c38
-rw-r--r--gcc/testsuite/gcc.dg/torture/fp-int-convert.h3
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr77309.c14
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr78218.c24
-rw-r--r--gcc/testsuite/gcc.dg/tree-prof/time-profiler-3.c22
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-ub.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c12
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr20702.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr21086.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr54245.c48
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr58480.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr71347.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c16
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp08.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/vrp111.c13
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-pr78205.c25
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr56541.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bswap32.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-bswap64.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-cond-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-nb-iter-ub-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/visibility-14.c2
-rw-r--r--gcc/testsuite/gcc.dg/visibility-15.c2
-rw-r--r--gcc/testsuite/gcc.dg/visibility-16.c2
-rw-r--r--gcc/testsuite/gcc.dg/visibility-17.c2
-rw-r--r--gcc/testsuite/gcc.dg/visibility-18.c2
-rw-r--r--gcc/testsuite/gcc.dg/visibility-19.c2
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vmaxnm_f32_1.c159
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vmaxnmq_f32_1.c160
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vminnm_f32_1.c159
-rw-r--r--gcc/testsuite/gcc.target/arm/simd/vminnmq_f32_1.c159
-rw-r--r--gcc/testsuite/gcc.target/i386/pr70799-2.c17
-rw-r--r--gcc/testsuite/gcc.target/i386/pr71529.C22
-rw-r--r--gcc/testsuite/gcc.target/i386/pr78035.c24
-rw-r--r--gcc/testsuite/gcc.target/i386/pr78227-1.c30
-rw-r--r--gcc/testsuite/gcc.target/i386/pr78227-2.c30
-rw-r--r--gcc/testsuite/gcc.target/mips/mips.exp4
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-add-1.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-add-2.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-add-3.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-add-4.c46
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-add-5.c16
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-add-6.c23
-rw-r--r--gcc/testsuite/gcc.target/powerpc/fold-vec-add-7.c23
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-extract-4.c76
-rw-r--r--gcc/testsuite/gcc.target/powerpc/vsx-extract-5.c77
-rw-r--r--gcc/testsuite/gcc.target/sparc/overflow-3.c15
-rw-r--r--gcc/testsuite/gcc.target/sparc/overflow-4.c44
-rw-r--r--gcc/testsuite/gcc.target/sparc/overflow-5.c43
-rw-r--r--gcc/testsuite/gfortran.dg/allocate_with_source_14.f032
-rw-r--r--gcc/testsuite/gfortran.dg/associate_23.f9036
-rw-r--r--gcc/testsuite/gfortran.dg/class_58.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/class_59.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/dec_exp_1.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/dec_exp_2.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/dec_exp_3.f9015
-rw-r--r--gcc/testsuite/gfortran.dg/dec_parameter_1.f64
-rw-r--r--gcc/testsuite/gfortran.dg/dec_parameter_2.f9063
-rw-r--r--gcc/testsuite/gfortran.dg/dec_parameter_3.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/dec_parameter_4.f9013
-rw-r--r--gcc/testsuite/gfortran.dg/elemental_optional_args_6.f901
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_l.f9032
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_l0.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/fmt_t_9.f41
-rw-r--r--gcc/testsuite/gfortran.dg/implicit_class_1.f901
-rw-r--r--gcc/testsuite/gfortran.dg/move_alloc_17.f9021
-rw-r--r--gcc/testsuite/gfortran.dg/move_alloc_18.f9021
-rw-r--r--gcc/testsuite/gfortran.dg/pr67219.f908
-rw-r--r--gcc/testsuite/gfortran.dg/pr70937.f901
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_comp_46.f9029
-rw-r--r--gcc/testsuite/gfortran.dg/select_type_39.f0320
-rw-r--r--gcc/testsuite/gfortran.dg/warn_argument_mismatch_1.f9034
-rw-r--r--gcc/testsuite/gfortran.dg/warn_conversion_9.f907
-rw-r--r--gcc/testsuite/gfortran.dg/where_5.f9015
-rw-r--r--gcc/testsuite/gfortran.dg/where_6.f9015
-rw-r--r--gcc/testsuite/lib/scanasm.exp1
-rw-r--r--gcc/testsuite/lib/target-supports.exp398
-rw-r--r--gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm2
-rw-r--r--gcc/tree-call-cdce.c13
-rw-r--r--gcc/tree-inline.c33
-rw-r--r--gcc/tree-profile.c107
-rw-r--r--gcc/tree-ssa-alias.c17
-rw-r--r--gcc/tree-ssa-alias.h2
-rw-r--r--gcc/tree-ssa-loop-im.c13
-rw-r--r--gcc/tree-ssa-math-opts.c221
-rw-r--r--gcc/tree-ssa-phiopt.c8
-rw-r--r--gcc/tree-ssa-reassoc.c2
-rw-r--r--gcc/tree-ssa-structalias.c14
-rw-r--r--gcc/tree-vect-data-refs.c63
-rw-r--r--gcc/tree-vect-loop.c85
-rw-r--r--gcc/tree-vect-slp.c203
-rw-r--r--gcc/tree-vect-stmts.c148
-rw-r--r--gcc/tree-vectorizer.h2
-rw-r--r--gcc/tree-vrp.c122
-rw-r--r--gcc/tree.c29
-rw-r--r--gcc/tree.h9
-rw-r--r--gcc/value-prof.h5
476 files changed, 15799 insertions, 4961 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 3f2ea4dfc71..cfdf5a5569f 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,1373 @@
+2016-11-09 Richard Biener <rguenther@suse.de>
+
+ * common.opt (flag_evaluation_order): Remove.
+ * expr.c (expand_operands): Remove code guarded by
+ flag_evaluation_order.
+ * fold-const.c (reorder_operands_p): Remove, it always returns
+ true.
+ (negate_expr_p): Remove calls to reorder_operands_p.
+ (fold_negate_expr): Likewise.
+ (tree_swap_operands_p): Likewise.
+ (fold_binary_loc): Likewise.
+
+2016-11-09 Andreas Schwab <schwab@suse.de>
+
+ PR target/78254
+ * config/m68k/m68k.md: Reject out-of-range bit pos in bit-fields
+ insns operating on a register.
+
+2016-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78007
+ * tree-vect-stmts.c (vectorizable_bswap): New function.
+ (vectorizable_call): Call vectorizable_bswap for
+ BUILT_IN_BSWAP{16,32,64} if arguments are not promoted.
+
+2016-11-09 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_compute_data_ref_alignment):
+ Look at the DR_BASE_ADDRESS object for forcing alignment.
+
+2016-11-09 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * ipa-cp.c (ipa_get_jf_pass_through_result): Handle unary expressions.
+ (propagate_vr_accross_jump_function): Likewise.
+ * ipa-prop.c (ipa_set_jf_unary_pass_through): New.
+ (load_from_param_1): New.
+ (load_from_unmodified_param): Factor common part into load_from_param_1.
+ (load_from_param): New.
+ (compute_complex_assign_jump_func): Handle unary expressions.
+ (ipa_write_jump_function): Likewise.
+ (ipa_read_jump_function): Likewise.
+
+2016-11-09 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ PR ipa/78121
+ * ipa-cp.c (propagate_vr_accross_jump_function): Pass param type.
+ Also fold constant passed as argument while computing value range.
+ (propagate_constants_accross_call): Pass param type.
+ * ipa-prop.c: export ipa_get_callee_param_type.
+ * ipa-prop.h: export ipa_get_callee_param_type.
+
+2016-11-09 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * asan.h (asan_intercepted_p): Handle BUILT_IN_STRCSPN,
+ BUILT_IN_STRPBRK, BUILT_IN_STRSPN and BUILT_IN_STRSTR.
+
+2016-11-09 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * asan.h (ASAN_STACK_MAGIC_PARTIAL): Remove.
+ * asan.c (ASAN_STACK_MAGIC_PARTIAL): Replace with
+ ASAN_STACK_MAGIC_MIDDLE.
+ (asan_global_struct): Increase the size of fields.
+ (asan_add_global): Add new field constructor.
+ * sanitizer.def (__asan_version_mismatch_check_v6): Replace with
+ __asan_version_mismatch_check_v8.
+
+ 2016-11-08 David Edelsohn <dje.gcc@gmail.com>
+
+ * dwarf2asm.c (USE_LINKONCE_INDIRECT): Test XCOFF_DEBUGGING_INFO
+ at runtime.
+
+2016-11-08 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/70799
+ * config/i386/i386.c (dimode_scalar_to_vector_candidate_p):
+ Handle ASHIFT and LSHIFTRT.
+ (dimode_scalar_chain::compute_convert_gain): Ditto.
+ (dimode_scalar_chain::convert_insn): Ditto.
+
+2016-11-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gimple-ssa-store-merging.c: Include selftest.h
+ (verify_array_eq): New function.
+ (verify_shift_bytes_in_array): Likewise.
+ (verify_shift_bytes_in_array_right): Likewise.
+ (verify_clear_bit_region): Likewise.
+ (verify_clear_bit_region_be): Likewise.
+ (store_merging_c_tests): Likewise.
+ * selftest.h (store_merging_c_tests): Declare prototype.
+ * selftest-run-tests.c (selftest::run_tests): Run
+ store_merging_c_tests.
+
+2016-11-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.opt (mold-rtx-costs): Delete.
+ (mnew-generic-costs): Delete.
+ * config/arm/arm-protos.h (struct tune_params): Delete rtx_costs field.
+ * config/arm/arm.c (arm_rtx_costs_1): Delete.
+ (arm_size_rtx_costs): Likewise.
+ (arm_slowmul_rtx_costs): Likewise.
+ (arm_fastmul_rtx_costs): Likewise.
+ (arm_xscale_rtx_costs): Likewise.
+ (arm_9e_rtx_costs): Likewise.
+ (arm_slowmul_tune, arm_fastmul_tune, arm_strongarm_tune,
+ arm_xscale_tune, arm_9e_tune, arm_v6t2_tune, arm_cortex_tune,
+ arm_cortex_a8_tune, arm_cortex_a7_tune, arm_cortex_a15_tune,
+ arm_cortex_a53_tune, arm_cortex_a57_tune, arm_cortex_a9_tune,
+ arm_cortex_a12_tune, arm_v7m_tune, arm_v6m_tune, arm_fa726te_tune
+ arm_cortex_a5_tune, arm_xgene1_tune, arm_marvell_pj4_tune,
+ arm_cortex_a35_tune, arm_exynosm1_tune, arm_cortex_a73_tune,
+ arm_cortex_m7_tune):
+ Delete rtx_costs field.
+ (arm_new_rtx_costs): Rename to...
+ (arm_rtx_costs_internal): ... This.
+ (arm_rtx_costs): Remove old way of doing rtx costs.
+
+2016-11-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/arm/arm.c (arm_slowmul_tune): Use generic_extra_costs.
+ (arm_fastmul_tune): Likewise.
+ (arm_strongarm_tune): Likewise.
+ (arm_xscale_tune): Likewise.
+ (arm_9e_tune): Likewise.
+ (arm_marvell_pj4_tune): Likewise.
+ (arm_v6t2_tune): Likewise.
+ (arm_v6m_tune): Likewise.
+ (arm_fa726te_tune): Likewise.
+
+2016-11-08 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/78234
+ * gimple-ssa-store-merging.c (clear_bit_region): Fix off-by-one error
+ in start != 0 case.
+
+2016-11-08 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/78242
+ * dbgcnt.def: Add new debug counter asan_use_after_scope.
+ * gimplify.c (gimplify_decl_expr): Do not sanitize vars
+ with a value expr. Do not add artificial variables to
+ live_switch_vars. Use the debug counter.
+ (gimplify_target_expr): Use the debug counter.
+ * internal-fn.def: Remove ECF_TM_PURE from ASAN_MARK builtin.
+ * sanitizer.def: Set ATTR_NOTHROW_LEAF_LIST to
+ BUILT_IN_ASAN_CLOBBER_N and BUILT_IN_ASAN_UNCLOBBER_N.
+
+2016-11-08 Richard Biener <rguenther@suse.de>
+
+ * tree-vect-stmts.c (get_group_load_store_type): If the
+ access is aligned do not trigger peeling for gaps.
+ * tree-vect-data-refs.c (vect_compute_data_ref_alignment): Do not
+ force alignment of vars with DECL_USER_ALIGN.
+
+2016-11-08 James Greenhalgh <james.greenhalgh@arm.com>
+
+ * config/aarch64/t-aarch64 (aarch64-c.o): Depend on TARGET_H.
+
+2016-11-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78205
+ * tree-vect-stmts.c (vectorizable_load): Move check whether
+ we may run into gaps when BB vectorizing SLP permutations ...
+ * tree-vect-slp.c (vect_supported_load_permutation_p): ...
+ here where we can do a more precise check.
+
+2016-11-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78224
+ * tree-call-cdce.c (shrink_wrap_one_built_in_call_with_conds):
+ Split the fallthru edge in case its successor may have PHIs.
+ Do not free dominance info.
+
+2016-11-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/78229
+ * config/i386/i386.c (ix86_gimple_fold_builtin): Do not adjust
+ EH info even for bzhi and pdep/pext.
+
+2016-11-07 Peter Bergner <bergner@vnet.ibm.com>
+
+ * config.gcc (powerpc*-*-*, rs6000*-*-*): Remove setting of
+ INCLUDE_EXTRA_SPEC for Advance Toolchain builds.
+
+2016-11-07 Segher Boessenkool <segher@kernel.crashing.org>
+
+ * config/rs6000/rs6000.md (div<mode>3): Expand using rs6000_emit_swdiv
+ if appropriate.
+ * config/rs6000/vector.md (div<mode>3): Ditto.
+
+2016-11-07 David Edelsohn <dje.gcc@gmail.com>
+
+ * configure.ac (.hidden): Change to conftest_s string. Provide string
+ for AIX assembler.
+ (gcc_cv_ld_hidden): Yes for AIX.
+ * configure: Regenerate.
+
+ * dwarf2asm.c (USE_LINKONCE_INDIRECT): Don't set for AIX (XCOFF).
+
+ * config/rs6000/rs6000-protos.h (rs6000_asm_weaken_decl): Declare
+ (rs6000_xcoff_asm_output_aligned_decl_common): Declare.
+ * config/rs6000/xcoff.h (TARGET_ASM_GLOBALIZE_DECL_NAME): Define.
+ (ASM_OUTPUT_ALIGNED_DECL_COMMON): Define.
+ (ASM_OUTPUT_ALIGNED_COMMON): Delete.
+ * config/rs6000/rs6000.c (rs6000_init_builtins): Change clog rename
+ from #if to if.
+ (rs6000_xcoff_visibility): New.
+ (rs6000_xcoff_declare_function_name): Add visibility support.
+ (rs6000_xcoff_asm_globalize_decl_name): New.
+ (rs6000_xcoff_asm_output_aligned_decl_common): New.
+ (rs6000_asm_weaken_decl): New.
+ (rs6000_code_end): Disable HIDDEN_LINKONCE on XCOFF.
+ config/rs6000/rs6000.h (ASM_WEAKEN_DECL): Change definition to
+ reference function.
+
+2016-11-07 Jack Howarth <howarth.at.gcc@gmail.com>
+
+ PR driver/78206
+ * incpath.c: (remove_dup(): Also silently ignore EPERM.
+
+2016-11-07 Martin Jambor <mjambor@suse.cz>
+
+ * tree.c (verify_type_variant): Use pointer comparison to check that
+ TYPE_SIZE_UNIT match.
+
+2016-11-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/77834
+ * dse.c (dse_step5): Call scan_reads even if just
+ insn_info->frame_read. Improve and fix dump file messages.
+
+ PR target/78227
+ * config/i386/i386.c (ix86_expand_sse_cmp): Force dest into
+ cmp_mode argument even for -O0 if cmp_mode != mode and maskcmp.
+
+2016-11-07 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR middle-end/35691
+ * match.pd: Add following two patterns:
+ (x == 0 & y == 0) -> (x | typeof(x)(y)) == 0.
+ (x != 0 | y != 0) -> (x | typeof(x)(y)) != 0.
+
+2016-11-07 Bernd Schmidt <bschmidt@redhat.com>
+
+ * emit-rtl.c (emit_copy_of_insn_after): Duplicate notes in order.
+ * sel-sched-ir.c (create_copy_of_insn_rtx): Likewise.
+ * rtl.h (duplicate_reg_notes): Declare.
+ * rtlanal.c (duplicate_reg_note): New function.
+
+ PR rtl-optimization/77309
+ * combine.c (make_compound_operation): Allow EQ for IN_CODE, and
+ don't assume an equality comparison for plain COMPARE.
+ (simplify_comparison): Pass a more accurate code to
+ make_compound_operation.
+
+2016-11-07 Pat Haugen <pthaugen@us.ibm.com>
+
+ * target.def (compute_pressure_classes): New target hook.
+ * doc/tm.texi.in: Document it.
+ * doc/tm.texi: Regenerate.
+ * ira.c (setup_pressure_classes): Call target hook if defined.
+
+2016-11-07 David Malcolm <dmalcolm@redhat.com>
+
+ * print-rtl.c (rtx_writer::operand_has_default_value_p): New
+ method.
+ (rtx_writer::print_rtx): In compact mode, omit trailing operands
+ that have the default values.
+ * print-rtl.h (rtx_writer::operand_has_default_value_p): New
+ method.
+ * rtl-tests.c (selftest::test_dumping_insns): Remove empty
+ label string from expected dump.
+ (seltest::test_uncond_jump): Remove trailing "(nil)" for REG_NOTES
+ from expected dump.
+
+2016-11-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/77834
+ * alias.c (nonoverlapping_memrefs_p): If one decl is
+ FUNCTION_DECL or LABEL_DECL and the other is not, return 1.
+
+2016-11-07 Richard Biener <rguenther@suse.de>
+
+ PR target/78229
+ * config/i386/i386.c (ix86_gimple_fold_builtin): Do not adjust
+ EH info.
+
+2016-11-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78218
+ * gimple-ssa-store-merging.c
+ (pass_store_merging::terminate_all_aliasing_chains):
+ Drop unused argument, fix alias check to also consider uses.
+ (pass_store_merging::execute): Adjust.
+
+2016-11-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78228
+ * tree-ssa-phiopt.c (abs_replacement): Avoid introducing
+ undefined behavior.
+
+2016-11-07 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/77822
+ * config/aarch64/aarch64.md (*tb<optab><mode>1): Use
+ aarch64_simd_shift_imm_<mode> predicate for operand 1.
+ (<optab>, ANY_EXTRACT): Use tighter predicates on operands 2 and 3
+ to restrict them to an appropriate range and add FAIL check if the
+ region they specify is out of range. Delete useless constraint
+ strings.
+ (*<optab><mode>, ANY_EXTRACT): Add appropriate predicates on operands
+ 2 and 3 to restrict their range and add pattern predicate.
+
+2016-11-07 Martin Liska <mliska@suse.cz>
+
+ * asan.c (enum asan_check_flags): Move the enum to header file.
+ (asan_init_shadow_ptr_types): Make type creation more generic.
+ (shadow_mem_size): New function.
+ (asan_emit_stack_protection): Use newly added ASAN_SHADOW_GRANULARITY.
+ Rewritten stack unpoisoning code.
+ (build_shadow_mem_access): Add new argument return_address.
+ (instrument_derefs): Instrument local variables if use after scope
+ sanitization is enabled.
+ (asan_store_shadow_bytes): New function.
+ (asan_expand_mark_ifn): Likewise.
+ (asan_sanitize_stack_p): Moved from asan_sanitize_stack_p.
+ * asan.h (enum asan_mark_flags): Moved here from asan.c
+ (asan_protect_stack_decl): Protect all declaration that need
+ to live in memory.
+ (asan_sanitize_use_after_scope): New function.
+ (asan_no_sanitize_address_p): Likewise.
+ * cfgexpand.c (partition_stack_vars): Consider
+ asan_sanitize_use_after_scope in condition.
+ (expand_stack_vars): Likewise.
+ * common.opt (-fsanitize-address-use-after-scope): New option.
+ * doc/invoke.texi (use-after-scope-direct-emission-threshold):
+ Explain the parameter.
+ * flag-types.h (enum sanitize_code): Define SANITIZE_USE_AFTER_SCOPE.
+ * gimplify.c (build_asan_poison_call_expr): New function.
+ (asan_poison_variable): Likewise.
+ (gimplify_bind_expr): Generate poisoning/unpoisoning for local
+ variables that have address taken.
+ (gimplify_decl_expr): Likewise.
+ (gimplify_target_expr): Likewise for C++ temporaries.
+ (sort_by_decl_uid): New function.
+ (gimplify_expr): Unpoison all variables for a label we can jump
+ from outside of a scope.
+ (gimplify_switch_expr): Unpoison variables defined in the switch
+ context.
+ (gimplify_function_tree): Clear asan_poisoned_variables.
+ (asan_poison_variables): New function.
+ (warn_switch_unreachable_r): Handle IFN_ASAN_MARK.
+ * internal-fn.c (expand_ASAN_MARK): New function.
+ * internal-fn.def (ASAN_MARK): Declare.
+ * opts.c (finish_options): Handle -fstack-reuse if
+ -fsanitize-address-use-after-scope is enabled.
+ (common_handle_option): Enable address sanitization if
+ -fsanitize-address-use-after-scope is enabled.
+ * params.def (PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD):
+ New parameter.
+ * params.h: Likewise.
+ * sancov.c (pass_sanopt::execute): Handle IFN_ASAN_MARK.
+ * sanitizer.def: Define __asan_poison_stack_memory and
+ __asan_unpoison_stack_memory functions.
+ * asan.c (asan_mark_poison_p): New function.
+ (transform_statements): Handle asan_mark_poison_p calls.
+ * gimple.c (nonfreeing_call_p): Handle IFN_ASAN_MARK.
+
+2016-11-07 Tamar Christina <tamar.christina@arm.com>
+
+ PR driver/78196
+ * Makefile.in (SELFTEST_FLAGS): Added -o /dev/null.
+
+2016-11-07 Martin Liska <mliska@suse.cz>
+
+ * tree-profile.c (gimple_gen_time_profiler): Set proper type
+ to time_profiler_counter_ptr.
+
+2016-11-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/37150
+ * tree-vectorizer.h (vect_transform_slp_perm_load): Add n_perms
+ parameter.
+ * tree-vect-slp.c (vect_supported_load_permutation_p): Adjust.
+ (vect_analyze_slp_cost_1): Account for the real number of
+ permutations emitted and for dead loads.
+ (vect_transform_slp_perm_load): Add n_perms parameter counting
+ the number of emitted permutations.
+ * tree-vect-stmts.c (vectorizable_load): Adjust.
+
+2016-11-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78189
+ * tree-vect-data-refs.c (vect_compute_data_ref_alignment): Fix
+ alignment computation.
+
+2016-11-06 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * ipa-cp.c (ipcp_bits_lattice::meet_with): Remove unreachable code.
+
+2016-11-05 Martin Sebor <msebor@redhat.com>
+
+ * doc/invoke.texi (Warning Options): Correct typos in -Walloca
+ documentation.
+
+2016-11-05 David Edelsohn <dje.gcc@gmail.com>
+
+ PR bootstrap/78188
+ PR c++/71848
+ * ipa-comdats.c (pass_ipa_comdats::gate): Require HAVE_COMDAT_GROUP.
+
+2016-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/77834
+ * alias.c (nonoverlapping_memrefs_p): Return 0 if exprx or expry
+ doesn't have rtl set.
+
+2016-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (gimple-ssa.h): New #include.
+ (TARGET_GIMPLE_FOLD_BUILTIN): Define as
+ rs6000_gimple_fold_builtin.
+ (rs6000_gimple_fold_builtin): New function. Add handling for
+ early expansion of vector addition builtins.
+
+2016-11-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * expr.h (copy_blkmode_from_reg): Delete.
+ * expr.c (copy_blkmode_from_reg): Make static.
+
+2016-11-04 Eric Botcazou <ebotcazou@adacore.com>
+
+ * defaults.h (LOAD_EXTEND_OP): Define if not already defined.
+ * combine.c (LOAD_EXTEND_OP): Delete.
+ (simplify_comparison): Fix comment about LOAD_EXTEND_OP.
+ * cse.c (LOAD_EXTEND_OP): Delete.
+ * fold-const.c (LOAD_EXTEND_OP): Likewise.
+ * fwprop.c (free_load_extend): Remove #ifdef LOAD_EXTEND_OP/#endif.
+ * postreload.c (LOAD_EXTEND_OP): Delete.
+ * reload.c (push_reload): Remove #ifdef LOAD_EXTEND_OP/#endif.
+ Convert conditional compilation based on WORD_REGISTER_OPERATIONS.
+ (find_reloads): Likewise.
+ * reload1.c (eliminate_regs_1): Likewise.
+ * rtlanal.c (nonzero_bits1): Remove #ifdef LOAD_EXTEND_OP/#endif.
+ (num_sign_bit_copies1): Likewise.
+
+2016-11-04 David Malcolm <dmalcolm@redhat.com>
+
+ * config/i386/i386.c: Include "selftest.h" and "selftest-rtl.h".
+ (selftest::ix86_test_dumping_hard_regs): New function.
+ (selftest::ix86_run_selftests): New function.
+ (TARGET_RUN_TARGET_SELFTESTS): When CHECKING_P, wire this up to
+ selftest::ix86_run_selftests.
+ * doc/tm.texi.in (TARGET_RUN_TARGET_SELFTESTS): New.
+ * doc/tm.texi: Regenerate
+ * selftest-rtl.h: New file.
+ * rtl-tests.c: Include "selftest-rtl.h".
+ (selftest::assert_rtl_dump_eq): Make non-static.
+ (ASSERT_RTL_DUMP_EQ): Move to selftest-rtl.h.
+ (selftest::test_dumping_regs): Update comment.
+ * selftest-run-tests.c: Include "target.h".
+ (selftest::run_tests): If non-NULL, call
+ targetm.run_target_selftests.
+ * target.def (run_target_selftests): New hook.
+
+2016-11-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * config/arm/arm-arches.def (armv8-m.main+dsp): Set Cortex-M33 as
+ representative core for this architecture.
+ * config/arm/arm-cores.def (cortex-m33): Define new processor.
+ * config/arm/arm-tables.opt: Regenerate.
+ * config/arm/arm-tune.md: Likewise.
+ * config/arm/bpabi.h (BE8_LINK_SPEC): Add Cortex-M33 to the list of
+ valid -mcpu options.
+ * doc/invoke.texi (ARM Options): Document new Cortex-M33 processor.
+
+2016-11-04 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ * config/arm/arm-arches.def (armv8-m.base): Set Cortex-M23 as
+ representative core for this architecture.
+ * config/arm/arm-cores.def (cortex-m23): Define new processor.
+ * config/arm/arm-tables.opt: Regenerate.
+ * config/arm/arm-tune.md: Likewise.
+ * config/arm/arm.c (arm_v6m_tune): Add Cortex-M23 to the list of cores
+ this tuning parameters apply to in the comment.
+ * config/arm/bpabi.h (BE8_LINK_SPEC): Add Cortex-M23 to the list of
+ valid -mcpu options.
+ * doc/invoke.texi (ARM Options): Document new Cortex-M23 processor.
+
+2016-11-04 Bin Cheng <bin.cheng@arm.com>
+
+ * fold-const.c (fold_cond_expr_with_comparison): Remove call
+ to pedantic_non_lvalue_loc. Remove useless code for lvalue
+ where cond_expr can't be a lvalue.
+
+2016-11-04 Claudiu Zissulescu <claziss@synopsys.com>
+
+ * config/arc/arc.c (arc_process_double_reg_moves): Use
+ gen_dexcl_2op call.
+ * config/arc/arc.md (movsi_insn): Disable unsupported move
+ instructions for ARCv2 cores.
+ (movdi): Use prepare_move_operands.
+ (movsf, movdf): Use move_dest_operand predicate.
+ * config/arc/constraints.md (Chs): Enable when barrel shifter is
+ present.
+ * config/arc/fpu.md (divsf3): Change to divsf3_fpu.
+ * config/arc/fpx.md (dexcl_3op_peep2_insn): Dx data register is
+ also a destination.
+ (dexcl_3op_peep2_insn_nores): Likewise.
+ * config/arc/arc.h (SHIFT_COUNT_TRUNCATED): Define to one.
+ (LINK_COMMAND_SPEC): Remove.
+
+2016-11-04 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/78185
+ * loop-invariant.c (find_exits): Record entering inner
+ loops as possibly exiting to handle infinite sub-loops.
+ * tree-ssa-loop-im.c: Include tree-ssa-loop-niter.h.
+ (fill_always_executed_in_1): Honor infinite child loops.
+
+2016-11-03 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR target/78192
+ * config/rs6000/vsx.md (vsx_extract_<mode>_di): The element number
+ has already been adjusted for endianness, so don't adjust it any
+ further.
+
+ PR target/77993
+ * config/rs6000/rs6000.h (FLOAT128_IBM_P): Do not allow IFmode or
+ ICmode unless we have standard PowerPC floating point.
+ * config/rs6000/rs6000.md (FP iterator): Likewise.
+ (FMOVE128 iterator): Likewise.
+
+2016-11-03 Jakub Jelinek <jakub@redhat.com>
+ Alexandre Oliva <aoliva@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR debug/28767
+ PR debug/56974
+ * langhooks.h (struct lang_hooks_for_types): Add type_dwarf_attribute
+ langhook.
+ * langhooks.c (lhd_type_dwarf_attribute): New function.
+ * langhooks-def.h (lhd_type_dwarf_attribute): Declare.
+ (LANG_HOOKS_TYPE_DWARF_ATTRIBUTE): Define.
+ (LANG_HOOKS_FOR_TYPES_INITIALIZER): Add
+ LANG_HOOKS_TYPE_DWARF_ATTRIBUTE.
+ (check_qualified_type, check_aligned_type): Call it.
+ * dwarf2out.c (modified_type_die): Don't use type_main_variant
+ for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
+ check_base_type and check_lang_type.
+ (gen_ptr_to_mbr_type_die): If lookup_type_die is already non-NULL,
+ return early. For pointer-to-data-member add DW_AT_use_location
+ attribute.
+ (gen_subroutine_type_die): Add DW_AT_{,rvalue_}reference attribute
+ if needed.
+ (gen_type_die_with_usage): Don't use type_main_variant
+ for FUNCTION_TYPE or METHOD_TYPE, instead walk over variants with
+ check_base_type and check_lang_type. Formatting fixes. Call
+ get_debug_type langhook.
+
+2016-11-03 Jason Merrill <jason@redhat.com>
+
+ * tree.c (check_lang_type): New.
+ (check_qualified_type): Use it.
+ (check_aligned_type): Use it.
+ * tree.h: Declare it.
+
+2016-11-03 Richard Earnshaw <rearnsha@arm.com>
+
+ * config.gcc (arm-wrs-vxworks): Set target_cpu_cname.
+ (arm*-freebsd*): Likewise.
+ (arm*-*-netbsdelf*): Likewise.
+ (arm*-*-linux*): Likewise.
+ (arm*-*-uclinux*eabi*): Likewise.
+ (arm*-*-phoenix*): Likewise.
+ (arm*-*-eabi*, arm*-*-symbianelf*, arm*-*-rtems*): Likewise.
+ (arm*-*-*): Don't clobber target_cpu_cname when --with-cpu is not
+ specified. Default to arm6 if target_cpu_cname is not set.
+ * arm/arm.c (arm_option_override): Simplify logic. Assert that the
+ default cpu has been correctly configured.
+ * arm/arm.h (TARGET_CPU_DEFAULT): Delete.
+ (target_cpus): Delete TARGET_CPU_generic, add TARGET_CPU_num_cores.
+ * arm/freebsd.h (SUBTARGET_CPU_DEFAULT): Delete.
+ * arm/linux-eabi.h (SUBTARGET_CPU_DEFAULT): Delete.
+ * arm/linux-elf.h (SUBTARGET_CPU_DEFAULT): Delete.
+ * arm/symbian.h (SUBTARGET_CPU_DEFAULT): Delete.
+ * arm/unknown-elf.h (SUBTARGET_CPU_DEFAULT): Delete.
+
+2016-11-03 Jiong Wang <jiong.wang@arm.com>
+
+ * reg-notes.def (CFA_VAL_EXPRESSION): New entry.
+ * dwarf2cfi.c (dwarf2out_frame_debug_cfa_val_expression): New function.
+ (dwarf2out_frame_debug): Support REG_CFA_VAL_EXPRESSION.
+ (output_cfa_loc): Support DW_CFA_val_expression.
+ (output_cfa_loc_raw): Likewise.
+ (output_cfi): Likewise.
+ (output_cfi_directive): Likewise.
+ * dwarf2out.c (dw_cfi_oprnd1_desc): Support DW_CFA_val_expression.
+ (dw_cfi_oprnd2_desc): Likewise.
+ (mem_loc_descriptor): Recognize new pattern generated for value
+ expression.
+
+2016-11-03 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR rtl-optimization/78186
+ * combine.c (change_zero_ext): Mask the RHS of a zero_extract as
+ well, when converting to IOR.
+
+2016-11-03 Eric Botcazou <ebotcazou@adacore.com>
+
+ * config/sparc/sparc.md (vec_interleave_lowv8qi): Delete.
+ (vec_interleave_highv8qi): Likewise.
+
+2016-11-03 Martin Liska <mliska@suse.cz>
+
+ * profile.c (instrument_values): Fix coding style.
+ (branch_prob): Use renamed function.
+ * tree-profile.c (init_ic_make_global_vars): Likewise.
+ (gimple_init_edge_profiler): Rename to
+ gimple_init_gcov_profiler.
+ tree_time_profiler_counter variable declaration.
+ (gimple_gen_time_profiler): Rewrite to do a direct gimple code
+ emission.
+ * value-prof.h: Remove an argument.
+
+2016-11-03 Richard Biener <rguenther@suse.de>
+
+ * config/rs6000/rs6000.c (rs6000_xcoff_declare_object_name): Use
+ symtab_node::get_create.
+
+2016-11-03 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * rtlanal.c (nonzero_bits1): Fix WORD_REGISTER_OPERATIONS condition.
+ Move comments into more natural position.
+
+2016-11-03 Vineet Gupta <vgupta@synopsys.com>
+
+ * config/arc/arc.h (SIZE_TYPE): Define as unsigned int.
+ (PTRDIFF_TYPE): Define as int.
+
+2016-11-03 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * ccmp.c (expand_ccmp_expr_1): Adjust.
+ (expand_ccmp_expr): Likewise.
+ (expand_ccmp_next): Likewise.
+ * config/aarch64/aarch64.c (aarch64_gen_ccmp_next): Likewise.
+ (aarch64_gen_ccmp_first): Likewise.
+ * doc/tm.texi: Regenerate.
+ * target.def (gen_ccmp_first): Change argument types to rtx_insn *.
+ (gen_ccmp_next): Likewise.
+
+2016-11-03 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-vect-loop.c (destroy_loop_vec_info): Handle cond_expr.
+ (vect_is_simple_reduction): Swap cond_reduction by inversion.
+
+2016-11-02 Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/i386.c (ix86_init_libfuncs): New. Call
+ darwin_rename_builtins here.
+ (ix86_expand_divmod_libfunc): New.
+ (TARGET_INIT_LIBFUNCS): Unconditionally define to ix86_init_libfuncs.
+ (TARGET_EXPAND_DIVMOD_LIBFUNC): Define.
+
+2016-11-02 Cesar Philippidis <cesar@codesourcery.com>
+ Nathan Sidwell <nathan@acm.org>
+
+ * config/nvptx/nvptx.c (PTX_GANG_DEFAULT): Set to zero.
+
+2016-11-02 Max Filippov <jcmvbkbc@gmail.com>
+
+ * config/xtensa/xtensa.c (xtensa_output_integer_literal_parts):
+ New function.
+ (xtensa_output_literal): Use xtensa_output_integer_literal_parts
+ to format MODE_INT and MODE_PARTIAL_INT literals.
+
+2016-11-02 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/78168
+ * config/r6000/rs6000.c (rs6000_get_separate_components): Return
+ NULL if TARGET_SPE_ABI.
+
+2016-11-02 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gimple-ssa-store-merging.c (encode_tree_to_bitpos): Don't forget to
+ clear padding bits even when they're less than a byte.
+
+2016-11-02 Richard Biener <rguenther@suse.de>
+
+ * gimple-ssa-store-merging.c: Include gimplify-me.h.
+ (imm_store_chain_info::output_merged_stores): Force base_addr
+ to be proper GIMPLE for a MEM_REF address.
+ (pass_store_merging::execute): Restrict negative bitpos
+ handling to non-MEM_REF bases. Remove TREE_THIS_VOLATILE
+ check. Take into account non-NULL_TREE offset if the base
+ is already addressable.
+
+2016-11-26 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * config/aarch64/aarch64-simd.md (aarch64_crypto_sha1hv4si):
+ New pattern.
+ (aarch64_be_crypto_sha1hv4si): New pattern.
+
+2016-11-02 Wilco Dijkstra <wdijkstr@arm.com>
+
+ * config/aarch64/aarch64.md (add<mode>3): Remove
+ redundant code. Don't split frame based additions.
+
+2016-11-02 Richard Biener <rguenther@suse.de>
+
+ * gimple-ssa-store-merging.c (struct store_immediate_info): Remove
+ redundant val and dest members.
+ (store_immediate_info::store_immediate_info): Adjust.
+ (merged_store_group::merged_store_group): Adjust.
+ (merged_store_group::apply_stores): Likewise.
+ (struct imm_store_chain_info): Add base_addr field.
+ (imm_store_chain_info::imm_store_chain_info): New constructor.
+ (imm_store_chain_info::terminate_and_process_chain): Do not pass base.
+ (imm_store_chain_info::output_merged_store): Likewise. Use
+ addr_base which is already the address.
+ (imm_store_chain_info::output_merged_stores): Likewise.
+ (pass_tree_store_merging::terminate_all_aliasing_chains): Take
+ imm_store_chain_info instead of base. Fix alias check.
+ (pass_tree_store_merging::terminate_and_release_chain): Likewise.
+ (imm_store_chain_info::coalesce_immediate_stores): Adjust.
+ (pass_store_merging::execute): Refuse to operate on TARGET_MEM_REF.
+ use the address of the base and adjust for other changes.
+
+2016-11-02 Martin Liska <mliska@suse.cz>
+
+ * fold-const-call.c (host_size_t_cst_p): Test whether
+ t is convertible to size_t.
+
+2016-11-02 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/78170
+ * gimple-ssa-store-merging.c (encode_tree_to_bitpos): Truncate padding
+ introduced by native_encode_expr on little-endian as well.
+
+2016-11-02 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/78162
+ * gimple-ssa-store-merging.c (execute): Mark stores with bitpos < 0
+ as invalid.
+
+2016-11-02 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (aarch64_register_saved_on_entry): Add
+ function comment.
+ (aarch64_next_callee_save): Likewise.
+ (aarch64_pushwb_single_reg): Likewise.
+ (aarch64_gen_storewb_pair): Likewise.
+ (aarch64_push_regs): Likewise.
+ (aarch64_gen_loadwb_pair): Likewise.
+ (aarch64_pop_regs): Likewise.
+ (aarch64_gen_store_pair): Likewise.
+ (aarch64_gen_load_pair): Likewise.
+ (aarch64_save_callee_saves): Likewise.
+ (aarch64_restore_callee_saves): Likewise.
+
+2016-11-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78035
+ PR tree-optimization/77964
+ * gimple-pretty-print.c (pp_points_to_solution): Print
+ vars_contains_interposable.
+ * tree-ssa-alias.c: Include varasm.h.
+ (ptrs_compare_unequal): Check vars_contains_interposable and
+ decl_binds_to_current_def_p.
+ (dump_points_to_solution): Dump vars_contains_interposable.
+ * tree-ssa-alias.h (struct pt_solution): Add vars_contains_interposable
+ flag.
+ * tree-ssa-structalias.c: Include varasm.h.
+ (set_uids_in_ptset): Record whether vars contains a
+ not decl_binds_to_current_def_p variable in vars_contains_interposable.
+ (ipa_escaped_pt): Update initializer.
+
+2016-11-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78047
+ * tree-ssa-structalias.c (push_fields_onto_fieldstack): Initialize
+ fake field at offset zero conservatively regarding to may_have_pointers.
+
+2016-11-02 Richard Biener <rguenther@suse.de>
+
+ * tree-vrp.c (evrp_dom_walker::before_dom_children): Call
+ infer_value_range on stmt ops and update value-ranges.
+ Dump visited stmts and blocks.
+ (evrp_dom_walker::push_value_range): Dump changes.
+ (evrp_dom_walker::pop_value_range): Likewise.
+ (evrp_dom_walker::try_find_new_range): Avoid noop changes.
+
+2016-11-01 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * emit-rtl.c (prev_nonnote_insn_bb): Change argument type to
+ rtx_insn *.
+ * rtl.h (prev_nonnote_insn_bb): Adjust prototype.
+
+2016-11-01 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * cfgrtl.c (delete_insn_chain): Change argument type to rtx_insn *
+ and adjust for that.
+ * cfgrtl.h (delete_insn_chain): Adjust prototype.
+
+2016-11-01 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * config/rl78/rl78.c (gen-and_emit_move): Change argument type
+ to rtx_insn *.
+ (transcode_memory_rtx): Likewise.
+ (move_to_acc): Likewise.
+ (move_from_acc): Likewise.
+ (move_acc_to_reg): Likewise.
+ (move_to_x): Likewise.
+ (move_to_hl): Likewise.
+ (move_to_de): Likewise.
+ * config/rs6000/rs6000.c (emit_frame_save): Likewise.
+ (rs6000_emit_savres_rtx): Likewise.
+ (rs6000_emit_prologue): Likewise.
+ * reorg.c (update_reg_unused_notes): Likewise.
+ * rtl.h (remove_note): Adjust prototype.
+ * rtlanal.c (remove_note): Make argument type rtx_insn *.
+
+2016-11-01 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * config/alpha/alpha.c (alpha_legitimize_address_1): Split up
+ variables so some can be rtx_insn *.
+ (alpha_emit_xfloating_libcall): Likewise.
+ * config/mips/mips.c (mips_call_tls_get_addr): Likewise.
+ (mips_legitimize_tls_address): Likewise.
+ * optabs.c (expand_binop): Likewise.
+ * reload1.c (gen_reload): Likewise.
+
+2016-11-01 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * reorg.c (relax_delay_slots): Split up the trial variable.
+
+2016-11-01 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
+
+ * config/arc/arc.c (arc_emit_call_tls_get_addr): Make the type
+ of variables rtx_insn *.
+ * config/arm/arm.c (arm_call_tls_get_addr): Likewise.
+ (legitimize_tls_address): Likewise.
+ * config/bfin/bfin.c (hwloop_optimize): Likewise.
+ (bfin_gen_bundles): Likewise.
+ * config/c6x/c6x.c (reorg_split_calls): Likewise.
+ (c6x_reorg): Likewise.
+ * config/frv/frv.c (frv_reorder_packet): Likewise.
+ * config/i386/i386.c (ix86_split_idivmod): Likewise.
+ * config/ia64/ia64.c (ia64_expand_compare): Likewise.
+ * config/m32c/m32c.c (m32c_prepare_shift): Likewise.
+ * config/mn10300/mn10300.c: Likewise.
+ * config/rl78/rl78.c: Likewise.
+ * config/s390/s390.c (s390_fix_long_loop_prediction): Likewise.
+ * config/sh/sh-mem.cc (sh_expand_cmpstr): Likewise.
+ (sh_expand_cmpnstr): Likewise.
+ (sh_expand_strlen): Likewise.
+ (sh_expand_setmem): Likewise.
+ * config/sh/sh.md: Likewise.
+ * emit-rtl.c (emit_pattern_before): Likewise.
+ * except.c: Likewise.
+ * final.c: Likewise.
+ * jump.c: Likewise.
+
+2016-11-01 Jason Merrill <jason@redhat.com>
+
+ * tree-inline.c (copy_tree_body_r): Only copy the taken branch of
+ a COND_EXPR with constant condition.
+
+2016-11-01 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (gen_variable_die): Remove again origin_die variable
+ and its initialization.
+
+2016-11-01 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * dwarf2out.c (output_rnglists): Wrap basebuf, len in
+ HAVE_AS_LEB128.
+
+2016-11-01 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (add_name_and_src_coords_attributes): Add NO_LINKAGE_NAME
+ argument, don't call add_linkage_name if it is true.
+ (gen_variable_die): For C++ inline static data members, consider the
+ initial call when old_die is NULL to be declaration and call
+ add_name_and_src_coords_attributes in that case with true as
+ NO_LINKAGE_NAME. Add DW_AT_inline attribute if needed.
+ (gen_member_die): For C++ inline static data members, emit a
+ definition DIE right away in DW_TAG_compile_unit context.
+
+2016-11-01 John David Anglin <danglin@gcc.gnu.org>
+
+ PR target/78166
+ * config/pa/pa.md: Add new shift/add patterns to handle
+ (plus (mult (reg) (mem_shadd_operand)) (reg)) source operand.
+
+2016-11-01 Max Filippov <jcmvbkbc@gmail.com>
+
+ * config/xtensa/xtensa-protos.h
+ (xtensa_use_return_instruction_p): New prototype.
+ * config/xtensa/xtensa.c (xtensa_current_frame_size,
+ xtensa_callee_save_size): Remove.
+ (struct machine_function): Add new fields: current_frame_size,
+ callee_save_size, frame_laid_out and epilogue_done.
+ (compute_frame_size, xtensa_expand_prologue,
+ xtensa_expand_epilogue): Replace xtensa_callee_save_size with
+ cfun->machine->callee_save_size and xtensa_current_frame_size
+ with cfun->machine->current_frame_size.
+ (compute_frame_size): Update cfun->machine->frame_laid_out and
+ don't update frame layout after reload completion.
+ (xtensa_expand_epilogue): Set cfun->machine->epilogue_done
+ instead of zeroing xtensa_current_frame_size.
+ (xtensa_use_return_instruction_p): New function.
+ * config/xtensa/xtensa.h (xtensa_current_frame_size): Remove
+ declaration.
+ (INITIAL_ELIMINATION_OFFSET): Use return value of
+ compute_frame_size instead of xtensa_current_frame_size value.
+ * config/xtensa/xtensa.md ("return" pattern): Use new predicate
+ function xtensa_use_return_instruction_p instead of inline code.
+
+2016-11-01 Jakub Jelinek <jakub@redhat.com>
+
+ * tree.h (BLOCK_IN_COLD_SECTION_P): Define.
+ * final.c (final_scan_insn): Set BLOCK_IN_COLD_SECTION_P.
+ * dwarf2out.c (rnglist_idx): New variable.
+ (struct dw_ranges): Add label, idx and maybe_new_sec fields.
+ (DEBUG_RNGLISTS_SECTION): Define.
+ (ranges_base_label): New variable.
+ (size_of_die) <case dw_val_class_range_list>: If using
+ DW_FORM_rnglistx, count size of uleb128 of range list index.
+ (value_format) <case dw_val_class_range_list>: For
+ -gdwarf-5 -gsplit-dwarf return DW_FORM_rnglistx.
+ (output_range_list_offset): Handle -gdwarf-5 .debug_rnglists
+ offsets. Multiply dwarf < 5 offsets by 2 * DWARF_ADDR_SIZE.
+ (add_ranges_num): Remove useless prototype. Don't multiply
+ by 2 * DWARF2_ADDR_SIZE. Add maybe_new_sec argument, adjust
+ for new fields added to dw_ranges struct.
+ (add_ranges): Add maybe_new_sec argument and pass it
+ through to add_ranges_num.
+ (note_rnglist_head): New function.
+ (add_ranges_by_labels): Pass true as maybe_new_sec to
+ add_ranges_num, call note_rnglist_head on the head of the list.
+ (output_ranges): Add function comment. Switch to
+ .debug_ranges section here and emit .Ldebug_ranges0 label.
+ (index_rnglists, output_rnglists): New functions.
+ (gen_subprogram_die): Formatting fixes.
+ (add_high_low_attributes): Don't divide offsets
+ by 2 * DWARF2_ADDR_SIZE. Call note_rnglist_head on the
+ first list element or when pointing into the middle of
+ a list. Pass true as second argument to add_ranges on the
+ first block fragment after cold/hot section switch.
+ (init_sections_and_labels): For -gdwarf-5 use .debug_rnglists
+ section instead of .debug_ranges. Initialize
+ ranges_base_label if -gdwarf-5 -gsplit-dwarf.
+ (dwarf2out_finish): For -gdwarf-5 -gsplit-dwarf call
+ index_rnglists and add DW_AT_rnglists_base attr. Don't switch
+ to dwarf_ranges_section here or emit .Ldebug_ranges0 label.
+ Call output_rnglists for -gdwarf-5.
+ (dwarf2out_c_finalize): Clear rnglist_idx.
+
+2016-11-01 Fritz Reese <fritzoreese@gmail.com>
+
+ * combine.c (simplify_compare_const): Add gcc_fallthrough.
+
+2016-11-01 Bilyan Borisov <bilyan.borisov@arm.com>
+ Tamar Christina <tamar.christina@arm.com>
+
+ * config/arm/arm-c.c (arm_cpu_builtins): New macro definition.
+ * config/arm/arm_neon.h (vmaxnm_f32): New intrinsinc.
+ (vmaxnmq_f32): Likewise.
+ (vminnm_f32): Likewise.
+ (vminnmq_f32): Likewise.
+ * config/arm/arm_neon_builtins.def (vmaxnm): New builtin.
+ (vminnm): Likewise.
+ * config/arm/neon.md (neon_<fmaxmin_op><mode>, VCVTF): New
+ expander.
+
+2016-10-31 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * config/rs6000/vsx.md (VSX_EXTRACT_FL): New iterator for all
+ binary floating point types supported by the hardware except for
+ double.
+ (vsx_xvcvsxwdp_df): Provide scalar result alternative to the
+ vector instruction for optimizing extracting a SImode from a
+ V4SImode vector and converting it to floating point.
+ (vsx_xvcvuxwdp_df): Likewise.
+ (vsx_extract_si): On ISA 3.0, allow extract target and temporary
+ registers to be any VSX register. Move stores to the end of the
+ constraints.
+ (vsx_extract_si_<uns>float_df): New combiner pattern and splitter
+ to optimize extracting a SImode from a V4SImode vector and
+ converting it to a binary floating point type supported by the
+ hardware. Use the vector converts instead of extracting the
+ element, sign extending it, and then converting it to double.
+ Other floating point types than double first convert to double,
+ then the double is converted to that type.
+ (vsx_extract_si_<uns>float_<mode>): Likewise.
+
+2016-10-31 Andrew Pinski <apinski@cavium.com>
+
+ * config/aarch64/driver-aarch64.c (host_detect_local_cpu):
+ Rewrite handling of part num to handle the case where
+ multiple implementers share the same part num.
+
+2016-10-31 Jan Kratochvil <jan.kratochvil@redhat.com>
+ Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (DWARF_COMPILE_UNIT_HEADER_SIZE): Adjust for -gdwarf-5.
+ (DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE): Likewise.
+
+2016-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.c (dwarf_AT): Handle DW_AT_dwo_name.
+ (use_debug_types): Adjust comment for DWARF5 DW_UT_type units.
+ (new_die): Handle DW_TAG_skeleton_unit like DW_TAG_compile_unit.
+ (is_cu_die, is_unit_die): Likewise.
+ (should_move_die_to_comdat, break_out_comdat_types): Adjust
+ comments for DWARF5 DW_UT_type units.
+ (output_compilation_unit_header): Add UT argument, output
+ start of DWARF5 .debug_info section header.
+ (output_comp_unit): Add dwo_id argument. Adjust
+ output_compilation_unit_header caller, for DW_UT_split_compile
+ emit dwo_id field, otherwise padding1. Emit padding2 field.
+ (add_top_level_skeleton_die_attrs): Add DW_AT_dwo_name
+ rather than DW_AT_GNU_dwo_name attr for -gdwarf-5.
+ (output_skeleton_debug_sections): Add dwo_id argument, for
+ -gdwarf-5 emit DWARF 5 DW_UT_skeleton header.
+ (output_comdat_type_unit): For -gdwarf-5 emit .debug_info
+ DW_UT_type or DW_UT_split_type units rather than .debug_types.
+ (dwarf2out_finish): Use DW_TAG_skeleton_unit rather than
+ DW_TAG_compile_unit for skeleton unit die. Don't add
+ DW_AT_GNU_dwo_id attributes for -gdwarf-5, instead pass checksum
+ address to output_comp_unit and output_skeleton_debug_sections.
+
+ * dwarf2out.c (debug_line_str_section): New variable.
+ (debug_line_str_hash): Likewise.
+ (DEBUG_LINE_STR_SECTION): Define.
+ (set_indirect_string): Handle DW_FORM_line_strp like
+ DW_FORM_strp.
+ (find_string_form): Fix up formatting.
+ (size_of_die): Handle DW_FORM_line_strp like DW_FORM_strp.
+ Fix up indentation.
+ (output_die): Handle DW_FORM_line_strp.
+ (DWARF5_USE_DEBUG_LINE_STR): Define.
+ (output_line_string): New function.
+ (output_file_names): Add -gdwarf-5 support.
+ (output_line_info): Likewise.
+ (init_sections_and_labels): Initialize debug_line_str_section.
+ (output_indirect_string): Change 2nd argument from void *
+ to enum dwarf_form form, compare with form rather than
+ DW_FORM_strp.
+ (output_indirect_strings): Pass DW_FORM_strp to
+ output_indirect_string traversion.
+ (dwarf2out_finish): Output .debug_line_str strings.
+ (dwarf2out_c_finalize): Clear debug_line_str_section and
+ debug_line_str_hash.
+
+2016-10-31 Tom Tromey <tom@tromey.com>
+
+ PR debug/77315
+ * dwarf2out.c (mem_loc_descriptor): Use DW_OP_form_tls_address.
+ (resolve_args_picking_1): Move DW_OP_form_tls_address case next to
+ DW_OP_GNU_push_tls_address case.
+ (loc_list_from_tree_1): Use DW_OP_form_tls_address.
+
+2016-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * dwarf2out.h (struct dw_loc_descr_node): Adjust comment
+ for frame_offset_rel bit.
+ (struct array_descr_info): Add rank field.
+ * dwarf2out.c (struct loc_descr_context): Add placeholder_arg
+ and placeholder_seen fields.
+ (resolve_args_picking_1): Handle also frame_offset_rel DW_OP_dup
+ and DW_OP_over. Optimize DW_OP_pick 0 into DW_OP_dup and
+ DW_OP_pick 1 into DW_OP_over.
+ (function_to_dwarf_procedure, type_byte_size, field_byte_offset,
+ gen_variant_part): Clear placeholder_{arg,seen}.
+ (loc_list_from_tree_1): Drop const from context argument.
+ Handle integral PLACEHOLDER_EXPR if context->placeholder_arg.
+ (loc_list_for_address_of_addr_expr_of_indirect_ref,
+ loc_list_from_tree, loc_descriptor_from_tree): Drop const from
+ context argument.
+ (add_scalar_info): Drop const from context argument. Handle
+ context->placeholder_arg.
+ (add_bound_info): Drop const from context argument.
+ (gen_descr_array_type_die): Drop const from ctx variable.
+ Initialize placeholder_arg and placeholder_seen. Add DW_AT_rank
+ attribute and use a single DW_TAG_generic_subrange instead of
+ 7 DW_TAG_subrange_type for assumed rank arrays.
+
+ * dwarf2out.h (enum dw_val_class): Add dw_val_class_loclistsptr.
+ * dwarf2out.c (struct dw_loc_list_struct): Change emitted field
+ from bool to 1-bit uchar bitfield. Add num_assigned and
+ offset_emitted bitfields.
+ (dw_val_equal_p): Compare v.val_lbl_id rather than v.val_unsigned
+ for dw_val_class_lineptr and dw_val_class_macptr. Handle
+ dw_val_class_loclistsptr.
+ (new_addr_loc_descr): Fix up formatting.
+ (DEBUG_LOCLISTS_SECTION, DEBUG_DWO_LOCLISTS_SECTION): Define.
+ (add_AT_low_high_pc): Fix up formatting.
+ (add_AT_loclistsptr): New function.
+ (AT_lbl): Allow dw_val_class_loclistsptr.
+ (print_dw_val, attr_checksum, attr_checksum_ordered, same_dw_val_p):
+ Handle dw_val_class_loclistsptr.
+ (loc_list_idx): New variable.
+ (output_loclists_offsets, assign_location_list_indexes): New
+ functions.
+ (size_of_die): For dw_val_class_loc_list -gsplit-dwarf -gdwarf-5
+ add size_of_uleb128 of the index. Drop never used
+ dwarf_split_debug_info AT_index handling. Handle
+ dw_val_class_loclistsptr.
+ (value_format): Return DW_FORM_loclistsx for dw_val_class_loc_list
+ if -gsplit-dwarf -gdwarf-5. Handle dw_val_class_loclistsptr.
+ (output_loc_list): Handle DWARF 5 .debug_loclists* format.
+ (output_loc_list_offset): Handle -gsplit-dwarf -gdwarf-5
+ DW_FORM_loclistx indexes.
+ (output_attr_index_or_value): Fix up formatting. Don't handle
+ dw_val_class_loc_list here.
+ (output_die): Formatting fixes. Handle dw_val_class_loclistsptr.
+ For dw_val_class_loc_list call output_loc_list_offset rather than
+ output_attr_index_or_value.
+ (init_sections_and_labels): For -gdwarf-5 use .debug_loclists
+ or .debug_loclists.dwo section name for debug_loc_section.
+ (resolve_addr_in_expr): Formatting fix.
+ (index_location_lists): Likewise.
+ (dwarf2out_finish): If there are any location lists, for
+ -gsplit-dwarf -gdwarf-5 add DW_AT_loclists_base attribute. Call
+ index_location_lists only if have_location_lists. Call
+ assign_location_list_indexes for -gsplit-dwarf -gdwarf-5. Emit
+ .debug_loclists{,.dwo} section header for -gdwarf-5, for -gdwarf-5
+ -gsplit-dwarf also emit offset table.
+
+ * dwarf2out.c (DWARF_LARGEST_DATA_FORM_BITS): Define.
+ (size_of_die, value_format, output_die): Use
+ DW_FORM_data16 for 128-bit dw_val_class_const_double or
+ dw_val_class_wide_int.
+
+ * dwarf2out.c (dwarf_op): Renamed to ...
+ (dwarf_OP): ... this.
+ (convert_descriptor_to_mode, scompare_loc_descriptor,
+ minmax_loc_descriptor, typed_binop, mem_loc_descriptor,
+ implicit_ptr_descriptor, optimize_one_addr_into_implicit_ptr): Adjust
+ callers.
+ (dwarf_AT, dwarf_TAG): New functions.
+ (check_die): Disallow DW_AT_call_all_calls next to
+ DW_AT_GNU_all_call_sites.
+ (gen_call_site_die): Use dwarf_TAG and dwarf_AT with DWARF 5 tag
+ and attributes instead of the corresponding GNU tag and attributes.
+ (gen_subprogram_die): Likewise. Emit call site information even
+ for -gdwarf-5 -gstrict-dwarf. Replace DW_AT_GNU_defaulted with
+ DW_AT_defaulted in comment.
+ (resolve_addr): Handle DW_AT_call_origin attribute on
+ DW_TAG_call_site DIE like DW_AT_abstract_origin on
+ DW_TAG_GNU_call_site DIE.
+
+ * dwarf2out.c (dwarf_op): New function.
+ (size_of_loc_descr): Handle DW_OP_{implicit_pointer,entry_value},
+ DW_OP_{const,regval,deref}_type and DW_OP_{convert,reinterpret}.
+ (output_loc_operands, output_loc_operands_raw): Likewise.
+ (resolve_args_picking_1, prune_unused_types_walk_loc_descr,
+ mark_base_types, hash_loc_operands, compare_loc_operands): Likewise.
+ (resolve_addr_in_expr): Likewise. Only punt for !dwarf_strict
+ if dwarf_version < 5.
+ (convert_descriptor_to_mode): Use dwarf_op (DW_OP_xxx) instead of
+ DW_OP_GNU_xxx.
+ (scompare_loc_descriptor, ucompare_loc_descriptor,
+ minmax_loc_descriptor, typed_binop, mem_loc_descriptor,
+ implicit_ptr_descriptor, optimize_one_addr_into_implicit_ptr,
+ optimize_location_into_implicit_ptr): Likewise. Only punt for
+ !dwarf_strict if dwarf_version < 5.
+ (string_cst_pool_decl): Adjust comment.
+ (non_dwarf_expression): Handle DW_OP_implicit_pointer.
+
+ * dwarf2out.h (enum dw_val_class): Add dw_val_class_const_implicit,
+ dw_val_class_unsigned_const_implicit and dw_val_class_file_implicit.
+ (struct dw_val_node): Add val_file_implicit field.
+ * dwarf2out.c (dw_val_equal_p, print_dw_val, attr_checksum,
+ attr_checksum_ordered, same_dw_val_p, size_of_die, value_format,
+ output_die): Handle dw_val_class_const_implicit,
+ dw_val_class_unsigned_const_implicit and dw_val_class_file_implicit.
+ (abbrev_die_table): Change into va_gc vec.
+ (abbrev_die_table_allocated, abbrev_die_table_in_use,
+ ABBREV_DIE_TABLE_INCREMENT): Remove.
+ (AT_int, AT_unsigned, AT_file): Allow dw_val_class_*_implicit.
+ (abbrev_opt_start, abbrev_usage_count, sorted_abbrev_dies): New
+ variables.
+ (build_abbrev_table): Adjust for abbrev_die_table being a va_gc vec.
+ If abbrev_opt_start, fill in abbrev_usage_count and abbrev_dies
+ vectors.
+ (die_abbrev_cmp, optimize_implicit_const, optimize_abbrev_table): New
+ functions.
+ (output_die_abbrevs): For DW_FORM_implicit_const emit sleb128 with
+ the implicit value.
+ (output_abbrev_section): Adjust for abbrev_die_table being a va_gc
+ vec.
+ (output_comp_unit): Initialize abbrev_opt_start if emitting the main
+ unit. Call optimize_abbrev_table.
+ (dwarf2out_init, dwarf2out_finish, dwarf2out_c_finalize): Adjust for
+ abbrev_die_table being a va_gc vec.
+
+ PR tree-optimization/77860
+ * tree-ssa-reassoc.c (eliminate_using_constants): Handle
+ also integral complex and vector constants.
+
+ * dwarf2out.c (dwarf2out_define, dwarf2out_undef, output_macinfo_op,
+ optimize_macinfo_range, save_macinfo_strings): Replace
+ DW_MACRO_GNU_* constants with corresponding DW_MACRO_* constants.
+ (output_macinfo): Likewise. Emit .debug_macro* rather than
+ .debug_macinfo* even for -gstrict-dwarf -gdwarf-5.
+ (init_sections_and_labels): Use .debug_macro* labels rather than
+ .debug_macinfo* labels even for -gstrict-dwarf -gdwarf-5.
+ (dwarf2out_finish): Use DW_AT_macros instead of DW_AT_macro_info
+ or DW_AT_GNU_macros for -gdwarf-5.
+
+2016-10-31 Waldemar Brodkorb <wbx@openadk.org>
+
+ * config/microblaze/linux.h (UCLIBC_DYNAMIC_LINKER): Define.
+
+2016-09-11 Le-Chun Wu <lcwu@google.com>
+ Mark Wielaard <mjw@redhat.com>
+
+ * common.opt (Wshadow=global): New option. Default for -Wshadow.
+ (Wshadow=local): New option.
+ (Wshadow-local): Hidden alias for -Wshadow=local.
+ (Wshadow=compatible-local): New option.
+ (Wshadow-compatible-local): Hidden alias for
+ -Wshadow=compatible-local.
+ * doc/invoke.texi: Document Wshadow=global, Wshadow=local and
+ Wshadow=compatible-local.
+
+2016-10-31 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-vect-slp.c (vect_get_and_check_slp_defs): New parameter SWAP.
+ Check slp defs for COND_EXPR by swapping/inverting operands if the
+ new parameter SWAP indicates so.
+ (vect_build_slp_tree_1): New parameter SWAP. Check COND_EXPR stmt
+ is isomorphic to the first stmt via swapping/inverting. Store swap
+ information in the new parameter SWAP.
+ (vect_build_slp_tree): New local array SWAP and pass it to function
+ vect_build_slp_tree_1. Cleanup result handling code for function
+ call to vect_get_and_check_slp_defs. Skip operand swapping if the
+ order of operands has been fixed as indicated by SWAP[i].
+
+2016-10-31 Bin Cheng <bin.cheng@arm.com>
+
+ * tree-vect-data-refs.c (vect_slp_analyze_node_dependences): Skip
+ unnecessary data dependence check after visited store stmt.
+
+2016-10-30 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR tree-optimization/71915
+ PR tree-optimization/71490
+ * gimple-ssa-strength-reduction.c (struct slsr_cand_d): Add
+ stride_type field.
+ (find_basis_for_base_expr): Require stride types to match when
+ seeking a basis.
+ (alloc_cand_and_find_basis): Record the stride type.
+ (slsr_process_phi): Pass stride type to alloc_cand_and_find_basis.
+ (backtrace_base_for_ref): Pass types to legal_cast_p_1 rather than
+ the expressions having those types.
+ (slsr_process_ref): Pass stride type to alloc_cand_and_find_basis.
+ (create_mul_ssa_cand): Likewise.
+ (create_mul_imm_cand): Likewise.
+ (create_add_ssa_cand): Likewise.
+ (create_add_imm_cand): Likewise.
+ (legal_cast_p_1): Change interface to accept types rather than the
+ expressions having those types.
+ (legal_cast_p): Pass types to legal_cast_p_1.
+ (slsr_process_cast): Pass stride type to
+ alloc_cand_and_find_basis.
+ (slsr_process_copy): Likewise.
+ (dump_candidate): Display stride type when a cast exists.
+ (create_add_on_incoming_edge): Introduce a cast when necessary for
+ the stride type.
+ (analyze_increments): Change the code checking for invalid casts
+ to rely on the stride type, and update the documentation and
+ example. Change the code checking for pointer multiplies to rely
+ on the stride type.
+ (insert_initializers): Introduce a cast when necessary for the
+ stride type. Use the stride type for the type of the initializer.
+
+2016-10-30 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ * config/arm/arm.c (arm_const_not_ok_for_debug_p): Use VAR_P.
+
+2016-10-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/77919
+ * expr.c (expand_expr_real_1) <normal_inner_ref>: Only avoid forcing
+ into memory if both modes are complex and their inner modes have the
+ same precision. If the two modes are different complex modes, convert
+ each part separately and generate a new CONCAT.
+
+2016-10-29 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa64-hpux.h (FINI_SECTION_ASM_OP): Define to null string.
+
+2016-10-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/78148
+ * gimple-ssa-store-merging.c
+ (imm_store_chain_info::output_merged_store): Use build_aligned_type
+ instead of SET_TYPE_ALIGN on shared integral type.
+
+2016-10-29 John David Anglin <danglin@gcc.gnu.org>
+
+ * config/pa/pa.h (BIGGEST_ALIGNMENT): Adjust comment.
+ (MALLOC_ABI_ALIGNMENT): Define to 128 on all targets except SOM.
+ Adjust comment.
+
+2016-10-28 Jeff Law <law@redhat.com>
+
+ * config/vax/vax.h (REGNO_REG_CLASS): Access the REGNO argument.
+ * config/spu/spu.h (REGNO_REG_CLASS): Likewise.
+
+2016-10-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/sourcebuild.texi (Ada Tests): Remove mention of gcc chapter.
+
+2016-10-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * target.def (min_arithmetic_precision): New hook.
+ * doc/tm.texi.in (Misc): Add TARGET_MIN_ARITHMETIC_PRECISION.
+ * doc/tm.texi: Regenerate.
+ * internal-fn.c (expand_arith_overflow): Adjust handling of target
+ dependent support by means of TARGET_MIN_ARITHMETIC_PRECISION.
+ * targhooks.c (default_min_arithmetic_precision): New function.
+ * targhooks.h (default_min_arithmetic_precision): Declare.
+ * config/sparc/sparc.c (TARGET_MIN_ARITHMETIC_PRECISION): Define.
+ (sparc_min_arithmetic_precision): New function.
+
+2016-10-28 Segher Boessenkool <segher@kernel.crashing.org>
+
+ PR target/71847
+ * combine.c (change_zero_ext): Handle zero_ext of hard registers.
+ Swap commutative operands in new RTL if needed. Handle zero_ext
+ in the set_dest.
+ (recog_for_combine): Pass *pnewpat to change_zero_ext instead of
+ PATTERN (insn).
+
+2016-10-28 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+ Kugan Vivekanandarajah <kuganv@linaro.org>
+ Jim Wilson <jim.wilson@linaro.org>
+
+ PR tree-optimization/43721
+ * target.def: New hook expand_divmod_libfunc.
+ * doc/tm.texi.in: Add hook for TARGET_EXPAND_DIVMOD_LIBFUNC.
+ * doc/tm.texi: Regenerate.
+ * internal-fn.def: Add new entry for DIVMOD ifn.
+ * internal-fn.c (expand_DIVMOD): New.
+ * tree-ssa-math-opts.c: Include optabs-libfuncs.h, tree-eh.h,
+ targhooks.h.
+ (widen_mul_stats): Add new field divmod_calls_inserted.
+ (target_supports_divmod_p): New.
+ (divmod_candidate_p): Likewise.
+ (convert_to_divmod): Likewise.
+ (pass_optimize_widening_mul::execute): Call calculate_dominance_info,
+ renumber_gimple_stmt_uids at beginning of function. Call
+ convert_to_divmod and record stats for divmod.
+ * config/arm/arm.c (arm_expand_divmod_libfunc): Override hook
+ TARGET_EXPAND_DIVMOD_LIBFUNC.
+ * doc/sourcebuild.texi: Add items for arm_divmod_simode, divmod,
+ divmod_simode.
+
+2016-10-28 Eric Botcazou <ebotcazou@adacore.com>
+ Segher Boessenkool <segher@kernel.crashing.org>
+
+ * dojump.c (do_jump_by_parts_greater_rtx): Invert probability when
+ swapping the arms of the branch.
+ * internal-fn.c (expand_addsub_overflow): Use a straight-line code
+ sequence for the generic signed-signed-signed case.
+
2016-10-28 Jeff Law <law@redhat.com>
* config/bfin/bfin.c (bfin_legitimate_address_p): Add missing
@@ -339,7 +1709,7 @@
2016-10-26 Jakub Jelinek <jakub@redhat.com>
- * gen-pass-instances.awk (adjust_linenos): INcrement pass_lines[p]
+ * gen-pass-instances.awk (adjust_linenos): Increment pass_lines[p]
by increment rather than double it.
(insert_remove_pass): Strip leading whitespace from args[3]. Don't
emit a space before args[4].
@@ -1838,7 +3208,7 @@
2016-10-14 Catherine Moore <clm@codesourcery.com>
- * gcc/config/mips/mips.c (mips_prepare_pch_save): Initialize
+ * config/mips/mips.c (mips_prepare_pch_save): Initialize
micromips_globals to zero.
2016-10-14 Richard Biener <rguenther@suse.de>
@@ -4989,8 +6359,8 @@
(arm_elf_section_type_flags): New.
* config/arm/elf.h (JUMP_TABLES_IN_TEXT_SECTION): Disable
for -mpure-code.
- * gcc/doc/texi (TARGET_ASM_ELF_FLAGS_NUMERIC): New.
- * gcc/doc/texi.in (TARGET_ASM_ELF_FLAGS_NUMERIC): Likewise.
+ * doc/texi (TARGET_ASM_ELF_FLAGS_NUMERIC): New.
+ * doc/texi.in (TARGET_ASM_ELF_FLAGS_NUMERIC): Likewise.
2016-09-22 Jan Hubicka <hubicka@ucw.cz>
@@ -6255,7 +7625,7 @@
* genmatch.c (parser::parse_expr): Increase buffer size to guarantee
it fits the output of the formatted function regardless of its
arguments.
- * gcc/genmodes.c (parser::parse_expr): Same.
+ * genmodes.c (parser::parse_expr): Same.
* gimplify.c (gimplify_asm_expr): Same.
* passes.c (pass_manager::register_one_dump_file): Same.
* print-tree.c (print_node): Same.
@@ -6466,7 +7836,7 @@
2016-08-30 Tamar Christina <tamar.christina@arm.com>
- * gcc/config/aarch64/aarch64-simd.md
+ * config/aarch64/aarch64-simd.md
(aarch64_ld2<mode>_dreg_le): New.
(aarch64_ld2<mode>_dreg_be): New.
(aarch64_ld2<mode>_dreg): Removed.
@@ -9932,7 +11302,7 @@
2016-07-20 Georg-Johann Lay <avr@gjlay.de>
- * gcc/config/avr.c (avr_legitimize_address) [AVR_TINY]: Force
+ * config/avr.c (avr_legitimize_address) [AVR_TINY]: Force
constant addresses outside [0,0xc0] into a register.
(avr_out_movhi_r_mr_reg_no_disp_tiny): Pass insn. And handle
cases where the base address register is unused after.
@@ -10354,7 +11724,7 @@
2016-07-14 Alan Modra <amodra@gmail.com>
- * gcc/config/rs6000/altivec.md (altivec_mov<mode>): Disparage
+ * config/rs6000/altivec.md (altivec_mov<mode>): Disparage
gpr alternatives. Correct '*' placement on Y,r alternative.
Add '*' on operand 1 of r,r alternative.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index fef34538447..162d8f6bb0f 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20161028
+20161109
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 622d038f6fb..7ecd1e4e726 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -1879,7 +1879,10 @@ rest.cross: specs
# Specify a dummy input file to placate the driver.
# Specify -nostdinc to work around missing WIND_BASE environment variable
# required for *-wrs-vxworks-* targets.
-SELFTEST_FLAGS = -nostdinc -x c /dev/null -S -fself-test
+# Specify -o /dev/null so the output of -S is discarded. More importantly
+# It does not try to create a file with the name "null.s" on POSIX and
+# "nul.s" on Windows. Because on Windows "nul" is a reserved file name.
+SELFTEST_FLAGS = -nostdinc -x c /dev/null -S -fself-test -o /dev/null
# Run the selftests during the build once we have a driver and a cc1,
# so that self-test failures are caught as early as possible.
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 14782a7b578..e37a0000fb8 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,11 @@
+2016-11-07 Tamar Christina <tamar.christina@arm.com>
+
+ * adaint.c: Added signal.h for Windows.
+
+2016-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc-interface/misc.c (gnat_get_array_descr_info): Clear rank field.
+
2016-10-24 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* gcc-interface/Make-lang.in (lang_checks_parallelized): New target.
@@ -5,7 +13,7 @@
2016-10-20 Nicolas Roche <roche@adacore.com>
- * gcc-interface/Makefile (x86-64/Linux): Restore missing pairs.
+ * gcc-interface/Makefile (x86-64/Darwin): Restore missing pairs.
(x86/Darwin): Likewise.
2016-10-19 Eric Botcazou <ebotcazou@adacore.com>
diff --git a/gcc/ada/adaint.c b/gcc/ada/adaint.c
index 353914708ad..819ea47e449 100644
--- a/gcc/ada/adaint.c
+++ b/gcc/ada/adaint.c
@@ -190,6 +190,7 @@ UINT CurrentCCSEncoding;
#include <accctrl.h>
#include <aclapi.h>
#include <tlhelp32.h>
+#include <signal.h>
#undef DIR_SEPARATOR
#define DIR_SEPARATOR '\\'
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index 76ad06c6e8d..1fed72a0520 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -898,6 +898,7 @@ gnat_get_array_descr_info (const_tree const_type,
}
info->ndimensions = i;
+ info->rank = NULL_TREE;
/* Too many dimensions? Give up generating proper description: yield instead
nested arrays. Note that in this case, this hook is invoked once on each
diff --git a/gcc/alias.c b/gcc/alias.c
index ca475ff92af..1ea2417bed1 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -2755,6 +2755,21 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant)
|| TREE_CODE (expry) == CONST_DECL)
return 1;
+ /* If one decl is known to be a function or label in a function and
+ the other is some kind of data, they can't overlap. */
+ if ((TREE_CODE (exprx) == FUNCTION_DECL
+ || TREE_CODE (exprx) == LABEL_DECL)
+ != (TREE_CODE (expry) == FUNCTION_DECL
+ || TREE_CODE (expry) == LABEL_DECL))
+ return 1;
+
+ /* If either of the decls doesn't have DECL_RTL set (e.g. marked as
+ living in multiple places), we can't tell anything. Exception
+ are FUNCTION_DECLs for which we can create DECL_RTL on demand. */
+ if ((!DECL_RTL_SET_P (exprx) && TREE_CODE (exprx) != FUNCTION_DECL)
+ || (!DECL_RTL_SET_P (expry) && TREE_CODE (expry) != FUNCTION_DECL))
+ return 0;
+
rtlx = DECL_RTL (exprx);
rtly = DECL_RTL (expry);
@@ -2797,7 +2812,7 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant)
/* Offset based disambiguation not appropriate for loop invariant */
if (loop_invariant)
- return 0;
+ return 0;
/* Offset based disambiguation is OK even if we do not know that the
declarations are necessarily different
diff --git a/gcc/asan.c b/gcc/asan.c
index c6d924014b6..6e93ea3aba5 100644
--- a/gcc/asan.c
+++ b/gcc/asan.c
@@ -245,6 +245,22 @@ static unsigned HOST_WIDE_INT asan_shadow_offset_value;
static bool asan_shadow_offset_computed;
static vec<char *> sanitized_sections;
+/* Return true if STMT is ASAN_MARK poisoning internal function call. */
+static inline bool
+asan_mark_poison_p (gimple *stmt)
+{
+ return (gimple_call_internal_p (stmt, IFN_ASAN_MARK)
+ && tree_to_uhwi (gimple_call_arg (stmt, 0)) == ASAN_MARK_CLOBBER);
+
+}
+
+/* Set of variable declarations that are going to be guarded by
+ use-after-scope sanitizer. */
+
+static hash_set<tree> *asan_handled_variables = NULL;
+
+hash_set <tree> *asan_used_labels = NULL;
+
/* Sets shadow offset to value in string VAL. */
bool
@@ -287,6 +303,14 @@ set_sanitized_sections (const char *sections)
}
}
+bool
+asan_sanitize_stack_p (void)
+{
+ return ((flag_sanitize & SANITIZE_ADDRESS)
+ && ASAN_STACK
+ && !asan_no_sanitize_address_p ());
+}
+
/* Checks whether section SEC should be sanitized. */
static bool
@@ -315,22 +339,13 @@ asan_shadow_offset ()
alias_set_type asan_shadow_set = -1;
-/* Pointer types to 1 resp. 2 byte integers in shadow memory. A separate
+/* Pointer types to 1, 2 or 4 byte integers in shadow memory. A separate
alias set is used for all shadow memory accesses. */
-static GTY(()) tree shadow_ptr_types[2];
+static GTY(()) tree shadow_ptr_types[3];
/* Decl for __asan_option_detect_stack_use_after_return. */
static GTY(()) tree asan_detect_stack_use_after_return;
-/* Various flags for Asan builtins. */
-enum asan_check_flags
-{
- ASAN_CHECK_STORE = 1 << 0,
- ASAN_CHECK_SCALAR_ACCESS = 1 << 1,
- ASAN_CHECK_NON_ZERO_LEN = 1 << 2,
- ASAN_CHECK_LAST = 1 << 3
-};
-
/* Hashtable support for memory references used by gimple
statements. */
@@ -933,12 +948,16 @@ static void
asan_init_shadow_ptr_types (void)
{
asan_shadow_set = new_alias_set ();
- shadow_ptr_types[0] = build_distinct_type_copy (signed_char_type_node);
- TYPE_ALIAS_SET (shadow_ptr_types[0]) = asan_shadow_set;
- shadow_ptr_types[0] = build_pointer_type (shadow_ptr_types[0]);
- shadow_ptr_types[1] = build_distinct_type_copy (short_integer_type_node);
- TYPE_ALIAS_SET (shadow_ptr_types[1]) = asan_shadow_set;
- shadow_ptr_types[1] = build_pointer_type (shadow_ptr_types[1]);
+ tree types[3] = { signed_char_type_node, short_integer_type_node,
+ integer_type_node };
+
+ for (unsigned i = 0; i < 3; i++)
+ {
+ shadow_ptr_types[i] = build_distinct_type_copy (types[i]);
+ TYPE_ALIAS_SET (shadow_ptr_types[i]) = asan_shadow_set;
+ shadow_ptr_types[i] = build_pointer_type (shadow_ptr_types[i]);
+ }
+
initialize_sanitizer_builtins ();
}
@@ -1022,6 +1041,15 @@ asan_function_start (void)
current_function_funcdef_no);
}
+/* Return number of shadow bytes that are occupied by a local variable
+ of SIZE bytes. */
+
+static unsigned HOST_WIDE_INT
+shadow_mem_size (unsigned HOST_WIDE_INT size)
+{
+ return ROUND_UP (size, ASAN_SHADOW_GRANULARITY) / ASAN_SHADOW_GRANULARITY;
+}
+
/* Insert code to protect stack vars. The prologue sequence should be emitted
directly, epilogue sequence returned. BASE is the register holding the
stack base, against which OFFSETS array offsets are relative to, OFFSETS
@@ -1047,7 +1075,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
HOST_WIDE_INT base_offset = offsets[length - 1];
HOST_WIDE_INT base_align_bias = 0, offset, prev_offset;
HOST_WIDE_INT asan_frame_size = offsets[0] - base_offset;
- HOST_WIDE_INT last_offset, last_size;
+ HOST_WIDE_INT last_offset;
int l;
unsigned char cur_shadow_byte = ASAN_STACK_MAGIC_LEFT;
tree str_cst, decl, id;
@@ -1205,16 +1233,16 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
(aoff - prev_offset)
>> ASAN_SHADOW_SHIFT);
prev_offset = aoff;
- for (i = 0; i < 4; i++, aoff += (1 << ASAN_SHADOW_SHIFT))
+ for (i = 0; i < 4; i++, aoff += ASAN_SHADOW_GRANULARITY)
if (aoff < offset)
{
- if (aoff < offset - (1 << ASAN_SHADOW_SHIFT) + 1)
+ if (aoff < offset - (HOST_WIDE_INT)ASAN_SHADOW_GRANULARITY + 1)
shadow_bytes[i] = 0;
else
shadow_bytes[i] = offset - aoff;
}
else
- shadow_bytes[i] = ASAN_STACK_MAGIC_PARTIAL;
+ shadow_bytes[i] = ASAN_STACK_MAGIC_MIDDLE;
emit_move_insn (shadow_mem, asan_shadow_cst (shadow_bytes));
offset = aoff;
}
@@ -1282,35 +1310,66 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb,
if (STRICT_ALIGNMENT)
set_mem_align (shadow_mem, (GET_MODE_ALIGNMENT (SImode)));
- prev_offset = base_offset;
+ /* Unpoison shadow memory of a stack at the very end of a function.
+ As we're poisoning stack variables at the end of their scope,
+ shadow memory must be properly unpoisoned here. The easiest approach
+ would be to collect all variables that should not be unpoisoned and
+ we unpoison shadow memory of the whole stack except ranges
+ occupied by these variables. */
last_offset = base_offset;
- last_size = 0;
- for (l = length; l; l -= 2)
+ HOST_WIDE_INT current_offset = last_offset;
+ if (length)
{
- offset = base_offset + ((offsets[l - 1] - base_offset)
- & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1));
- if (last_offset + last_size != offset)
+ HOST_WIDE_INT var_end_offset = 0;
+ HOST_WIDE_INT stack_start = offsets[length - 1];
+ gcc_assert (last_offset == stack_start);
+
+ for (int l = length - 2; l > 0; l -= 2)
{
- shadow_mem = adjust_address (shadow_mem, VOIDmode,
- (last_offset - prev_offset)
- >> ASAN_SHADOW_SHIFT);
- prev_offset = last_offset;
- asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
- last_offset = offset;
- last_size = 0;
+ HOST_WIDE_INT var_offset = offsets[l];
+ current_offset = var_offset;
+ var_end_offset = offsets[l - 1];
+ HOST_WIDE_INT rounded_size = ROUND_UP (var_end_offset - var_offset,
+ BITS_PER_UNIT);
+
+ /* Should we unpoison the variable? */
+ if (asan_handled_variables != NULL
+ && asan_handled_variables->contains (decl))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ const char *n = (DECL_NAME (decl)
+ ? IDENTIFIER_POINTER (DECL_NAME (decl))
+ : "<unknown>");
+ fprintf (dump_file, "Unpoisoning shadow stack for variable: "
+ "%s (%" PRId64 "B)\n", n,
+ var_end_offset - var_offset);
+ }
+
+ unsigned HOST_WIDE_INT s
+ = shadow_mem_size (current_offset - last_offset);
+ asan_clear_shadow (shadow_mem, s);
+ HOST_WIDE_INT shift
+ = shadow_mem_size (current_offset - last_offset + rounded_size);
+ shadow_mem = adjust_address (shadow_mem, VOIDmode, shift);
+ last_offset = var_offset + rounded_size;
+ current_offset = last_offset;
+ }
+
}
- last_size += base_offset + ((offsets[l - 2] - base_offset)
- & ~(ASAN_RED_ZONE_SIZE - HOST_WIDE_INT_1))
- - offset;
- }
- if (last_size)
- {
- shadow_mem = adjust_address (shadow_mem, VOIDmode,
- (last_offset - prev_offset)
- >> ASAN_SHADOW_SHIFT);
- asan_clear_shadow (shadow_mem, last_size >> ASAN_SHADOW_SHIFT);
+
+ /* Handle last redzone. */
+ current_offset = offsets[0];
+ asan_clear_shadow (shadow_mem,
+ shadow_mem_size (current_offset - last_offset));
}
+ /* Clean-up set with instrumented stack variables. */
+ delete asan_handled_variables;
+ asan_handled_variables = NULL;
+ delete asan_used_labels;
+ asan_used_labels = NULL;
+
do_pending_stack_adjust ();
if (lab)
emit_label (lab);
@@ -1590,12 +1649,14 @@ insert_if_then_before_iter (gcond *cond,
gsi_insert_after (&cond_insert_point, cond, GSI_NEW_STMT);
}
-/* Build
- (base_addr >> ASAN_SHADOW_SHIFT) + asan_shadow_offset (). */
+/* Build (base_addr >> ASAN_SHADOW_SHIFT) + asan_shadow_offset ().
+ If RETURN_ADDRESS is set to true, return memory location instread
+ of a value in the shadow memory. */
static tree
build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
- tree base_addr, tree shadow_ptr_type)
+ tree base_addr, tree shadow_ptr_type,
+ bool return_address = false)
{
tree t, uintptr_type = TREE_TYPE (base_addr);
tree shadow_type = TREE_TYPE (shadow_ptr_type);
@@ -1618,11 +1679,15 @@ build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location,
gimple_set_location (g, location);
gsi_insert_after (gsi, g, GSI_NEW_STMT);
- t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g),
- build_int_cst (shadow_ptr_type, 0));
- g = gimple_build_assign (make_ssa_name (shadow_type), MEM_REF, t);
- gimple_set_location (g, location);
- gsi_insert_after (gsi, g, GSI_NEW_STMT);
+ if (!return_address)
+ {
+ t = build2 (MEM_REF, shadow_type, gimple_assign_lhs (g),
+ build_int_cst (shadow_ptr_type, 0));
+ g = gimple_build_assign (make_ssa_name (shadow_type), MEM_REF, t);
+ gimple_set_location (g, location);
+ gsi_insert_after (gsi, g, GSI_NEW_STMT);
+ }
+
return gimple_assign_lhs (g);
}
@@ -1826,7 +1891,9 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t,
{
/* Automatic vars in the current function will be always
accessible. */
- if (decl_function_context (inner) == current_function_decl)
+ if (decl_function_context (inner) == current_function_decl
+ && (!asan_sanitize_use_after_scope ()
+ || !TREE_ADDRESSABLE (inner)))
return;
}
/* Always instrument external vars, they might be dynamically
@@ -2141,8 +2208,10 @@ transform_statements (void)
If the current instruction is a function call that
might free something, let's forget about the memory
references that got instrumented. Otherwise we might
- miss some instrumentation opportunities. */
- if (is_gimple_call (s) && !nonfreeing_call_p (s))
+ miss some instrumentation opportunities. Do the same
+ for a ASAN_MARK poisoning internal function. */
+ if (is_gimple_call (s)
+ && (!nonfreeing_call_p (s) || asan_mark_poison_p (s)))
empty_mem_ref_hash_table ();
gsi_next (&i);
@@ -2191,19 +2260,20 @@ asan_dynamic_init_call (bool after_p)
const void *__module_name;
uptr __has_dynamic_init;
__asan_global_source_location *__location;
+ char *__odr_indicator;
} type. */
static tree
asan_global_struct (void)
{
- static const char *field_names[7]
+ static const char *field_names[8]
= { "__beg", "__size", "__size_with_redzone",
- "__name", "__module_name", "__has_dynamic_init", "__location"};
- tree fields[7], ret;
+ "__name", "__module_name", "__has_dynamic_init", "__location", "__odr_indicator"};
+ tree fields[8], ret;
int i;
ret = make_node (RECORD_TYPE);
- for (i = 0; i < 7; i++)
+ for (i = 0; i < 8; i++)
{
fields[i]
= build_decl (UNKNOWN_LOCATION, FIELD_DECL,
@@ -2312,6 +2382,8 @@ asan_add_global (tree decl, tree type, vec<constructor_elt, va_gc> *v)
else
locptr = build_int_cst (uptr, 0);
CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, locptr);
+ /* TODO: support ODR indicators. */
+ CONSTRUCTOR_APPEND_ELT (vinner, NULL_TREE, build_int_cst (uptr, 0));
init = build_constructor (type, vinner);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
}
@@ -2576,6 +2648,131 @@ asan_finish_file (void)
flag_sanitize |= SANITIZE_ADDRESS;
}
+/* Poison or unpoison (depending on IS_CLOBBER variable) shadow memory based
+ on SHADOW address. Newly added statements will be added to ITER with
+ given location LOC. We mark SIZE bytes in shadow memory, where
+ LAST_CHUNK_SIZE is greater than zero in situation where we are at the
+ end of a variable. */
+
+static void
+asan_store_shadow_bytes (gimple_stmt_iterator *iter, location_t loc,
+ tree shadow,
+ unsigned HOST_WIDE_INT base_addr_offset,
+ bool is_clobber, unsigned size,
+ unsigned last_chunk_size)
+{
+ tree shadow_ptr_type;
+
+ switch (size)
+ {
+ case 1:
+ shadow_ptr_type = shadow_ptr_types[0];
+ break;
+ case 2:
+ shadow_ptr_type = shadow_ptr_types[1];
+ break;
+ case 4:
+ shadow_ptr_type = shadow_ptr_types[2];
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ unsigned char c = (char) is_clobber ? ASAN_STACK_MAGIC_USE_AFTER_SCOPE : 0;
+ unsigned HOST_WIDE_INT val = 0;
+ for (unsigned i = 0; i < size; ++i)
+ {
+ unsigned char shadow_c = c;
+ if (i == size - 1 && last_chunk_size && !is_clobber)
+ shadow_c = last_chunk_size;
+ val |= (unsigned HOST_WIDE_INT) shadow_c << (BITS_PER_UNIT * i);
+ }
+
+ /* Handle last chunk in unpoisoning. */
+ tree magic = build_int_cst (TREE_TYPE (shadow_ptr_type), val);
+
+ tree dest = build2 (MEM_REF, TREE_TYPE (shadow_ptr_type), shadow,
+ build_int_cst (shadow_ptr_type, base_addr_offset));
+
+ gimple *g = gimple_build_assign (dest, magic);
+ gimple_set_location (g, loc);
+ gsi_insert_after (iter, g, GSI_NEW_STMT);
+}
+
+/* Expand the ASAN_MARK builtins. */
+
+bool
+asan_expand_mark_ifn (gimple_stmt_iterator *iter)
+{
+ gimple *g = gsi_stmt (*iter);
+ location_t loc = gimple_location (g);
+ HOST_WIDE_INT flags = tree_to_shwi (gimple_call_arg (g, 0));
+ gcc_assert (flags < ASAN_MARK_LAST);
+ bool is_clobber = (flags & ASAN_MARK_CLOBBER) != 0;
+
+ tree base = gimple_call_arg (g, 1);
+ gcc_checking_assert (TREE_CODE (base) == ADDR_EXPR);
+ tree decl = TREE_OPERAND (base, 0);
+ gcc_checking_assert (TREE_CODE (decl) == VAR_DECL);
+ if (asan_handled_variables == NULL)
+ asan_handled_variables = new hash_set<tree> (16);
+ asan_handled_variables->add (decl);
+ tree len = gimple_call_arg (g, 2);
+
+ gcc_assert (tree_fits_shwi_p (len));
+ unsigned HOST_WIDE_INT size_in_bytes = tree_to_shwi (len);
+ gcc_assert (size_in_bytes);
+
+ g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
+ NOP_EXPR, base);
+ gimple_set_location (g, loc);
+ gsi_replace (iter, g, false);
+ tree base_addr = gimple_assign_lhs (g);
+
+ /* Generate direct emission if size_in_bytes is small. */
+ if (size_in_bytes <= ASAN_PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD)
+ {
+ unsigned HOST_WIDE_INT shadow_size = shadow_mem_size (size_in_bytes);
+
+ tree shadow = build_shadow_mem_access (iter, loc, base_addr,
+ shadow_ptr_types[0], true);
+
+ for (unsigned HOST_WIDE_INT offset = 0; offset < shadow_size;)
+ {
+ unsigned size = 1;
+ if (shadow_size - offset >= 4)
+ size = 4;
+ else if (shadow_size - offset >= 2)
+ size = 2;
+
+ unsigned HOST_WIDE_INT last_chunk_size = 0;
+ unsigned HOST_WIDE_INT s = (offset + size) * ASAN_SHADOW_GRANULARITY;
+ if (s > size_in_bytes)
+ last_chunk_size = ASAN_SHADOW_GRANULARITY - (s - size_in_bytes);
+
+ asan_store_shadow_bytes (iter, loc, shadow, offset, is_clobber,
+ size, last_chunk_size);
+ offset += size;
+ }
+ }
+ else
+ {
+ g = gimple_build_assign (make_ssa_name (pointer_sized_int_node),
+ NOP_EXPR, len);
+ gimple_set_location (g, loc);
+ gsi_insert_before (iter, g, GSI_SAME_STMT);
+ tree sz_arg = gimple_assign_lhs (g);
+
+ tree fun = builtin_decl_implicit (is_clobber ? BUILT_IN_ASAN_CLOBBER_N
+ : BUILT_IN_ASAN_UNCLOBBER_N);
+ g = gimple_build_call (fun, 2, base_addr, sz_arg);
+ gimple_set_location (g, loc);
+ gsi_insert_after (iter, g, GSI_NEW_STMT);
+ }
+
+ return false;
+}
+
/* Expand the ASAN_{LOAD,STORE} builtins. */
bool
diff --git a/gcc/asan.h b/gcc/asan.h
index 7ec693f2b3c..9cf5904618b 100644
--- a/gcc/asan.h
+++ b/gcc/asan.h
@@ -29,6 +29,7 @@ extern bool asan_protect_global (tree);
extern void initialize_sanitizer_builtins (void);
extern tree asan_dynamic_init_call (bool);
extern bool asan_expand_check_ifn (gimple_stmt_iterator *, bool);
+extern bool asan_expand_mark_ifn (gimple_stmt_iterator *);
extern gimple_stmt_iterator create_cond_insert_point
(gimple_stmt_iterator *, bool, bool, bool, basic_block *, basic_block *);
@@ -36,9 +37,14 @@ extern gimple_stmt_iterator create_cond_insert_point
/* Alias set for accessing the shadow memory. */
extern alias_set_type asan_shadow_set;
+/* Hash set of labels that are either used in a goto, or their address
+ has been taken. */
+extern hash_set <tree> *asan_used_labels;
+
/* Shadow memory is found at
(address >> ASAN_SHADOW_SHIFT) + asan_shadow_offset (). */
#define ASAN_SHADOW_SHIFT 3
+#define ASAN_SHADOW_GRANULARITY (1UL << ASAN_SHADOW_SHIFT)
/* Red zone size, stack and global variables are padded by ASAN_RED_ZONE_SIZE
up to 2 * ASAN_RED_ZONE_SIZE - 1 bytes. */
@@ -50,22 +56,31 @@ extern alias_set_type asan_shadow_set;
the frame. Middle is for padding in between variables, right is
above the last protected variable and partial immediately after variables
up to ASAN_RED_ZONE_SIZE alignment. */
-#define ASAN_STACK_MAGIC_LEFT 0xf1
-#define ASAN_STACK_MAGIC_MIDDLE 0xf2
-#define ASAN_STACK_MAGIC_RIGHT 0xf3
-#define ASAN_STACK_MAGIC_PARTIAL 0xf4
-#define ASAN_STACK_MAGIC_USE_AFTER_RET 0xf5
+#define ASAN_STACK_MAGIC_LEFT 0xf1
+#define ASAN_STACK_MAGIC_MIDDLE 0xf2
+#define ASAN_STACK_MAGIC_RIGHT 0xf3
+#define ASAN_STACK_MAGIC_USE_AFTER_RET 0xf5
+#define ASAN_STACK_MAGIC_USE_AFTER_SCOPE 0xf8
#define ASAN_STACK_FRAME_MAGIC 0x41b58ab3
#define ASAN_STACK_RETIRED_MAGIC 0x45e0360e
-/* Return true if DECL should be guarded on the stack. */
-
-static inline bool
-asan_protect_stack_decl (tree decl)
+/* Various flags for Asan builtins. */
+enum asan_check_flags
{
- return DECL_P (decl) && !DECL_ARTIFICIAL (decl);
-}
+ ASAN_CHECK_STORE = 1 << 0,
+ ASAN_CHECK_SCALAR_ACCESS = 1 << 1,
+ ASAN_CHECK_NON_ZERO_LEN = 1 << 2,
+ ASAN_CHECK_LAST = 1 << 3
+};
+
+/* Flags for Asan check builtins. */
+enum asan_mark_flags
+{
+ ASAN_MARK_CLOBBER = 1 << 0,
+ ASAN_MARK_UNCLOBBER = 1 << 1,
+ ASAN_MARK_LAST = 1 << 2
+};
/* Return the size of padding needed to insert after a protected
decl of SIZE. */
@@ -81,6 +96,8 @@ extern bool set_asan_shadow_offset (const char *);
extern void set_sanitized_sections (const char *);
+extern bool asan_sanitize_stack_p (void);
+
/* Return TRUE if builtin with given FCODE will be intercepted by
libasan. */
@@ -103,6 +120,36 @@ asan_intercepted_p (enum built_in_function fcode)
|| fcode == BUILT_IN_STRNCASECMP
|| fcode == BUILT_IN_STRNCAT
|| fcode == BUILT_IN_STRNCMP
+ || fcode == BUILT_IN_STRCSPN
+ || fcode == BUILT_IN_STRPBRK
+ || fcode == BUILT_IN_STRSPN
+ || fcode == BUILT_IN_STRSTR
|| fcode == BUILT_IN_STRNCPY;
}
+
+/* Return TRUE if we should instrument for use-after-scope sanity checking. */
+
+static inline bool
+asan_sanitize_use_after_scope (void)
+{
+ return (flag_sanitize_address_use_after_scope && asan_sanitize_stack_p ());
+}
+
+static inline bool
+asan_no_sanitize_address_p (void)
+{
+ return lookup_attribute ("no_sanitize_address",
+ DECL_ATTRIBUTES (current_function_decl));
+}
+
+/* Return true if DECL should be guarded on the stack. */
+
+static inline bool
+asan_protect_stack_decl (tree decl)
+{
+ return DECL_P (decl)
+ && (!DECL_ARTIFICIAL (decl)
+ || (asan_sanitize_use_after_scope () && TREE_ADDRESSABLE (decl)));
+}
+
#endif /* TREE_ASAN */
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 15d7488ba04..5207c34c912 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,41 @@
+2016-11-07 Jason Merrill <jason@redhat.com>
+
+ * c.opt (Wc++1z-compat): New.
+ * c-cppbuiltin.c (c_cpp_builtins): Add __cpp_noexcept_function_type.
+
+2016-11-07 Martin Liska <mliska@suse.cz>
+
+ * c-warn.c (warn_for_unused_label): Save all labels used
+ in goto or in &label.
+
+2016-11-03 Jason Merrill <jason@redhat.com>
+
+ * c-cppbuiltin.c (c_cpp_builtins): Correct
+ __cpp_inheriting_constructors.
+
+2016-11-01 Jason Merrill <jason@redhat.com>
+
+ * c-cppbuiltin.c (c_cpp_builtins): Update
+ __cpp_inheriting_constructors.
+
+ * c.opt (-fnew-inheriting-ctors): New.
+ * c-opts.c: Default to on for ABI 11+.
+
+2016-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/77948
+ * c.opt (fext-numeric-literals): Add Var and Init.
+ * c-opts.c (c_common_handle_option): Don't clear
+ cpp_opts->ext_numeric_literals for -std=c++{11,14,1z}.
+ (c_common_post_options): Clear it here if not set
+ explicitly.
+
+2016-10-28 Aldy Hernandez <aldyh@redhat.com>
+
+ PR debug/77773
+ * c-pretty-print.c (simple_type_specifier): Do not dereference `t'
+ if NULL.
+
2016-10-25 Jakub Jelinek <jakub@redhat.com>
* c-common.h (enum rid): Add RID_BUILTIN_LAUNDER.
diff --git a/gcc/c-family/c-cppbuiltin.c b/gcc/c-family/c-cppbuiltin.c
index 7d689a9c0ff..55dbf44d34f 100644
--- a/gcc/c-family/c-cppbuiltin.c
+++ b/gcc/c-family/c-cppbuiltin.c
@@ -904,7 +904,10 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_initializer_lists=200806");
cpp_define (pfile, "__cpp_delegating_constructors=200604");
cpp_define (pfile, "__cpp_nsdmi=200809");
- cpp_define (pfile, "__cpp_inheriting_constructors=200802");
+ if (!flag_new_inheriting_ctors)
+ cpp_define (pfile, "__cpp_inheriting_constructors=200802");
+ else
+ cpp_define (pfile, "__cpp_inheriting_constructors=201511");
cpp_define (pfile, "__cpp_ref_qualifiers=200710");
cpp_define (pfile, "__cpp_alias_templates=200704");
}
@@ -938,6 +941,7 @@ c_cpp_builtins (cpp_reader *pfile)
cpp_define (pfile, "__cpp_inline_variables=201606");
cpp_define (pfile, "__cpp_aggregate_bases=201603");
cpp_define (pfile, "__cpp_deduction_guides=201606");
+ cpp_define (pfile, "__cpp_noexcept_function_type=201510");
}
if (flag_concepts)
cpp_define (pfile, "__cpp_concepts=201507");
diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index c39930708d6..de260e7dcee 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -624,31 +624,19 @@ c_common_handle_option (size_t scode, const char *arg, int value,
case OPT_std_c__11:
case OPT_std_gnu__11:
if (!preprocessing_asm_p)
- {
- set_std_cxx11 (code == OPT_std_c__11 /* ISO */);
- if (code == OPT_std_c__11)
- cpp_opts->ext_numeric_literals = 0;
- }
+ set_std_cxx11 (code == OPT_std_c__11 /* ISO */);
break;
case OPT_std_c__14:
case OPT_std_gnu__14:
if (!preprocessing_asm_p)
- {
- set_std_cxx14 (code == OPT_std_c__14 /* ISO */);
- if (code == OPT_std_c__14)
- cpp_opts->ext_numeric_literals = 0;
- }
+ set_std_cxx14 (code == OPT_std_c__14 /* ISO */);
break;
case OPT_std_c__1z:
case OPT_std_gnu__1z:
if (!preprocessing_asm_p)
- {
- set_std_cxx1z (code == OPT_std_c__1z /* ISO */);
- if (code == OPT_std_c__1z)
- cpp_opts->ext_numeric_literals = 0;
- }
+ set_std_cxx1z (code == OPT_std_c__1z /* ISO */);
break;
case OPT_std_c90:
@@ -914,6 +902,12 @@ c_common_post_options (const char **pfilename)
if (flag_abi_version == 0)
flag_abi_version = 11;
+ /* By default, enable the new inheriting constructor semantics along with ABI
+ 11. New and old should coexist fine, but it is a change in what
+ artificial symbols are generated. */
+ if (!global_options_set.x_flag_new_inheriting_ctors)
+ flag_new_inheriting_ctors = abi_version_at_least (11);
+
if (cxx_dialect >= cxx11)
{
/* If we're allowing C++0x constructs, don't warn about C++98
@@ -923,6 +917,11 @@ c_common_post_options (const char **pfilename)
if (warn_narrowing == -1)
warn_narrowing = 1;
+
+ /* Unless -f{,no-}ext-numeric-literals has been used explicitly,
+ for -std=c++{11,14,1z} default to -fno-ext-numeric-literals. */
+ if (flag_iso && !global_options_set.x_flag_ext_numeric_literals)
+ cpp_opts->ext_numeric_literals = 0;
}
else if (warn_narrowing == -1)
warn_narrowing = 0;
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 90428cac183..7ad59003456 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -344,14 +344,17 @@ c_pretty_printer::simple_type_specifier (tree t)
else
{
int prec = TYPE_PRECISION (t);
+ tree common_t;
if (ALL_FIXED_POINT_MODE_P (TYPE_MODE (t)))
- t = c_common_type_for_mode (TYPE_MODE (t), TYPE_SATURATING (t));
+ common_t = c_common_type_for_mode (TYPE_MODE (t),
+ TYPE_SATURATING (t));
else
- t = c_common_type_for_mode (TYPE_MODE (t), TYPE_UNSIGNED (t));
- if (TYPE_NAME (t))
+ common_t = c_common_type_for_mode (TYPE_MODE (t),
+ TYPE_UNSIGNED (t));
+ if (common_t && TYPE_NAME (common_t))
{
- simple_type_specifier (t);
- if (TYPE_PRECISION (t) != prec)
+ simple_type_specifier (common_t);
+ if (TYPE_PRECISION (common_t) != prec)
{
pp_colon (this);
pp_decimal_int (this, prec);
diff --git a/gcc/c-family/c-warn.c b/gcc/c-family/c-warn.c
index 904f6d3cf4f..18ee24787a9 100644
--- a/gcc/c-family/c-warn.c
+++ b/gcc/c-family/c-warn.c
@@ -28,7 +28,7 @@ along with GCC; see the file COPYING3. If not see
#include "tm_p.h"
#include "diagnostic.h"
#include "intl.h"
-
+#include "asan.h"
/* Print a warning if a constant expression had overflow in folding.
Invoke this function on every expression that the language
@@ -1627,6 +1627,13 @@ warn_for_unused_label (tree label)
else
warning (OPT_Wunused_label, "label %q+D declared but not defined", label);
}
+ else if (asan_sanitize_use_after_scope ())
+ {
+ if (asan_used_labels == NULL)
+ asan_used_labels = new hash_set<tree> (16);
+
+ asan_used_labels->add (label);
+ }
}
/* Warn for division by zero according to the value of DIVISOR. LOC
diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt
index 458d453cdd8..213353b9abd 100644
--- a/gcc/c-family/c.opt
+++ b/gcc/c-family/c.opt
@@ -360,6 +360,13 @@ Wc++14-compat
C++ ObjC++ Var(warn_cxx14_compat) Warning LangEnabledBy(C++ ObjC++,Wall)
Warn about C++ constructs whose meaning differs between ISO C++ 2011 and ISO C++ 2014.
+Wc++1z-compat
+C++ ObjC++ Var(warn_cxx1z_compat) Warning LangEnabledBy(C++ ObjC++,Wall)
+Warn about C++ constructs whose meaning differs between ISO C++ 2014 and (forthcoming) ISO C++ 201z(7?).
+
+Wc++17-compat
+C++ ObjC++ Warning Alias(Wc++1z-compat) Undocumented
+
Wcast-qual
C ObjC C++ ObjC++ Var(warn_cast_qual) Warning
Warn about casts which discard qualifiers.
@@ -1362,6 +1369,10 @@ fimplicit-templates
C++ ObjC++ Var(flag_implicit_templates) Init(1)
Emit implicit instantiations of templates.
+fnew-inheriting-ctors
+C++ ObjC++ Var(flag_new_inheriting_ctors) Init(1)
+Implement C++17 inheriting constructor semantics.
+
ffriend-injection
C++ ObjC++ Var(flag_friend_injection)
Inject friend functions into enclosing namespace.
@@ -1705,7 +1716,7 @@ C ObjC C++ ObjC++ Joined
-femit-struct-debug-detailed=<spec-list> Detailed reduced debug info for structs.
fext-numeric-literals
-C++ ObjC++
+C++ ObjC++ Var(flag_ext_numeric_literals) Init(1)
Interpret imaginary, fixed-point, or other gnu number suffix as the corresponding
number literal rather than a user-defined number literal.
diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog
index 725afcfefa0..ee50c304b5f 100644
--- a/gcc/c/ChangeLog
+++ b/gcc/c/ChangeLog
@@ -1,3 +1,9 @@
+2016-09-11 Le-Chun Wu <lcwu@google.com>
+ Mark Wielaard <mjw@redhat.com>
+
+ * c-decl.c (warn_if_shadowing): Use the warning code corresponding
+ to the given -Wshadow= variant.
+
2016-10-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
* c-typeck.c: Include memmodel.h.
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index 136f304ca30..3e1b7a4016b 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -2735,7 +2735,9 @@ warn_if_shadowing (tree new_decl)
struct c_binding *b;
/* Shadow warnings wanted? */
- if (!warn_shadow
+ if (!(warn_shadow
+ || warn_shadow_local
+ || warn_shadow_compatible_local)
/* No shadow warnings for internally generated vars. */
|| DECL_IS_BUILTIN (new_decl)
/* No shadow warnings for vars made for inlining. */
@@ -2759,9 +2761,23 @@ warn_if_shadowing (tree new_decl)
break;
}
else if (TREE_CODE (old_decl) == PARM_DECL)
- warned = warning (OPT_Wshadow,
- "declaration of %q+D shadows a parameter",
- new_decl);
+ {
+ enum opt_code warning_code;
+
+ /* If '-Wshadow=compatible-local' is specified without other
+ -Wshadow= flags, we will warn only when the types of the
+ shadowing variable (i.e. new_decl) and the shadowed variable
+ (old_decl) are compatible. */
+ if (warn_shadow)
+ warning_code = OPT_Wshadow;
+ else if (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
+ warning_code = OPT_Wshadow_compatible_local;
+ else
+ warning_code = OPT_Wshadow_local;
+ warned = warning_at (DECL_SOURCE_LOCATION (new_decl), warning_code,
+ "declaration of %qD shadows a parameter",
+ new_decl);
+ }
else if (DECL_FILE_SCOPE_P (old_decl))
{
/* Do not warn if a variable shadows a function, unless
@@ -2784,8 +2800,23 @@ warn_if_shadowing (tree new_decl)
break;
}
else
- warned = warning (OPT_Wshadow, "declaration of %q+D shadows a "
- "previous local", new_decl);
+ {
+ enum opt_code warning_code;
+
+ /* If '-Wshadow=compatible-local' is specified without other
+ -Wshadow= flags, we will warn only when the types of the
+ shadowing variable (i.e. new_decl) and the shadowed variable
+ (old_decl) are compatible. */
+ if (warn_shadow)
+ warning_code = OPT_Wshadow;
+ else if (comptypes (TREE_TYPE (old_decl), TREE_TYPE (new_decl)))
+ warning_code = OPT_Wshadow_compatible_local;
+ else
+ warning_code = OPT_Wshadow_local;
+ warned = warning_at (DECL_SOURCE_LOCATION (new_decl), warning_code,
+ "declaration of %qD shadows a previous local",
+ new_decl);
+ }
if (warned)
inform (DECL_SOURCE_LOCATION (old_decl),
diff --git a/gcc/ccmp.c b/gcc/ccmp.c
index 615b7e653f2..14222ca5942 100644
--- a/gcc/ccmp.c
+++ b/gcc/ccmp.c
@@ -122,7 +122,7 @@ ccmp_candidate_p (gimple *g)
GEN_SEQ returns all compare insns. */
static rtx
expand_ccmp_next (gimple *g, tree_code code, rtx prev,
- rtx *prep_seq, rtx *gen_seq)
+ rtx_insn **prep_seq, rtx_insn **gen_seq)
{
rtx_code rcode;
int unsignedp = TYPE_UNSIGNED (TREE_TYPE (gimple_assign_rhs1 (g)));
@@ -149,10 +149,8 @@ expand_ccmp_next (gimple *g, tree_code code, rtx prev,
PREP_SEQ returns all insns to prepare opearand.
GEN_SEQ returns all compare insns. */
static rtx
-expand_ccmp_expr_1 (gimple *g, rtx *prep_seq, rtx *gen_seq)
+expand_ccmp_expr_1 (gimple *g, rtx_insn **prep_seq, rtx_insn **gen_seq)
{
- rtx prep_seq_1, gen_seq_1;
- rtx prep_seq_2, gen_seq_2;
tree exp = gimple_assign_rhs_to_tree (g);
tree_code code = TREE_CODE (exp);
gimple *gs0 = get_gimple_for_ssa_name (TREE_OPERAND (exp, 0));
@@ -180,6 +178,7 @@ expand_ccmp_expr_1 (gimple *g, rtx *prep_seq, rtx *gen_seq)
rcode0 = get_rtx_code (code0, unsignedp0);
rcode1 = get_rtx_code (code1, unsignedp1);
+ rtx_insn *prep_seq_1, *gen_seq_1;
tmp = targetm.gen_ccmp_first (&prep_seq_1, &gen_seq_1, rcode0,
gimple_assign_rhs1 (gs0),
gimple_assign_rhs2 (gs0));
@@ -187,14 +186,15 @@ expand_ccmp_expr_1 (gimple *g, rtx *prep_seq, rtx *gen_seq)
if (tmp != NULL)
{
ret = expand_ccmp_next (gs1, code, tmp, &prep_seq_1, &gen_seq_1);
- cost1 = seq_cost (safe_as_a <rtx_insn *> (prep_seq_1), speed_p);
- cost1 += seq_cost (safe_as_a <rtx_insn *> (gen_seq_1), speed_p);
+ cost1 = seq_cost (prep_seq_1, speed_p);
+ cost1 += seq_cost (gen_seq_1, speed_p);
}
/* FIXME: Temporary workaround for PR69619.
Avoid exponential compile time due to expanding gs0 and gs1 twice.
If gs0 and gs1 are complex, the cost will be high, so avoid
reevaluation if above an arbitrary threshold. */
+ rtx_insn *prep_seq_2, *gen_seq_2;
if (tmp == NULL || cost1 < COSTS_N_INSNS (25))
tmp2 = targetm.gen_ccmp_first (&prep_seq_2, &gen_seq_2, rcode1,
gimple_assign_rhs1 (gs1),
@@ -207,8 +207,8 @@ expand_ccmp_expr_1 (gimple *g, rtx *prep_seq, rtx *gen_seq)
{
ret2 = expand_ccmp_next (gs0, code, tmp2, &prep_seq_2,
&gen_seq_2);
- cost2 = seq_cost (safe_as_a <rtx_insn *> (prep_seq_2), speed_p);
- cost2 += seq_cost (safe_as_a <rtx_insn *> (gen_seq_2), speed_p);
+ cost2 = seq_cost (prep_seq_2, speed_p);
+ cost2 += seq_cost (gen_seq_2, speed_p);
}
if (cost2 < cost1)
@@ -262,14 +262,13 @@ expand_ccmp_expr (gimple *g)
{
rtx_insn *last;
rtx tmp;
- rtx prep_seq, gen_seq;
-
- prep_seq = gen_seq = NULL_RTX;
if (!ccmp_candidate_p (g))
return NULL_RTX;
last = get_last_insn ();
+
+ rtx_insn *prep_seq = NULL, *gen_seq = NULL;
tmp = expand_ccmp_expr_1 (g, &prep_seq, &gen_seq);
if (tmp)
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 430ad38f096..7ffb5585b76 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -868,18 +868,6 @@ union_stack_vars (size_t a, size_t b)
}
}
-/* Return true if the current function should have its stack frame
- protected by address sanitizer. */
-
-static inline bool
-asan_sanitize_stack_p (void)
-{
- return ((flag_sanitize & SANITIZE_ADDRESS)
- && ASAN_STACK
- && !lookup_attribute ("no_sanitize_address",
- DECL_ATTRIBUTES (current_function_decl)));
-}
-
/* A subroutine of expand_used_vars. Binpack the variables into
partitions constrained by the interference graph. The overall
algorithm used is as follows:
@@ -941,7 +929,8 @@ partition_stack_vars (void)
sizes, as the shorter vars wouldn't be adequately protected.
Don't do that for "large" (unsupported) alignment objects,
those aren't protected anyway. */
- if (asan_sanitize_stack_p () && isize != jsize
+ if ((asan_sanitize_stack_p ())
+ && isize != jsize
&& ialign * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
break;
@@ -1128,7 +1117,8 @@ expand_stack_vars (bool (*pred) (size_t), struct stack_vars_data *data)
if (alignb * BITS_PER_UNIT <= MAX_SUPPORTED_STACK_ALIGNMENT)
{
base = virtual_stack_vars_rtx;
- if (asan_sanitize_stack_p () && pred)
+ if ((asan_sanitize_stack_p ())
+ && pred)
{
HOST_WIDE_INT prev_offset
= align_base (frame_offset,
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index 813f7cee092..d2719db0019 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -240,17 +240,15 @@ delete_insn_and_edges (rtx_insn *insn)
insns that cannot be removed to NULL. */
void
-delete_insn_chain (rtx start, rtx finish, bool clear_bb)
+delete_insn_chain (rtx start, rtx_insn *finish, bool clear_bb)
{
- rtx_insn *prev, *current;
-
/* Unchain the insns one by one. It would be quicker to delete all of these
with a single unchaining, rather than one at a time, but we need to keep
the NOTE's. */
- current = safe_as_a <rtx_insn *> (finish);
+ rtx_insn *current = finish;
while (1)
{
- prev = PREV_INSN (current);
+ rtx_insn *prev = PREV_INSN (current);
if (NOTE_P (current) && !can_delete_note_p (as_a <rtx_note *> (current)))
;
else
diff --git a/gcc/cfgrtl.h b/gcc/cfgrtl.h
index d81928a6ebf..f4c139605a2 100644
--- a/gcc/cfgrtl.h
+++ b/gcc/cfgrtl.h
@@ -22,7 +22,7 @@ along with GCC; see the file COPYING3. If not see
extern void delete_insn (rtx);
extern bool delete_insn_and_edges (rtx_insn *);
-extern void delete_insn_chain (rtx, rtx, bool);
+extern void delete_insn_chain (rtx, rtx_insn *, bool);
extern basic_block create_basic_block_structure (rtx_insn *, rtx_insn *,
rtx_note *, basic_block);
extern void compute_bb_for_insn (void);
diff --git a/gcc/combine.c b/gcc/combine.c
index 64413b4436e..69020561c31 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -104,10 +104,6 @@ along with GCC; see the file COPYING3. If not see
#include "rtl-iter.h"
#include "print-rtl.h"
-#ifndef LOAD_EXTEND_OP
-#define LOAD_EXTEND_OP(M) UNKNOWN
-#endif
-
/* Number of attempts to combine instructions in this function. */
static int combine_attempts;
@@ -7757,7 +7753,8 @@ extract_left_shift (rtx x, int count)
IN_CODE says what kind of expression we are processing. Normally, it is
SET. In a memory address it is MEM. When processing the arguments of
- a comparison or a COMPARE against zero, it is COMPARE. */
+ a comparison or a COMPARE against zero, it is COMPARE, or EQ if more
+ precisely it is an equality comparison against zero. */
rtx
make_compound_operation (rtx x, enum rtx_code in_code)
@@ -7771,6 +7768,7 @@ make_compound_operation (rtx x, enum rtx_code in_code)
rtx new_rtx = 0;
rtx tem;
const char *fmt;
+ bool equality_comparison = false;
/* PR rtl-optimization/70944. */
if (VECTOR_MODE_P (mode))
@@ -7780,6 +7778,11 @@ make_compound_operation (rtx x, enum rtx_code in_code)
address, we stay there. If we have a comparison, set to COMPARE,
but once inside, go back to our default of SET. */
+ if (in_code == EQ)
+ {
+ equality_comparison = true;
+ in_code = COMPARE;
+ }
next_code = (code == MEM ? MEM
: ((code == COMPARE || COMPARISON_P (x))
&& XEXP (x, 1) == const0_rtx) ? COMPARE
@@ -7988,11 +7991,12 @@ make_compound_operation (rtx x, enum rtx_code in_code)
/* If we are in a comparison and this is an AND with a power of two,
convert this into the appropriate bit extract. */
else if (in_code == COMPARE
- && (i = exact_log2 (UINTVAL (XEXP (x, 1)))) >= 0)
+ && (i = exact_log2 (UINTVAL (XEXP (x, 1)))) >= 0
+ && (equality_comparison || i < GET_MODE_PRECISION (mode) - 1))
new_rtx = make_extraction (mode,
- make_compound_operation (XEXP (x, 0),
- next_code),
- i, NULL_RTX, 1, 1, 0, 1);
+ make_compound_operation (XEXP (x, 0),
+ next_code),
+ i, NULL_RTX, 1, 1, 0, 1);
/* If the one operand is a paradoxical subreg of a register or memory and
the constant (limited to the smaller mode) has only zero bits where
@@ -11106,9 +11110,10 @@ recog_for_combine_1 (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
Return whether anything was so changed. */
static bool
-change_zero_ext (rtx *src)
+change_zero_ext (rtx pat)
{
bool changed = false;
+ rtx *src = &SET_SRC (pat);
subrtx_ptr_iterator::array_type array;
FOR_EACH_SUBRTX_PTR (iter, array, src, NONCONST)
@@ -11140,6 +11145,14 @@ change_zero_ext (rtx *src)
size = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)));
x = SUBREG_REG (XEXP (x, 0));
}
+ else if (GET_CODE (x) == ZERO_EXTEND
+ && SCALAR_INT_MODE_P (mode)
+ && REG_P (XEXP (x, 0))
+ && HARD_REGISTER_P (XEXP (x, 0)))
+ {
+ size = GET_MODE_PRECISION (GET_MODE (XEXP (x, 0)));
+ x = gen_rtx_REG (mode, REGNO (XEXP (x, 0)));
+ }
else
continue;
@@ -11150,6 +11163,47 @@ change_zero_ext (rtx *src)
changed = true;
}
+ if (changed)
+ FOR_EACH_SUBRTX_PTR (iter, array, src, NONCONST)
+ {
+ rtx x = **iter;
+ if (COMMUTATIVE_ARITH_P (x)
+ && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
+ {
+ rtx tem = XEXP (x, 0);
+ SUBST (XEXP (x, 0), XEXP (x, 1));
+ SUBST (XEXP (x, 1), tem);
+ }
+ }
+
+ rtx *dst = &SET_DEST (pat);
+ if (GET_CODE (*dst) == ZERO_EXTRACT
+ && REG_P (XEXP (*dst, 0))
+ && CONST_INT_P (XEXP (*dst, 1))
+ && CONST_INT_P (XEXP (*dst, 2)))
+ {
+ rtx reg = XEXP (*dst, 0);
+ int width = INTVAL (XEXP (*dst, 1));
+ int offset = INTVAL (XEXP (*dst, 2));
+ machine_mode mode = GET_MODE (reg);
+ int reg_width = GET_MODE_PRECISION (mode);
+ if (BITS_BIG_ENDIAN)
+ offset = reg_width - width - offset;
+
+ wide_int mask = wi::shifted_mask (offset, width, true, reg_width);
+ rtx x = gen_rtx_AND (mode, reg, immed_wide_int_const (mask, mode));
+ rtx y = simplify_gen_binary (ASHIFT, mode, SET_SRC (pat),
+ GEN_INT (offset));
+ wide_int mask2 = wi::shifted_mask (offset, width, false, reg_width);
+ y = simplify_gen_binary (AND, mode, y,
+ immed_wide_int_const (mask2, mode));
+ rtx z = simplify_gen_binary (IOR, mode, x, y);
+ SUBST (SET_DEST (pat), reg);
+ SUBST (SET_SRC (pat), z);
+
+ changed = true;
+ }
+
return changed;
}
@@ -11172,7 +11226,7 @@ change_zero_ext (rtx *src)
static int
recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
{
- rtx pat = PATTERN (insn);
+ rtx pat = *pnewpat;
int insn_code_number = recog_for_combine_1 (pnewpat, insn, pnotes);
if (insn_code_number >= 0 || check_asm_operands (pat))
return insn_code_number;
@@ -11181,7 +11235,7 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
bool changed = false;
if (GET_CODE (pat) == SET)
- changed = change_zero_ext (&SET_SRC (pat));
+ changed = change_zero_ext (pat);
else if (GET_CODE (pat) == PARALLEL)
{
int i;
@@ -11189,7 +11243,7 @@ recog_for_combine (rtx *pnewpat, rtx_insn *insn, rtx *pnotes)
{
rtx set = XVECEXP (pat, 0, i);
if (GET_CODE (set) == SET)
- changed |= change_zero_ext (&SET_SRC (set));
+ changed |= change_zero_ext (set);
}
}
@@ -11367,6 +11421,7 @@ simplify_compare_const (enum rtx_code code, machine_mode mode,
const_op -= 1;
code = LE;
/* ... fall through to LE case below. */
+ gcc_fallthrough ();
}
else
break;
@@ -11396,6 +11451,7 @@ simplify_compare_const (enum rtx_code code, machine_mode mode,
const_op -= 1;
code = GT;
/* ... fall through to GT below. */
+ gcc_fallthrough ();
}
else
break;
@@ -12413,19 +12469,23 @@ simplify_comparison (enum rtx_code code, rtx *pop0, rtx *pop1)
care bits and we can assume they have any convenient value. So
making the transformation is safe.
- 2. SUBREG_REG (op0) is a memory and LOAD_EXTEND_OP is not defined.
+ 2. SUBREG_REG (op0) is a memory and LOAD_EXTEND_OP is UNKNOWN.
In this case the upper bits of op0 are undefined. We should not make
the simplification in that case as we do not know the contents of
those bits.
- 3. SUBREG_REG (op0) is a memory and LOAD_EXTEND_OP is defined and not
- UNKNOWN. In that case we know those bits are zeros or ones. We must
- also be sure that they are the same as the upper bits of op1.
+ 3. SUBREG_REG (op0) is a memory and LOAD_EXTEND_OP is not UNKNOWN.
+ In that case we know those bits are zeros or ones. We must also be
+ sure that they are the same as the upper bits of op1.
We can never remove a SUBREG for a non-equality comparison because
the sign bit is in a different place in the underlying object. */
- op0 = make_compound_operation (op0, op1 == const0_rtx ? COMPARE : SET);
+ rtx_code op0_mco_code = SET;
+ if (op1 == const0_rtx)
+ op0_mco_code = code == NE || code == EQ ? EQ : COMPARE;
+
+ op0 = make_compound_operation (op0, op0_mco_code);
op1 = make_compound_operation (op1, SET);
if (GET_CODE (op0) == SUBREG && subreg_lowpart_p (op0)
diff --git a/gcc/common.opt b/gcc/common.opt
index 20dbfc1d6a1..314145a09d3 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -58,10 +58,6 @@ int flag_incremental_link = 0
Variable
int flag_complex_method = 1
-; Nonzero if subexpressions must be evaluated from left-to-right.
-Variable
-int flag_evaluation_order = 0
-
; Language specific warning pass for unused results.
Variable
bool flag_warn_unused_result = false
@@ -668,7 +664,25 @@ Warn about returning a pointer/reference to a local or temporary variable.
Wshadow
Common Var(warn_shadow) Warning
-Warn when one local variable shadows another.
+Warn when one variable shadows another. Same as -Wshadow=global.
+
+Wshadow=global
+Common Warning Alias(Wshadow)
+Warn when one variable shadows another (globally).
+
+Wshadow=local
+Common Var(warn_shadow_local) Warning EnabledBy(Wshadow)
+Warn when one local variable shadows another local variable or parameter.
+
+Wshadow-local
+Common Warning Undocumented Alias(Wshadow=local)
+
+Wshadow=compatible-local
+Common Var(warn_shadow_compatible_local) Warning EnabledBy(Wshadow=local)
+Warn when one local variable shadows another local variable or parameter of compatible type.
+
+Wshadow-compatible-local
+Common Warning Undocumented Alias(Wshadow=compatible-local)
Wstack-protector
Common Var(warn_stack_protect) Warning
@@ -889,7 +903,8 @@ Driver Undocumented
; identity, such as ia32 calling convention attributes (stdcall, etc.)
; Default in G++ 6 (set in c_common_post_options).
;
-; 11: The version of the ABI that corrects mangling of sizeof... expressions.
+; 11: The version of the ABI that corrects mangling of sizeof... expressions
+; and introduces new inheriting constructor handling.
; Default in G++ 7.
;
; Additional positive integers will be assigned as new versions of
@@ -967,6 +982,9 @@ fsanitize-recover
Common Report
This switch is deprecated; use -fsanitize-recover= instead.
+fsanitize-address-use-after-scope
+Common Driver Report Var(flag_sanitize_address_use_after_scope) Init(0)
+
fsanitize-undefined-trap-on-error
Common Driver Report Var(flag_sanitize_undefined_trap_on_error) Init(0)
Use trap instead of a library function for undefined behavior sanitization.
diff --git a/gcc/compare-elim.c b/gcc/compare-elim.c
index 2820de9ae8d..c66f13152ce 100644
--- a/gcc/compare-elim.c
+++ b/gcc/compare-elim.c
@@ -627,7 +627,7 @@ try_eliminate_compare (struct comparison *cmp)
/* We've reached PREV_CLOBBER without finding a modification of IN_A.
Validate that PREV_CLOBBER itself does in fact refer to IN_A. Do
recall that we've already validated the shape of PREV_CLOBBER. */
- rtx insn = cmp->prev_clobber;
+ rtx_insn *insn = cmp->prev_clobber;
x = XVECEXP (PATTERN (insn), 0, 0);
if (rtx_equal_p (SET_DEST (x), in_a))
cmp_src = SET_SRC (x);
diff --git a/gcc/config.gcc b/gcc/config.gcc
index f9148dd95ce..3e0be229765 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1049,6 +1049,7 @@ arm-wrs-vxworks)
tm_file="elfos.h arm/elf.h arm/aout.h ${tm_file} vx-common.h vxworks.h arm/vxworks.h"
extra_options="${extra_options} arm/vxworks.opt"
tmake_file="${tmake_file} arm/t-arm arm/t-vxworks"
+ target_cpu_cname="arm6"
;;
arm*-*-freebsd*) # ARM FreeBSD EABI
tm_file="dbxelf.h elfos.h ${fbsd_tm_file} arm/elf.h"
@@ -1061,11 +1062,15 @@ arm*-*-freebsd*) # ARM FreeBSD EABI
tm_file="${tm_file} arm/bpabi.h arm/freebsd.h arm/aout.h arm/arm.h"
case $target in
armv6*-*-freebsd*)
+ target_cpu_cname="arm1176jzfs"
tm_defines="${tm_defines} TARGET_FREEBSD_ARMv6=1"
if test $fbsd_major -ge 11; then
tm_defines="${tm_defines} TARGET_FREEBSD_ARM_HARD_FLOAT=1"
fi
;;
+ *)
+ target_cpu_cname="arm9"
+ ;;
esac
with_tls=${with_tls:-gnu}
;;
@@ -1073,6 +1078,7 @@ arm*-*-netbsdelf*)
tm_file="dbxelf.h elfos.h netbsd.h netbsd-elf.h arm/elf.h arm/aout.h ${tm_file} arm/netbsd-elf.h"
extra_options="${extra_options} netbsd.opt netbsd-elf.opt"
tmake_file="${tmake_file} arm/t-arm"
+ target_cpu_cname="arm6"
;;
arm*-*-linux-*) # ARM GNU/Linux with ELF
tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h arm/elf.h arm/linux-gas.h arm/linux-elf.h"
@@ -1084,6 +1090,7 @@ arm*-*-linux-*) # ARM GNU/Linux with ELF
esac
tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf arm/t-bpabi arm/t-linux-eabi"
tm_file="$tm_file arm/bpabi.h arm/linux-eabi.h arm/aout.h vxworks-dummy.h arm/arm.h"
+ target_cpu_cname="arm10tdmi"
# Define multilib configuration for arm-linux-androideabi.
case ${target} in
*-androideabi)
@@ -1098,6 +1105,7 @@ arm*-*-uclinux*eabi*) # ARM ucLinux
tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/linux-gas.h arm/uclinux-elf.h glibc-stdint.h"
tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf arm/t-bpabi"
tm_file="$tm_file arm/bpabi.h arm/uclinux-eabi.h arm/aout.h vxworks-dummy.h arm/arm.h"
+ target_cpu_cname="arm7tdmi"
# The EABI requires the use of __cxa_atexit.
default_use_cxa_atexit=yes
;;
@@ -1106,6 +1114,7 @@ arm*-*-phoenix*)
tm_file="${tm_file} newlib-stdint.h phoenix.h"
tm_file="${tm_file} arm/aout.h arm/arm.h"
tmake_file="${tmake_file} arm/t-arm arm/t-bpabi arm/t-phoenix"
+ target_cpu_cname="arm7tdmi"
;;
arm*-*-eabi* | arm*-*-symbianelf* | arm*-*-rtems*)
case ${target} in
@@ -1115,6 +1124,7 @@ arm*-*-eabi* | arm*-*-symbianelf* | arm*-*-rtems*)
default_use_cxa_atexit=yes
tm_file="dbxelf.h elfos.h arm/unknown-elf.h arm/elf.h arm/bpabi.h"
tmake_file="${tmake_file} arm/t-arm arm/t-arm-elf"
+ target_cpu_cname="arm7tdmi"
case ${target} in
arm*-*-eabi*)
tm_file="$tm_file newlib-stdint.h"
@@ -1130,6 +1140,7 @@ arm*-*-eabi* | arm*-*-symbianelf* | arm*-*-rtems*)
# We do not include t-bpabi for Symbian OS because the system
# provides its own implementation of the BPABI functions.
tmake_file="${tmake_file} arm/t-symbian"
+ target_cpu_cname="arm10tdmi"
;;
esac
tm_file="${tm_file} arm/aout.h vxworks-dummy.h arm/arm.h"
@@ -3638,8 +3649,10 @@ case "${target}" in
${srcdir}/config/arm/arm-cores.def | \
sed -e 's/^[^,]*,[ ]*//' | \
sed -e 's/,.*$//'`
- eval "target_${which}_cname=$new_val"
- echo "For $val real value is $new_val"
+ if [ x"$val" != x ] ; then
+ eval "target_${which}_cname=$new_val"
+ echo "For $val real value is $new_val"
+ fi
true
else
echo "Unknown CPU used in --with-$which=$val" 1>&2
@@ -4124,16 +4137,6 @@ case "${target}" in
(at="/opt/$with_advance_toolchain"
echo "/* Use Advance Toolchain $at */"
echo
- echo "#ifndef USE_AT_INCLUDE_FILES"
- echo "#define USE_AT_INCLUDE_FILES 1"
- echo "#endif"
- echo
- echo "#if USE_AT_INCLUDE_FILES"
- echo "#undef INCLUDE_EXTRA_SPEC"
- echo "#define INCLUDE_EXTRA_SPEC" \
- "\"-isystem $at/include\""
- echo "#endif"
- echo
echo "#undef LINK_OS_EXTRA_SPEC32"
echo "#define LINK_OS_EXTRA_SPEC32" \
"\"%(link_os_new_dtags)" \
@@ -4313,7 +4316,7 @@ case ${target} in
arm*-*-*)
if test x$target_cpu_cname = x
then
- target_cpu_default2=TARGET_CPU_generic
+ target_cpu_default2=TARGET_CPU_arm6
else
target_cpu_default2=TARGET_CPU_$target_cpu_cname
fi
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 9ce7f000509..89bdcb3f7ed 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -5705,6 +5705,26 @@
[(set_attr "type" "crypto_sha1_fast")]
)
+(define_insn "aarch64_crypto_sha1hv4si"
+ [(set (match_operand:SI 0 "register_operand" "=w")
+ (unspec:SI [(vec_select:SI (match_operand:V4SI 1 "register_operand" "w")
+ (parallel [(const_int 0)]))]
+ UNSPEC_SHA1H))]
+ "TARGET_SIMD && TARGET_CRYPTO && !BYTES_BIG_ENDIAN"
+ "sha1h\\t%s0, %s1"
+ [(set_attr "type" "crypto_sha1_fast")]
+)
+
+(define_insn "aarch64_be_crypto_sha1hv4si"
+ [(set (match_operand:SI 0 "register_operand" "=w")
+ (unspec:SI [(vec_select:SI (match_operand:V4SI 1 "register_operand" "w")
+ (parallel [(const_int 3)]))]
+ UNSPEC_SHA1H))]
+ "TARGET_SIMD && TARGET_CRYPTO && BYTES_BIG_ENDIAN"
+ "sha1h\\t%s0, %s1"
+ [(set_attr "type" "crypto_sha1_fast")]
+)
+
(define_insn "aarch64_crypto_sha1su1v4si"
[(set (match_operand:V4SI 0 "register_operand" "=w")
(unspec:V4SI [(match_operand:V4SI 1 "register_operand" "0")
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index df74ad96949..b7d4640826a 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -2936,12 +2936,18 @@ aarch64_layout_frame (void)
cfun->machine->frame.laid_out = true;
}
+/* Return true if the register REGNO is saved on entry to
+ the current function. */
+
static bool
aarch64_register_saved_on_entry (int regno)
{
return cfun->machine->frame.reg_offset[regno] >= 0;
}
+/* Return the next register up from REGNO up to LIMIT for the callee
+ to save. */
+
static unsigned
aarch64_next_callee_save (unsigned regno, unsigned limit)
{
@@ -2950,6 +2956,9 @@ aarch64_next_callee_save (unsigned regno, unsigned limit)
return regno;
}
+/* Push the register number REGNO of mode MODE to the stack with write-back
+ adjusting the stack by ADJUSTMENT. */
+
static void
aarch64_pushwb_single_reg (machine_mode mode, unsigned regno,
HOST_WIDE_INT adjustment)
@@ -2966,6 +2975,10 @@ aarch64_pushwb_single_reg (machine_mode mode, unsigned regno,
RTX_FRAME_RELATED_P (insn) = 1;
}
+/* Generate and return an instruction to store the pair of registers
+ REG and REG2 of mode MODE to location BASE with write-back adjusting
+ the stack location BASE by ADJUSTMENT. */
+
static rtx
aarch64_gen_storewb_pair (machine_mode mode, rtx base, rtx reg, rtx reg2,
HOST_WIDE_INT adjustment)
@@ -2985,6 +2998,9 @@ aarch64_gen_storewb_pair (machine_mode mode, rtx base, rtx reg, rtx reg2,
}
}
+/* Push registers numbered REGNO1 and REGNO2 to the stack, adjusting the
+ stack pointer by ADJUSTMENT. */
+
static void
aarch64_push_regs (unsigned regno1, unsigned regno2, HOST_WIDE_INT adjustment)
{
@@ -3004,6 +3020,9 @@ aarch64_push_regs (unsigned regno1, unsigned regno2, HOST_WIDE_INT adjustment)
RTX_FRAME_RELATED_P (insn) = 1;
}
+/* Load the pair of register REG, REG2 of mode MODE from stack location BASE,
+ adjusting it by ADJUSTMENT afterwards. */
+
static rtx
aarch64_gen_loadwb_pair (machine_mode mode, rtx base, rtx reg, rtx reg2,
HOST_WIDE_INT adjustment)
@@ -3021,6 +3040,10 @@ aarch64_gen_loadwb_pair (machine_mode mode, rtx base, rtx reg, rtx reg2,
}
}
+/* Pop the two registers numbered REGNO1, REGNO2 from the stack, adjusting it
+ afterwards by ADJUSTMENT and writing the appropriate REG_CFA_RESTORE notes
+ into CFI_OPS. */
+
static void
aarch64_pop_regs (unsigned regno1, unsigned regno2, HOST_WIDE_INT adjustment,
rtx *cfi_ops)
@@ -3045,6 +3068,9 @@ aarch64_pop_regs (unsigned regno1, unsigned regno2, HOST_WIDE_INT adjustment,
}
}
+/* Generate and return a store pair instruction of mode MODE to store
+ register REG1 to MEM1 and register REG2 to MEM2. */
+
static rtx
aarch64_gen_store_pair (machine_mode mode, rtx mem1, rtx reg1, rtx mem2,
rtx reg2)
@@ -3062,6 +3088,9 @@ aarch64_gen_store_pair (machine_mode mode, rtx mem1, rtx reg1, rtx mem2,
}
}
+/* Generate and regurn a load pair isntruction of mode MODE to load register
+ REG1 from MEM1 and register REG2 from MEM2. */
+
static rtx
aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
rtx mem2)
@@ -3079,6 +3108,9 @@ aarch64_gen_load_pair (machine_mode mode, rtx reg1, rtx mem1, rtx reg2,
}
}
+/* Emit code to save the callee-saved registers from register number START
+ to LIMIT to the stack at the location starting at offset START_OFFSET,
+ skipping any write-back candidates if SKIP_WB is true. */
static void
aarch64_save_callee_saves (machine_mode mode, HOST_WIDE_INT start_offset,
@@ -3137,6 +3169,11 @@ aarch64_save_callee_saves (machine_mode mode, HOST_WIDE_INT start_offset,
}
}
+/* Emit code to restore the callee registers of mode MODE from register
+ number START up to and including LIMIT. Restore from the stack offset
+ START_OFFSET, skipping any write-back candidates if SKIP_WB is true.
+ Write the appropriate REG_CFA_RESTORE notes into CFI_OPS. */
+
static void
aarch64_restore_callee_saves (machine_mode mode,
HOST_WIDE_INT start_offset, unsigned start,
@@ -13197,7 +13234,7 @@ aarch64_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
}
static rtx
-aarch64_gen_ccmp_first (rtx *prep_seq, rtx *gen_seq,
+aarch64_gen_ccmp_first (rtx_insn **prep_seq, rtx_insn **gen_seq,
int code, tree treeop0, tree treeop1)
{
machine_mode op_mode, cmp_mode, cc_mode = CCmode;
@@ -13271,8 +13308,8 @@ aarch64_gen_ccmp_first (rtx *prep_seq, rtx *gen_seq,
}
static rtx
-aarch64_gen_ccmp_next (rtx *prep_seq, rtx *gen_seq, rtx prev, int cmp_code,
- tree treeop0, tree treeop1, int bit_code)
+aarch64_gen_ccmp_next (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev,
+ int cmp_code, tree treeop0, tree treeop1, int bit_code)
{
rtx op0, op1, target;
machine_mode op_mode, cmp_mode, cc_mode = CCmode;
@@ -13281,7 +13318,7 @@ aarch64_gen_ccmp_next (rtx *prep_seq, rtx *gen_seq, rtx prev, int cmp_code,
struct expand_operand ops[6];
int aarch64_cond;
- push_to_sequence ((rtx_insn*) *prep_seq);
+ push_to_sequence (*prep_seq);
expand_operands (treeop0, treeop1, NULL_RTX, &op0, &op1, EXPAND_NORMAL);
op_mode = GET_MODE (op0);
@@ -13347,7 +13384,7 @@ aarch64_gen_ccmp_next (rtx *prep_seq, rtx *gen_seq, rtx prev, int cmp_code,
create_fixed_operand (&ops[4], prev);
create_fixed_operand (&ops[5], GEN_INT (aarch64_cond));
- push_to_sequence ((rtx_insn*) *gen_seq);
+ push_to_sequence (*gen_seq);
if (!maybe_expand_insn (icode, 6, ops))
{
end_sequence ();
diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md
index 6afaf906915..46eaa30b159 100644
--- a/gcc/config/aarch64/aarch64.md
+++ b/gcc/config/aarch64/aarch64.md
@@ -639,7 +639,8 @@
[(set (pc) (if_then_else
(EQL (zero_extract:DI (match_operand:GPI 0 "register_operand" "r")
(const_int 1)
- (match_operand 1 "const_int_operand" "n"))
+ (match_operand 1
+ "aarch64_simd_shift_imm_<mode>" "n"))
(const_int 0))
(label_ref (match_operand 2 "" ""))
(pc)))
@@ -1605,25 +1606,12 @@
(match_operand:GPI 2 "aarch64_pluslong_operand" "")))]
""
{
- if (aarch64_pluslong_strict_immedate (operands[2], <MODE>mode))
- {
- /* Give CSE the opportunity to share this constant across additions. */
- if (!cse_not_expected && can_create_pseudo_p ())
- operands[2] = force_reg (<MODE>mode, operands[2]);
-
- /* Split will refuse to operate on a modification to the stack pointer.
- Aid the prologue and epilogue expanders by splitting this now. */
- else if (reload_completed && operands[0] == stack_pointer_rtx)
- {
- HOST_WIDE_INT i = INTVAL (operands[2]);
- HOST_WIDE_INT s = (i >= 0 ? i & 0xfff : -(-i & 0xfff));
- emit_insn (gen_rtx_SET (operands[0],
- gen_rtx_PLUS (<MODE>mode, operands[1],
- GEN_INT (i - s))));
- operands[1] = operands[0];
- operands[2] = GEN_INT (s);
- }
- }
+ /* If the constant is too large for a single instruction and isn't frame
+ based, split off the immediate so it is available for CSE. */
+ if (!aarch64_plus_immediate (operands[2], <MODE>mode)
+ && can_create_pseudo_p ()
+ && !REGNO_PTR_FRAME_P (REGNO (operands[1])))
+ operands[2] = force_reg (<MODE>mode, operands[2]);
})
(define_insn "*add<mode>3_aarch64"
@@ -4281,19 +4269,28 @@
(define_expand "<optab>"
[(set (match_operand:DI 0 "register_operand" "=r")
- (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand" "r")
- (match_operand 2 "const_int_operand" "n")
- (match_operand 3 "const_int_operand" "n")))]
- ""
+ (ANY_EXTRACT:DI (match_operand:DI 1 "register_operand")
+ (match_operand 2
+ "aarch64_simd_shift_imm_offset_di")
+ (match_operand 3 "aarch64_simd_shift_imm_di")))]
""
+ {
+ if (!IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
+ 1, GET_MODE_BITSIZE (DImode) - 1))
+ FAIL;
+ }
)
+
(define_insn "*<optab><mode>"
[(set (match_operand:GPI 0 "register_operand" "=r")
(ANY_EXTRACT:GPI (match_operand:GPI 1 "register_operand" "r")
- (match_operand 2 "const_int_operand" "n")
- (match_operand 3 "const_int_operand" "n")))]
- ""
+ (match_operand 2
+ "aarch64_simd_shift_imm_offset_<mode>" "n")
+ (match_operand 3
+ "aarch64_simd_shift_imm_<mode>" "n")))]
+ "IN_RANGE (INTVAL (operands[2]) + INTVAL (operands[3]),
+ 1, GET_MODE_BITSIZE (<MODE>mode) - 1)"
"<su>bfx\\t%<w>0, %<w>1, %3, %2"
[(set_attr "type" "bfm")]
)
diff --git a/gcc/config/aarch64/driver-aarch64.c b/gcc/config/aarch64/driver-aarch64.c
index 658a4cd72e9..c21942c1aab 100644
--- a/gcc/config/aarch64/driver-aarch64.c
+++ b/gcc/config/aarch64/driver-aarch64.c
@@ -169,7 +169,6 @@ host_detect_local_cpu (int argc, const char **argv)
bool tune = false;
bool cpu = false;
unsigned int i = 0;
- unsigned int core_idx = 0;
unsigned char imp = INVALID_IMP;
unsigned int cores[2] = { INVALID_CORE, INVALID_CORE };
unsigned int n_cores = 0;
@@ -219,18 +218,13 @@ host_detect_local_cpu (int argc, const char **argv)
if (strstr (buf, "part") != NULL)
{
unsigned ccore = parse_field (buf);
- for (i = 0; aarch64_cpu_data[i].name != NULL; i++)
- if (ccore == aarch64_cpu_data[i].part_no
- && !contains_core_p (cores, ccore))
- {
- if (n_cores == 2)
- goto not_found;
-
- cores[n_cores++] = ccore;
- core_idx = i;
- arch_id = aarch64_cpu_data[i].arch;
- break;
- }
+ if (!contains_core_p (cores, ccore))
+ {
+ if (n_cores == 2)
+ goto not_found;
+
+ cores[n_cores++] = ccore;
+ }
continue;
}
if (!tune && !processed_exts && strstr (buf, "Features") != NULL)
@@ -276,11 +270,19 @@ host_detect_local_cpu (int argc, const char **argv)
if (n_cores == 0 || n_cores > 2 || imp == INVALID_IMP)
goto not_found;
- if (arch && !arch_id)
- goto not_found;
-
if (arch)
{
+ /* Search for one of the cores in the list. */
+ for (i = 0; aarch64_cpu_data[i].name != NULL; i++)
+ if (aarch64_cpu_data[i].implementer_id == imp
+ && contains_core_p (cores, aarch64_cpu_data[i].part_no))
+ {
+ arch_id = aarch64_cpu_data[i].arch;
+ break;
+ }
+ if (!arch_id)
+ goto not_found;
+
struct aarch64_arch_driver_info* arch_info = get_arch_from_id (arch_id);
/* We got some arch indentifier that's not in aarch64-arches.def? */
@@ -312,7 +314,15 @@ host_detect_local_cpu (int argc, const char **argv)
/* The simple, non-big.LITTLE case. */
else
{
- if (aarch64_cpu_data[core_idx].implementer_id != imp)
+ int core_idx = -1;
+ for (i = 0; aarch64_cpu_data[i].name != NULL; i++)
+ if (cores[0] == aarch64_cpu_data[i].part_no
+ && aarch64_cpu_data[i].implementer_id == imp)
+ {
+ core_idx = i;
+ break;
+ }
+ if (core_idx == -1)
goto not_found;
res = concat ("-m", cpu ? "cpu" : "tune", "=",
diff --git a/gcc/config/aarch64/t-aarch64 b/gcc/config/aarch64/t-aarch64
index 04eb63666e8..b461eb5bede 100644
--- a/gcc/config/aarch64/t-aarch64
+++ b/gcc/config/aarch64/t-aarch64
@@ -52,7 +52,7 @@ aarch-common.o: $(srcdir)/config/arm/aarch-common.c $(CONFIG_H) $(SYSTEM_H) \
$(srcdir)/config/arm/aarch-common.c
aarch64-c.o: $(srcdir)/config/aarch64/aarch64-c.c $(CONFIG_H) $(SYSTEM_H) \
- coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
+ coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H) $(TARGET_H)
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/aarch64/aarch64-c.c
diff --git a/gcc/config/alpha/alpha-passes.def b/gcc/config/alpha/alpha-passes.def
index d960e7cfc06..977605a105a 100644
--- a/gcc/config/alpha/alpha-passes.def
+++ b/gcc/config/alpha/alpha-passes.def
@@ -17,5 +17,5 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
- INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_align_insns);
INSERT_PASS_AFTER (pass_convert_to_eh_region_ranges, 1, pass_handle_trap_shadows);
+ INSERT_PASS_BEFORE (pass_shorten_branches, 1, pass_align_insns);
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 7f5396725b0..6d390ae6dfa 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -1017,7 +1017,8 @@ alpha_legitimize_address_1 (rtx x, rtx scratch, machine_mode mode)
&& GET_MODE_SIZE (mode) <= UNITS_PER_WORD
&& symbolic_operand (x, Pmode))
{
- rtx r0, r16, eqv, tga, tp, insn, dest, seq;
+ rtx r0, r16, eqv, tga, tp, dest, seq;
+ rtx_insn *insn;
switch (tls_symbolic_operand_type (x))
{
@@ -1025,66 +1026,70 @@ alpha_legitimize_address_1 (rtx x, rtx scratch, machine_mode mode)
break;
case TLS_MODEL_GLOBAL_DYNAMIC:
- start_sequence ();
+ {
+ start_sequence ();
- r0 = gen_rtx_REG (Pmode, 0);
- r16 = gen_rtx_REG (Pmode, 16);
- tga = get_tls_get_addr ();
- dest = gen_reg_rtx (Pmode);
- seq = GEN_INT (alpha_next_sequence_number++);
+ r0 = gen_rtx_REG (Pmode, 0);
+ r16 = gen_rtx_REG (Pmode, 16);
+ tga = get_tls_get_addr ();
+ dest = gen_reg_rtx (Pmode);
+ seq = GEN_INT (alpha_next_sequence_number++);
- emit_insn (gen_movdi_er_tlsgd (r16, pic_offset_table_rtx, x, seq));
- insn = gen_call_value_osf_tlsgd (r0, tga, seq);
- insn = emit_call_insn (insn);
- RTL_CONST_CALL_P (insn) = 1;
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
+ emit_insn (gen_movdi_er_tlsgd (r16, pic_offset_table_rtx, x, seq));
+ rtx val = gen_call_value_osf_tlsgd (r0, tga, seq);
+ insn = emit_call_insn (val);
+ RTL_CONST_CALL_P (insn) = 1;
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
- insn = get_insns ();
- end_sequence ();
+ insn = get_insns ();
+ end_sequence ();
- emit_libcall_block (insn, dest, r0, x);
- return dest;
+ emit_libcall_block (insn, dest, r0, x);
+ return dest;
+ }
case TLS_MODEL_LOCAL_DYNAMIC:
- start_sequence ();
+ {
+ start_sequence ();
- r0 = gen_rtx_REG (Pmode, 0);
- r16 = gen_rtx_REG (Pmode, 16);
- tga = get_tls_get_addr ();
- scratch = gen_reg_rtx (Pmode);
- seq = GEN_INT (alpha_next_sequence_number++);
+ r0 = gen_rtx_REG (Pmode, 0);
+ r16 = gen_rtx_REG (Pmode, 16);
+ tga = get_tls_get_addr ();
+ scratch = gen_reg_rtx (Pmode);
+ seq = GEN_INT (alpha_next_sequence_number++);
- emit_insn (gen_movdi_er_tlsldm (r16, pic_offset_table_rtx, seq));
- insn = gen_call_value_osf_tlsldm (r0, tga, seq);
- insn = emit_call_insn (insn);
- RTL_CONST_CALL_P (insn) = 1;
- use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
+ emit_insn (gen_movdi_er_tlsldm (r16, pic_offset_table_rtx, seq));
+ rtx val = gen_call_value_osf_tlsldm (r0, tga, seq);
+ insn = emit_call_insn (val);
+ RTL_CONST_CALL_P (insn) = 1;
+ use_reg (&CALL_INSN_FUNCTION_USAGE (insn), r16);
- insn = get_insns ();
- end_sequence ();
+ insn = get_insns ();
+ end_sequence ();
- eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
- UNSPEC_TLSLDM_CALL);
- emit_libcall_block (insn, scratch, r0, eqv);
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_TLSLDM_CALL);
+ emit_libcall_block (insn, scratch, r0, eqv);
- eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPREL);
- eqv = gen_rtx_CONST (Pmode, eqv);
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_DTPREL);
+ eqv = gen_rtx_CONST (Pmode, eqv);
- if (alpha_tls_size == 64)
- {
- dest = gen_reg_rtx (Pmode);
- emit_insn (gen_rtx_SET (dest, eqv));
- emit_insn (gen_adddi3 (dest, dest, scratch));
- return dest;
- }
- if (alpha_tls_size == 32)
- {
- insn = gen_rtx_HIGH (Pmode, eqv);
- insn = gen_rtx_PLUS (Pmode, scratch, insn);
- scratch = gen_reg_rtx (Pmode);
- emit_insn (gen_rtx_SET (scratch, insn));
- }
- return gen_rtx_LO_SUM (Pmode, scratch, eqv);
+ if (alpha_tls_size == 64)
+ {
+ dest = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (dest, eqv));
+ emit_insn (gen_adddi3 (dest, dest, scratch));
+ return dest;
+ }
+ if (alpha_tls_size == 32)
+ {
+ rtx temp = gen_rtx_HIGH (Pmode, eqv);
+ temp = gen_rtx_PLUS (Pmode, scratch, temp);
+ scratch = gen_reg_rtx (Pmode);
+ emit_insn (gen_rtx_SET (scratch, temp));
+ }
+ return gen_rtx_LO_SUM (Pmode, scratch, eqv);
+ }
case TLS_MODEL_INITIAL_EXEC:
eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, x), UNSPEC_TPREL);
@@ -1106,10 +1111,10 @@ alpha_legitimize_address_1 (rtx x, rtx scratch, machine_mode mode)
emit_insn (gen_get_thread_pointerdi (tp));
if (alpha_tls_size == 32)
{
- insn = gen_rtx_HIGH (Pmode, eqv);
- insn = gen_rtx_PLUS (Pmode, tp, insn);
+ rtx temp = gen_rtx_HIGH (Pmode, eqv);
+ temp = gen_rtx_PLUS (Pmode, tp, temp);
tp = gen_reg_rtx (Pmode);
- emit_insn (gen_rtx_SET (tp, insn));
+ emit_insn (gen_rtx_SET (tp, temp));
}
return gen_rtx_LO_SUM (Pmode, tp, eqv);
@@ -3059,7 +3064,7 @@ static void
alpha_emit_xfloating_libcall (rtx func, rtx target, rtx operands[],
int noperands, rtx equiv)
{
- rtx usage = NULL_RTX, tmp, reg;
+ rtx usage = NULL_RTX, reg;
int regno = 16, i;
start_sequence ();
@@ -3109,9 +3114,9 @@ alpha_emit_xfloating_libcall (rtx func, rtx target, rtx operands[],
gcc_unreachable ();
}
- tmp = gen_rtx_MEM (QImode, func);
- tmp = emit_call_insn (gen_call_value (reg, tmp, const0_rtx,
- const0_rtx, const0_rtx));
+ rtx mem = gen_rtx_MEM (QImode, func);
+ rtx_insn *tmp = emit_call_insn (gen_call_value (reg, mem, const0_rtx,
+ const0_rtx, const0_rtx));
CALL_INSN_FUNCTION_USAGE (tmp) = usage;
RTL_CONST_CALL_P (tmp) = 1;
diff --git a/gcc/config/arc/arc.c b/gcc/config/arc/arc.c
index 0e7b63dc6f7..5ba7ccc776f 100644
--- a/gcc/config/arc/arc.c
+++ b/gcc/config/arc/arc.c
@@ -4830,7 +4830,6 @@ static rtx
arc_emit_call_tls_get_addr (rtx sym, int reloc, rtx eqv)
{
rtx r0 = gen_rtx_REG (Pmode, R0_REG);
- rtx insns;
rtx call_fusage = NULL_RTX;
start_sequence ();
@@ -4847,7 +4846,7 @@ arc_emit_call_tls_get_addr (rtx sym, int reloc, rtx eqv)
RTL_PURE_CALL_P (call_insn) = 1;
add_function_usage_to (call_insn, call_fusage);
- insns = get_insns ();
+ rtx_insn *insns = get_insns ();
end_sequence ();
rtx dest = gen_reg_rtx (Pmode);
@@ -9021,10 +9020,7 @@ arc_process_double_reg_moves (rtx *operands)
rtx srcLow = simplify_gen_subreg (SImode, src, DFmode,
TARGET_BIG_ENDIAN ? 4 : 0);
- emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode,
- gen_rtvec (3, dest, srcHigh, srcLow),
- VUNSPEC_ARC_DEXCL_NORES));
-
+ emit_insn (gen_dexcl_2op (dest, srcHigh, srcLow));
}
else
gcc_unreachable ();
diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index b146f3a9a05..a4adce0812e 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -128,24 +128,6 @@ along with GCC; see the file COPYING3. If not see
%{!marclinux*: %{pg|p|profile:-marclinux_prof;: -marclinux}} \
%{!z:-z max-page-size=0x2000 -z common-page-size=0x2000} \
%{shared:-shared}"
-/* Like the standard LINK_COMMAND_SPEC, but add %G when building
- a shared library with -nostdlib, so that the hidden functions of libgcc
- will be incorporated.
- N.B., we don't want a plain -lgcc, as this would lead to re-exporting
- non-hidden functions, so we have to consider libgcc_s.so.* first, which in
- turn should be wrapped with --as-needed. */
-#define LINK_COMMAND_SPEC "\
-%{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
- %(linker) %l " LINK_PIE_SPEC "%X %{o*} %{A} %{d} %{e*} %{m} %{N} %{n} %{r}\
- %{s} %{t} %{u*} %{x} %{z} %{Z} %{!A:%{!nostdlib:%{!nostartfiles:%S}}}\
- %{static:} %{L*} %(mfwrap) %(link_libgcc) %o\
- %{fopenacc|fopenmp|%:gt(%{ftree-parallelize-loops=*:%*} 1):\
- %:include(libgomp.spec)%(link_gomp)}\
- %(mflib)\
- %{fprofile-arcs|fprofile-generate|coverage:-lgcov}\
- %{!nostdlib:%{!nodefaultlibs:%(link_ssp) %(link_gcc_c_sequence)}}\
- %{!A:%{!nostdlib:%{!nostartfiles:%E}}} %{T*} }}}}}}"
-
#else
#define LINK_SPEC "%{mbig-endian:-EB} %{EB} %{EL}\
%{pg|p:-marcelf_prof;mA7|mARC700|mcpu=arc700|mcpu=ARC700: -marcelf}"
@@ -409,8 +391,8 @@ if (GET_MODE_CLASS (MODE) == MODE_INT \
/* Define this as 1 if `char' should by default be signed; else as 0. */
#define DEFAULT_SIGNED_CHAR 0
-#define SIZE_TYPE "long unsigned int"
-#define PTRDIFF_TYPE "long int"
+#define SIZE_TYPE "unsigned int"
+#define PTRDIFF_TYPE "int"
#define WCHAR_TYPE "int"
#define WCHAR_TYPE_SIZE 32
@@ -1570,13 +1552,10 @@ extern int arc_return_address_regs[4];
/* Undo the effects of the movmem pattern presence on STORE_BY_PIECES_P . */
#define MOVE_RATIO(SPEED) ((SPEED) ? 15 : 3)
-/* Define this to be nonzero if shift instructions ignore all but the low-order
- few bits. Changed from 1 to 0 for rotate pattern testcases
- (e.g. 20020226-1.c). This change truncates the upper 27 bits of a word
- while rotating a word. Came to notice through a combine phase
- optimization viz. a << (32-b) is equivalent to a << (-b).
+/* Define this to be nonzero if shift instructions ignore all but the
+ low-order few bits.
*/
-#define SHIFT_COUNT_TRUNCATED 0
+#define SHIFT_COUNT_TRUNCATED 1
/* Value is 1 if truncating an integer of INPREC bits to OUTPREC bits
is done just by pretending it is already truncated. */
diff --git a/gcc/config/arc/arc.md b/gcc/config/arc/arc.md
index e127d5b0352..7147fbdb244 100644
--- a/gcc/config/arc/arc.md
+++ b/gcc/config/arc/arc.md
@@ -704,9 +704,9 @@
; the iscompact attribute allows the epilogue expander to know for which
; insns it should lengthen the return insn.
; N.B. operand 1 of alternative 7 expands into pcl,symbol@gotpc .
-(define_insn "*movsi_insn" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
- [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q, w, h, w,w, w, w, w, w,???w, ?w, w,Rcq#q, w,Rcq, S, Us<,RcqRck,!*x, r,!*Rsd,!*Rcd,r,Ucm, Usd,m,???m,VUsc,VUsc")
- (match_operand:SI 1 "move_src_operand" " cL, cP,Rcq#q,hCm1,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,?Cal, T,Rcq,RcqRck, Us>,Usd,Ucm, Usd, Ucd,m, w,!*Rzd,c,?Rac, Cm3, C32"))]
+(define_insn "*movsi_insn" ; 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
+ [(set (match_operand:SI 0 "move_dest_operand" "=Rcq,Rcq#q, w, h, w,w, w, w, w, w,???w, ?w, w,Rcq#q, w,Rcq, S, Us<,RcqRck,!*x, r,!*Rsd,!*Rcd,r,Ucm, Usd,m,???m,VUsc,VUsc")
+ (match_operand:SI 1 "move_src_operand" " cL, cP,Rcq#q,hPCm1,cL,I,Crr,Clo,Chi,Cbi,?Rac,Cpc,Clb, ?Cal,?Cal, T,Rcq,RcqRck, Us>,Usd,Ucm, Usd, Ucd,m, w,!*Rzd,c,?Rac, Cm3, C32"))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
|| (CONSTANT_P (operands[1])
@@ -751,7 +751,7 @@
; of Crr to 4.
(set_attr "length" "*,*,*,*,4,4,4,4,4,4,4,8,8,*,8,*,*,*,*,*,4,*,4,*,*,*,*,*,4,8")
(set_attr "predicable" "yes,no,yes,no,yes,no,no,no,no,no,yes,no,no,yes,yes,no,no,no,no,no,no,no,no,no,no,no,no,no,no,no")
- (set_attr "cpu_facility" "*,*,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
+ (set_attr "cpu_facility" "av1,av1,av1,av2,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,av2,av2,*,*,av2,*,*,av2,*")])
;; Sometimes generated by the epilogue code. We don't want to
;; recognize these addresses in general, because the limm is costly,
@@ -1088,12 +1088,9 @@
(match_operand:DI 1 "general_operand" ""))]
""
"
-{
- /* Everything except mem = const or mem = mem can be done easily. */
-
- if (GET_CODE (operands[0]) == MEM)
- operands[1] = force_reg (DImode, operands[1]);
-}")
+ if (prepare_move_operands (operands, DImode))
+ DONE;
+ ")
(define_insn_and_split "*movdi_insn"
[(set (match_operand:DI 0 "move_dest_operand" "=w, w,r,m")
@@ -1140,7 +1137,7 @@
;; Floating point move insns.
(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
+ [(set (match_operand:SF 0 "move_dest_operand" "")
(match_operand:SF 1 "general_operand" ""))]
""
"if (prepare_move_operands (operands, SFmode)) DONE;")
@@ -1161,7 +1158,7 @@
(set_attr "iscompact" "true,false,false,false,false")])
(define_expand "movdf"
- [(set (match_operand:DF 0 "nonimmediate_operand" "")
+ [(set (match_operand:DF 0 "move_dest_operand" "")
(match_operand:DF 1 "general_operand" ""))]
""
"if (prepare_move_operands (operands, DFmode)) DONE;")
@@ -1231,12 +1228,18 @@
; second time to put back the contents which the first DEXCLx
; will have overwritten
; dexcl2 r0, r1, r0
- (set (match_dup 4) ; aka r0result
- ; aka DF, r1, r0
- (unspec_volatile:SI [(match_dup 1) (match_dup 5) (match_dup 4)] VUNSPEC_ARC_DEXCL ))
+ (parallel [
+ (set (match_dup 4) ; aka r0result
+ ; aka DF, r1, r0
+ (unspec_volatile:SI [(match_dup 5) (match_dup 4)]
+ VUNSPEC_ARC_DEXCL))
+ (clobber (match_dup 1))
+ ])
; Generate the second, which makes sure operand5 and operand4 values
; are put back in the Dx register properly.
- (unspec_volatile:SI [(match_dup 1) (match_dup 5) (match_dup 4)] VUNSPEC_ARC_DEXCL_NORES )
+ (set (match_dup 1) (unspec_volatile:DF
+ [(match_dup 5) (match_dup 4)]
+ VUNSPEC_ARC_DEXCL_NORES))
; Note: we cannot use a (clobber (match_scratch)) here because
; the combine pass will end up replacing uses of it with 0
diff --git a/gcc/config/arc/constraints.md b/gcc/config/arc/constraints.md
index b7bf2d39c4e..8eccb2fdfe3 100644
--- a/gcc/config/arc/constraints.md
+++ b/gcc/config/arc/constraints.md
@@ -256,7 +256,8 @@
"@internal
constant for a highpart that can be checked with a shift (asr.f 0,rn,m)"
(and (match_code "const_int")
- (match_test "IS_POWEROF2_P (-ival)")))
+ (match_test "IS_POWEROF2_P (-ival)")
+ (match_test "TARGET_BARREL_SHIFTER")))
(define_constraint "Clo"
"@internal
diff --git a/gcc/config/arc/fpu.md b/gcc/config/arc/fpu.md
index 9b0a65d9386..e43047ce1d6 100644
--- a/gcc/config/arc/fpu.md
+++ b/gcc/config/arc/fpu.md
@@ -193,11 +193,13 @@
(set_attr "type" "fpu")])
;; Division
-(define_insn "divsf3"
+(define_insn "*divsf3_fpu"
[(set (match_operand:SF 0 "register_operand" "=r,r,r,r,r")
(div:SF (match_operand:SF 1 "nonmemory_operand" "0,r,0,r,F")
(match_operand:SF 2 "nonmemory_operand" "r,r,F,F,r")))]
- "TARGET_FP_SP_SQRT"
+ "TARGET_FP_SP_SQRT
+ && (register_operand (operands[1], SFmode)
+ || register_operand (operands[2], SFmode))"
"fsdiv%? %0,%1,%2"
[(set_attr "length" "4,4,8,8,8")
(set_attr "iscompact" "false")
diff --git a/gcc/config/arc/fpx.md b/gcc/config/arc/fpx.md
index 2e11157cabf..9ed2b7c683a 100644
--- a/gcc/config/arc/fpx.md
+++ b/gcc/config/arc/fpx.md
@@ -168,28 +168,26 @@
(set_attr "type" "lr")]
)
-
(define_insn "*dexcl_3op_peep2_insn"
[(set (match_operand:SI 0 "dest_reg_operand" "=r") ; not register_operand, to accept SUBREG
- (unspec_volatile:SI [
- (match_operand:DF 1 "arc_double_register_operand" "D")
- (match_operand:SI 2 "shouldbe_register_operand" "r") ; r1
- (match_operand:SI 3 "shouldbe_register_operand" "r") ; r0
- ] VUNSPEC_ARC_DEXCL ))
- ]
+ (unspec_volatile:SI
+ [(match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
+ (match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
+ ] VUNSPEC_ARC_DEXCL ))
+ (clobber (match_operand:DF 3 "arc_double_register_operand" "=&D"))]
"TARGET_DPFP"
- "dexcl%F1 %0, %2, %3"
+ "dexcl%F3 %0, %1, %2"
[(set_attr "type" "move")
(set_attr "length" "4")]
)
;; version which will not overwrite operand0
-(define_insn "*dexcl_3op_peep2_insn_nores"
- [ (unspec_volatile:SI [
- (match_operand:DF 0 "arc_double_register_operand" "D")
- (match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
- (match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
- ] VUNSPEC_ARC_DEXCL_NORES )
+(define_insn "dexcl_2op"
+ [(set (match_operand:DF 0 "arc_double_register_operand" "=D")
+ (unspec_volatile:DF
+ [(match_operand:SI 1 "shouldbe_register_operand" "r") ; r1
+ (match_operand:SI 2 "shouldbe_register_operand" "r") ; r0
+ ] VUNSPEC_ARC_DEXCL_NORES))
]
"TARGET_DPFP"
"dexcl%F0 0, %1, %2"
diff --git a/gcc/config/arm/arm-arches.def b/gcc/config/arm/arm-arches.def
index 4b196a7d118..cd79bc50585 100644
--- a/gcc/config/arm/arm-arches.def
+++ b/gcc/config/arm/arm-arches.def
@@ -69,11 +69,11 @@ ARM_ARCH ("armv8.2-a", cortexa53, 8A,
ARM_ARCH ("armv8.2-a+fp16", cortexa53, 8A,
ARM_FSET_MAKE (FL_CO_PROC | FL_CRC32 | FL_FOR_ARCH8A,
FL2_FOR_ARCH8_2A | FL2_FP16INST))
-ARM_ARCH("armv8-m.base", cortexm0, 8M_BASE,
+ARM_ARCH("armv8-m.base", cortexm23, 8M_BASE,
ARM_FSET_MAKE_CPU1 ( FL_FOR_ARCH8M_BASE))
ARM_ARCH("armv8-m.main", cortexm7, 8M_MAIN,
ARM_FSET_MAKE_CPU1(FL_CO_PROC | FL_FOR_ARCH8M_MAIN))
-ARM_ARCH("armv8-m.main+dsp", cortexm7, 8M_MAIN,
+ARM_ARCH("armv8-m.main+dsp", cortexm33, 8M_MAIN,
ARM_FSET_MAKE_CPU1(FL_CO_PROC | FL_ARCH7EM | FL_FOR_ARCH8M_MAIN))
ARM_ARCH("iwmmxt", iwmmxt, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT))
ARM_ARCH("iwmmxt2", iwmmxt2, 5TE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_STRONG | FL_FOR_ARCH5TE | FL_XSCALE | FL_IWMMXT | FL_IWMMXT2))
diff --git a/gcc/config/arm/arm-c.c b/gcc/config/arm/arm-c.c
index df930f44801..74417a6446d 100644
--- a/gcc/config/arm/arm-c.c
+++ b/gcc/config/arm/arm-c.c
@@ -87,6 +87,9 @@ arm_cpu_builtins (struct cpp_reader* pfile)
((TARGET_ARM_ARCH >= 5 && !TARGET_THUMB)
|| TARGET_ARM_ARCH_ISA_THUMB >=2));
+ def_or_undef_macro (pfile, "__ARM_FEATURE_NUMERIC_MAXMIN",
+ TARGET_ARM_ARCH >= 8 && TARGET_NEON && TARGET_FPU_ARMV8);
+
def_or_undef_macro (pfile, "__ARM_FEATURE_SIMD32", TARGET_INT_SIMD);
builtin_define_with_int_value ("__ARM_SIZEOF_MINIMAL_ENUM",
diff --git a/gcc/config/arm/arm-cores.def b/gcc/config/arm/arm-cores.def
index 2072e1e6f8d..ec63ee4abe5 100644
--- a/gcc/config/arm/arm-cores.def
+++ b/gcc/config/arm/arm-cores.def
@@ -166,7 +166,9 @@ ARM_CORE("cortex-a15.cortex-a7", cortexa15cortexa7, cortexa7, 7A, ARM_FSET_MAKE_
ARM_CORE("cortex-a17.cortex-a7", cortexa17cortexa7, cortexa7, 7A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_THUMB_DIV | FL_ARM_DIV | FL_FOR_ARCH7A), cortex_a12)
/* V8 Architecture Processors */
+ARM_CORE("cortex-m23", cortexm23, cortexm23, 8M_BASE, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_FOR_ARCH8M_BASE), v6m)
ARM_CORE("cortex-a32", cortexa32, cortexa53, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_CRC32 | FL_FOR_ARCH8A), cortex_a35)
+ARM_CORE("cortex-m33", cortexm33, cortexm33, 8M_MAIN, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_ARCH7EM | FL_FOR_ARCH8M_MAIN), v7m)
ARM_CORE("cortex-a35", cortexa35, cortexa53, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_CRC32 | FL_FOR_ARCH8A), cortex_a35)
ARM_CORE("cortex-a53", cortexa53, cortexa53, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_CRC32 | FL_FOR_ARCH8A), cortex_a53)
ARM_CORE("cortex-a57", cortexa57, cortexa57, 8A, ARM_FSET_MAKE_CPU1 (FL_LDSCHED | FL_CRC32 | FL_FOR_ARCH8A), cortex_a57)
diff --git a/gcc/config/arm/arm-protos.h b/gcc/config/arm/arm-protos.h
index fd8b6d106d1..95bae5ef57b 100644
--- a/gcc/config/arm/arm-protos.h
+++ b/gcc/config/arm/arm-protos.h
@@ -260,7 +260,6 @@ struct cpu_cost_table;
struct tune_params
{
- bool (*rtx_costs) (rtx, RTX_CODE, RTX_CODE, int *, bool);
const struct cpu_cost_table *insn_extra_cost;
bool (*sched_adjust_cost) (rtx_insn *, int, rtx_insn *, int *);
int (*branch_cost) (bool, bool);
diff --git a/gcc/config/arm/arm-tables.opt b/gcc/config/arm/arm-tables.opt
index ee9e3bb7ec5..f7886b94be7 100644
--- a/gcc/config/arm/arm-tables.opt
+++ b/gcc/config/arm/arm-tables.opt
@@ -307,9 +307,15 @@ EnumValue
Enum(processor_type) String(cortex-a17.cortex-a7) Value(cortexa17cortexa7)
EnumValue
+Enum(processor_type) String(cortex-m23) Value(cortexm23)
+
+EnumValue
Enum(processor_type) String(cortex-a32) Value(cortexa32)
EnumValue
+Enum(processor_type) String(cortex-m33) Value(cortexm33)
+
+EnumValue
Enum(processor_type) String(cortex-a35) Value(cortexa35)
EnumValue
diff --git a/gcc/config/arm/arm-tune.md b/gcc/config/arm/arm-tune.md
index 594ce9d1734..e782baccf42 100644
--- a/gcc/config/arm/arm-tune.md
+++ b/gcc/config/arm/arm-tune.md
@@ -32,9 +32,10 @@
cortexr4f,cortexr5,cortexr7,
cortexr8,cortexm7,cortexm4,
cortexm3,marvell_pj4,cortexa15cortexa7,
- cortexa17cortexa7,cortexa32,cortexa35,
- cortexa53,cortexa57,cortexa72,
- cortexa73,exynosm1,qdf24xx,
- xgene1,cortexa57cortexa53,cortexa72cortexa53,
- cortexa73cortexa35,cortexa73cortexa53"
+ cortexa17cortexa7,cortexm23,cortexa32,
+ cortexm33,cortexa35,cortexa53,
+ cortexa57,cortexa72,cortexa73,
+ exynosm1,qdf24xx,xgene1,
+ cortexa57cortexa53,cortexa72cortexa53,cortexa73cortexa35,
+ cortexa73cortexa53"
(const (symbol_ref "((enum attr_tune) arm_tune)")))
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 3c4c7042d9c..13f61f49ff8 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -62,6 +62,7 @@
#include "builtins.h"
#include "tm-constrs.h"
#include "rtl-iter.h"
+#include "optabs-libfuncs.h"
/* This file should be included last. */
#include "target-def.h"
@@ -164,12 +165,6 @@ static void arm_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
static bool arm_have_conditional_execution (void);
static bool arm_cannot_force_const_mem (machine_mode, rtx);
static bool arm_legitimate_constant_p (machine_mode, rtx);
-static bool arm_rtx_costs_1 (rtx, enum rtx_code, int*, bool);
-static bool arm_size_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *);
-static bool arm_slowmul_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
-static bool arm_fastmul_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
-static bool arm_xscale_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
-static bool arm_9e_rtx_costs (rtx, enum rtx_code, enum rtx_code, int *, bool);
static bool arm_rtx_costs (rtx, machine_mode, int, int, int *, bool);
static int arm_address_cost (rtx, machine_mode, addr_space_t, bool);
static int arm_register_move_cost (machine_mode, reg_class_t, reg_class_t);
@@ -304,6 +299,7 @@ static section *arm_function_section (tree, enum node_frequency, bool, bool);
static bool arm_asm_elf_flags_numeric (unsigned int flags, unsigned int *num);
static unsigned int arm_elf_section_type_flags (tree decl, const char *name,
int reloc);
+static void arm_expand_divmod_libfunc (rtx, machine_mode, rtx, rtx, rtx *, rtx *);
/* Table of machine attributes. */
static const struct attribute_spec arm_attribute_table[] =
@@ -739,6 +735,9 @@ static const struct attribute_spec arm_attribute_table[] =
#undef TARGET_SECTION_TYPE_FLAGS
#define TARGET_SECTION_TYPE_FLAGS arm_elf_section_type_flags
+#undef TARGET_EXPAND_DIVMOD_LIBFUNC
+#define TARGET_EXPAND_DIVMOD_LIBFUNC arm_expand_divmod_libfunc
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Obstack for minipool constant handling. */
@@ -1698,8 +1697,7 @@ const struct cpu_cost_table v7m_extra_costs =
const struct tune_params arm_slowmul_tune =
{
- arm_slowmul_rtx_costs,
- NULL, /* Insn extra costs. */
+ &generic_extra_costs, /* Insn extra costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
@@ -1721,8 +1719,7 @@ const struct tune_params arm_slowmul_tune =
const struct tune_params arm_fastmul_tune =
{
- arm_fastmul_rtx_costs,
- NULL, /* Insn extra costs. */
+ &generic_extra_costs, /* Insn extra costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
@@ -1747,8 +1744,7 @@ const struct tune_params arm_fastmul_tune =
const struct tune_params arm_strongarm_tune =
{
- arm_fastmul_rtx_costs,
- NULL, /* Insn extra costs. */
+ &generic_extra_costs, /* Insn extra costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
@@ -1770,8 +1766,7 @@ const struct tune_params arm_strongarm_tune =
const struct tune_params arm_xscale_tune =
{
- arm_xscale_rtx_costs,
- NULL, /* Insn extra costs. */
+ &generic_extra_costs, /* Insn extra costs. */
xscale_sched_adjust_cost,
arm_default_branch_cost,
&arm_default_vec_cost,
@@ -1793,8 +1788,7 @@ const struct tune_params arm_xscale_tune =
const struct tune_params arm_9e_tune =
{
- arm_9e_rtx_costs,
- NULL, /* Insn extra costs. */
+ &generic_extra_costs, /* Insn extra costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
@@ -1816,8 +1810,7 @@ const struct tune_params arm_9e_tune =
const struct tune_params arm_marvell_pj4_tune =
{
- arm_9e_rtx_costs,
- NULL, /* Insn extra costs. */
+ &generic_extra_costs, /* Insn extra costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
@@ -1839,8 +1832,7 @@ const struct tune_params arm_marvell_pj4_tune =
const struct tune_params arm_v6t2_tune =
{
- arm_9e_rtx_costs,
- NULL, /* Insn extra costs. */
+ &generic_extra_costs, /* Insn extra costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost,
@@ -1864,7 +1856,6 @@ const struct tune_params arm_v6t2_tune =
/* Generic Cortex tuning. Use more specific tunings if appropriate. */
const struct tune_params arm_cortex_tune =
{
- arm_9e_rtx_costs,
&generic_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -1887,7 +1878,6 @@ const struct tune_params arm_cortex_tune =
const struct tune_params arm_cortex_a8_tune =
{
- arm_9e_rtx_costs,
&cortexa8_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -1910,7 +1900,6 @@ const struct tune_params arm_cortex_a8_tune =
const struct tune_params arm_cortex_a7_tune =
{
- arm_9e_rtx_costs,
&cortexa7_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -1933,7 +1922,6 @@ const struct tune_params arm_cortex_a7_tune =
const struct tune_params arm_cortex_a15_tune =
{
- arm_9e_rtx_costs,
&cortexa15_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -1956,7 +1944,6 @@ const struct tune_params arm_cortex_a15_tune =
const struct tune_params arm_cortex_a35_tune =
{
- arm_9e_rtx_costs,
&cortexa53_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -1979,7 +1966,6 @@ const struct tune_params arm_cortex_a35_tune =
const struct tune_params arm_cortex_a53_tune =
{
- arm_9e_rtx_costs,
&cortexa53_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -2002,7 +1988,6 @@ const struct tune_params arm_cortex_a53_tune =
const struct tune_params arm_cortex_a57_tune =
{
- arm_9e_rtx_costs,
&cortexa57_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -2025,7 +2010,6 @@ const struct tune_params arm_cortex_a57_tune =
const struct tune_params arm_exynosm1_tune =
{
- arm_9e_rtx_costs,
&exynosm1_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -2048,7 +2032,6 @@ const struct tune_params arm_exynosm1_tune =
const struct tune_params arm_xgene1_tune =
{
- arm_9e_rtx_costs,
&xgene1_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -2071,7 +2054,6 @@ const struct tune_params arm_xgene1_tune =
const struct tune_params arm_qdf24xx_tune =
{
- arm_9e_rtx_costs,
&qdf24xx_extra_costs,
NULL, /* Scheduler cost adjustment. */
arm_default_branch_cost,
@@ -2097,7 +2079,6 @@ const struct tune_params arm_qdf24xx_tune =
const struct tune_params arm_cortex_a5_tune =
{
- arm_9e_rtx_costs,
&cortexa5_extra_costs,
NULL, /* Sched adj cost. */
arm_cortex_a5_branch_cost,
@@ -2120,7 +2101,6 @@ const struct tune_params arm_cortex_a5_tune =
const struct tune_params arm_cortex_a9_tune =
{
- arm_9e_rtx_costs,
&cortexa9_extra_costs,
cortex_a9_sched_adjust_cost,
arm_default_branch_cost,
@@ -2143,7 +2123,6 @@ const struct tune_params arm_cortex_a9_tune =
const struct tune_params arm_cortex_a12_tune =
{
- arm_9e_rtx_costs,
&cortexa12_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -2166,7 +2145,6 @@ const struct tune_params arm_cortex_a12_tune =
const struct tune_params arm_cortex_a73_tune =
{
- arm_9e_rtx_costs,
&cortexa57_extra_costs,
NULL, /* Sched adj cost. */
arm_default_branch_cost,
@@ -2196,7 +2174,6 @@ const struct tune_params arm_cortex_a73_tune =
const struct tune_params arm_v7m_tune =
{
- arm_9e_rtx_costs,
&v7m_extra_costs,
NULL, /* Sched adj cost. */
arm_cortex_m_branch_cost,
@@ -2221,7 +2198,6 @@ const struct tune_params arm_v7m_tune =
const struct tune_params arm_cortex_m7_tune =
{
- arm_9e_rtx_costs,
&v7m_extra_costs,
NULL, /* Sched adj cost. */
arm_cortex_m7_branch_cost,
@@ -2243,11 +2219,11 @@ const struct tune_params arm_cortex_m7_tune =
};
/* The arm_v6m_tune is duplicated from arm_cortex_tune, rather than
- arm_v6t2_tune. It is used for cortex-m0, cortex-m1 and cortex-m0plus. */
+ arm_v6t2_tune. It is used for cortex-m0, cortex-m1, cortex-m0plus and
+ cortex-m23. */
const struct tune_params arm_v6m_tune =
{
- arm_9e_rtx_costs,
- NULL, /* Insn extra costs. */
+ &generic_extra_costs, /* Insn extra costs. */
NULL, /* Sched adj cost. */
arm_default_branch_cost,
&arm_default_vec_cost, /* Vectorizer costs. */
@@ -2269,8 +2245,7 @@ const struct tune_params arm_v6m_tune =
const struct tune_params arm_fa726te_tune =
{
- arm_9e_rtx_costs,
- NULL, /* Insn extra costs. */
+ &generic_extra_costs, /* Insn extra costs. */
fa726te_sched_adjust_cost,
arm_default_branch_cost,
&arm_default_vec_cost,
@@ -3099,17 +3074,7 @@ arm_option_override (void)
arm_feature_set sought = ARM_FSET_EMPTY;;
arm_selected_cpu = &all_cores[TARGET_CPU_DEFAULT];
- if (!arm_selected_cpu->name)
- {
-#ifdef SUBTARGET_CPU_DEFAULT
- /* Use the subtarget default CPU if none was specified by
- configure. */
- arm_selected_cpu = &all_cores[SUBTARGET_CPU_DEFAULT];
-#endif
- /* Default to ARM6. */
- if (!arm_selected_cpu->name)
- arm_selected_cpu = &all_cores[arm6];
- }
+ gcc_assert (arm_selected_cpu->name);
sel = arm_selected_cpu;
insn_flags = sel->flags;
@@ -7900,10 +7865,10 @@ load_tls_operand (rtx x, rtx reg)
return reg;
}
-static rtx
+static rtx_insn *
arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
{
- rtx insns, label, labelno, sum;
+ rtx label, labelno, sum;
gcc_assert (reloc != TLS_DESCSEQ);
start_sequence ();
@@ -7927,7 +7892,7 @@ arm_call_tls_get_addr (rtx x, rtx reg, rtx *valuep, int reloc)
LCT_PURE, /* LCT_CONST? */
Pmode, 1, reg, Pmode);
- insns = get_insns ();
+ rtx_insn *insns = get_insns ();
end_sequence ();
return insns;
@@ -7959,7 +7924,8 @@ arm_tls_descseq_addr (rtx x, rtx reg)
rtx
legitimize_tls_address (rtx x, rtx reg)
{
- rtx dest, tp, label, labelno, sum, insns, ret, eqv, addend;
+ rtx dest, tp, label, labelno, sum, ret, eqv, addend;
+ rtx_insn *insns;
unsigned int model = SYMBOL_REF_TLS_MODEL (x);
switch (model)
@@ -8477,621 +8443,6 @@ thumb1_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
}
}
-static inline bool
-arm_rtx_costs_1 (rtx x, enum rtx_code outer, int* total, bool speed)
-{
- machine_mode mode = GET_MODE (x);
- enum rtx_code subcode;
- rtx operand;
- enum rtx_code code = GET_CODE (x);
- *total = 0;
-
- switch (code)
- {
- case MEM:
- /* Memory costs quite a lot for the first word, but subsequent words
- load at the equivalent of a single insn each. */
- *total = COSTS_N_INSNS (2 + ARM_NUM_REGS (mode));
- return true;
-
- case DIV:
- case MOD:
- case UDIV:
- case UMOD:
- if (TARGET_HARD_FLOAT && mode == SFmode)
- *total = COSTS_N_INSNS (2);
- else if (TARGET_HARD_FLOAT && mode == DFmode && !TARGET_VFP_SINGLE)
- *total = COSTS_N_INSNS (4);
- else
- *total = COSTS_N_INSNS (20);
- return false;
-
- case ROTATE:
- if (REG_P (XEXP (x, 1)))
- *total = COSTS_N_INSNS (1); /* Need to subtract from 32 */
- else if (!CONST_INT_P (XEXP (x, 1)))
- *total = rtx_cost (XEXP (x, 1), mode, code, 1, speed);
-
- /* Fall through */
- case ROTATERT:
- if (mode != SImode)
- {
- *total += COSTS_N_INSNS (4);
- return true;
- }
-
- /* Fall through */
- case ASHIFT: case LSHIFTRT: case ASHIFTRT:
- *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- if (mode == DImode)
- {
- *total += COSTS_N_INSNS (3);
- return true;
- }
-
- *total += COSTS_N_INSNS (1);
- /* Increase the cost of complex shifts because they aren't any faster,
- and reduce dual issue opportunities. */
- if (arm_tune_cortex_a9
- && outer != SET && !CONST_INT_P (XEXP (x, 1)))
- ++*total;
-
- return true;
-
- case MINUS:
- if (mode == DImode)
- {
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- if (CONST_INT_P (XEXP (x, 0))
- && const_ok_for_arm (INTVAL (XEXP (x, 0))))
- {
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
- return true;
- }
-
- if (CONST_INT_P (XEXP (x, 1))
- && const_ok_for_arm (INTVAL (XEXP (x, 1))))
- {
- *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- return true;
- }
-
- return false;
- }
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- if (TARGET_HARD_FLOAT
- && (mode == SFmode
- || (mode == DFmode && !TARGET_VFP_SINGLE)))
- {
- *total = COSTS_N_INSNS (1);
- if (CONST_DOUBLE_P (XEXP (x, 0))
- && arm_const_double_rtx (XEXP (x, 0)))
- {
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
- return true;
- }
-
- if (CONST_DOUBLE_P (XEXP (x, 1))
- && arm_const_double_rtx (XEXP (x, 1)))
- {
- *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- return true;
- }
-
- return false;
- }
- *total = COSTS_N_INSNS (20);
- return false;
- }
-
- *total = COSTS_N_INSNS (1);
- if (CONST_INT_P (XEXP (x, 0))
- && const_ok_for_arm (INTVAL (XEXP (x, 0))))
- {
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
- return true;
- }
-
- subcode = GET_CODE (XEXP (x, 1));
- if (subcode == ASHIFT || subcode == ASHIFTRT
- || subcode == LSHIFTRT
- || subcode == ROTATE || subcode == ROTATERT)
- {
- *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- *total += rtx_cost (XEXP (XEXP (x, 1), 0), mode, subcode, 0, speed);
- return true;
- }
-
- /* A shift as a part of RSB costs no more than RSB itself. */
- if (GET_CODE (XEXP (x, 0)) == MULT
- && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
- {
- *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, code, 0, speed);
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
- return true;
- }
-
- if (subcode == MULT
- && power_of_two_operand (XEXP (XEXP (x, 1), 1), SImode))
- {
- *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- *total += rtx_cost (XEXP (XEXP (x, 1), 0), mode, subcode, 0, speed);
- return true;
- }
-
- if (GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == RTX_COMPARE
- || GET_RTX_CLASS (GET_CODE (XEXP (x, 1))) == RTX_COMM_COMPARE)
- {
- *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code,
- 0, speed);
- if (REG_P (XEXP (XEXP (x, 1), 0))
- && REGNO (XEXP (XEXP (x, 1), 0)) != CC_REGNUM)
- *total += COSTS_N_INSNS (1);
-
- return true;
- }
-
- /* Fall through */
-
- case PLUS:
- if (code == PLUS && arm_arch6 && mode == SImode
- && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
- {
- *total = COSTS_N_INSNS (1);
- *total += rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode,
- GET_CODE (XEXP (x, 0)), 0, speed);
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
- return true;
- }
-
- /* MLA: All arguments must be registers. We filter out
- multiplication by a power of two, so that we fall down into
- the code below. */
- if (GET_CODE (XEXP (x, 0)) == MULT
- && !power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
- {
- /* The cost comes from the cost of the multiply. */
- return false;
- }
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- if (TARGET_HARD_FLOAT
- && (mode == SFmode
- || (mode == DFmode && !TARGET_VFP_SINGLE)))
- {
- *total = COSTS_N_INSNS (1);
- if (CONST_DOUBLE_P (XEXP (x, 1))
- && arm_const_double_rtx (XEXP (x, 1)))
- {
- *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- return true;
- }
-
- return false;
- }
-
- *total = COSTS_N_INSNS (20);
- return false;
- }
-
- if (GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_COMPARE
- || GET_RTX_CLASS (GET_CODE (XEXP (x, 0))) == RTX_COMM_COMPARE)
- {
- *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 1), mode, code,
- 1, speed);
- if (REG_P (XEXP (XEXP (x, 0), 0))
- && REGNO (XEXP (XEXP (x, 0), 0)) != CC_REGNUM)
- *total += COSTS_N_INSNS (1);
- return true;
- }
-
- /* Fall through */
-
- case AND: case XOR: case IOR:
-
- /* Normally the frame registers will be spilt into reg+const during
- reload, so it is a bad idea to combine them with other instructions,
- since then they might not be moved outside of loops. As a compromise
- we allow integration with ops that have a constant as their second
- operand. */
- if (REG_OR_SUBREG_REG (XEXP (x, 0))
- && ARM_FRAME_RTX (REG_OR_SUBREG_RTX (XEXP (x, 0)))
- && !CONST_INT_P (XEXP (x, 1)))
- *total = COSTS_N_INSNS (1);
-
- if (mode == DImode)
- {
- *total += COSTS_N_INSNS (2);
- if (CONST_INT_P (XEXP (x, 1))
- && const_ok_for_op (INTVAL (XEXP (x, 1)), code))
- {
- *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- return true;
- }
-
- return false;
- }
-
- *total += COSTS_N_INSNS (1);
- if (CONST_INT_P (XEXP (x, 1))
- && const_ok_for_op (INTVAL (XEXP (x, 1)), code))
- {
- *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- return true;
- }
- subcode = GET_CODE (XEXP (x, 0));
- if (subcode == ASHIFT || subcode == ASHIFTRT
- || subcode == LSHIFTRT
- || subcode == ROTATE || subcode == ROTATERT)
- {
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
- *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
- return true;
- }
-
- if (subcode == MULT
- && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
- {
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
- *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
- return true;
- }
-
- if (subcode == UMIN || subcode == UMAX
- || subcode == SMIN || subcode == SMAX)
- {
- *total = COSTS_N_INSNS (3);
- return true;
- }
-
- return false;
-
- case MULT:
- /* This should have been handled by the CPU specific routines. */
- gcc_unreachable ();
-
- case TRUNCATE:
- if (arm_arch3m && mode == SImode
- && GET_CODE (XEXP (x, 0)) == LSHIFTRT
- && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
- && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0))
- == GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 1)))
- && (GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (XEXP (XEXP (x, 0), 0), 0)) == SIGN_EXTEND))
- {
- *total = rtx_cost (XEXP (XEXP (x, 0), 0), VOIDmode, LSHIFTRT,
- 0, speed);
- return true;
- }
- *total = COSTS_N_INSNS (2); /* Plus the cost of the MULT */
- return false;
-
- case NEG:
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- if (TARGET_HARD_FLOAT
- && (mode == SFmode
- || (mode == DFmode && !TARGET_VFP_SINGLE)))
- {
- *total = COSTS_N_INSNS (1);
- return false;
- }
- *total = COSTS_N_INSNS (2);
- return false;
- }
-
- /* Fall through */
- case NOT:
- *total = COSTS_N_INSNS (ARM_NUM_REGS(mode));
- if (mode == SImode && code == NOT)
- {
- subcode = GET_CODE (XEXP (x, 0));
- if (subcode == ASHIFT || subcode == ASHIFTRT
- || subcode == LSHIFTRT
- || subcode == ROTATE || subcode == ROTATERT
- || (subcode == MULT
- && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode)))
- {
- *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode,
- 0, speed);
- /* Register shifts cost an extra cycle. */
- if (!CONST_INT_P (XEXP (XEXP (x, 0), 1)))
- *total += COSTS_N_INSNS (1) + rtx_cost (XEXP (XEXP (x, 0), 1),
- mode, subcode,
- 1, speed);
- return true;
- }
- }
-
- return false;
-
- case IF_THEN_ELSE:
- if (GET_CODE (XEXP (x, 1)) == PC || GET_CODE (XEXP (x, 2)) == PC)
- {
- *total = COSTS_N_INSNS (4);
- return true;
- }
-
- operand = XEXP (x, 0);
-
- if (!((GET_RTX_CLASS (GET_CODE (operand)) == RTX_COMPARE
- || GET_RTX_CLASS (GET_CODE (operand)) == RTX_COMM_COMPARE)
- && REG_P (XEXP (operand, 0))
- && REGNO (XEXP (operand, 0)) == CC_REGNUM))
- *total += COSTS_N_INSNS (1);
- *total += rtx_cost (XEXP (x, 1), VOIDmode, code, 1, speed);
- *total += rtx_cost (XEXP (x, 2), VOIDmode, code, 2, speed);
- return true;
-
- case NE:
- if (mode == SImode && XEXP (x, 1) == const0_rtx)
- {
- *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code,
- 0, speed);
- return true;
- }
- goto scc_insn;
-
- case GE:
- if ((!REG_P (XEXP (x, 0)) || REGNO (XEXP (x, 0)) != CC_REGNUM)
- && mode == SImode && XEXP (x, 1) == const0_rtx)
- {
- *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code,
- 0, speed);
- return true;
- }
- goto scc_insn;
-
- case LT:
- if ((!REG_P (XEXP (x, 0)) || REGNO (XEXP (x, 0)) != CC_REGNUM)
- && mode == SImode && XEXP (x, 1) == const0_rtx)
- {
- *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code,
- 0, speed);
- return true;
- }
- goto scc_insn;
-
- case EQ:
- case GT:
- case LE:
- case GEU:
- case LTU:
- case GTU:
- case LEU:
- case UNORDERED:
- case ORDERED:
- case UNEQ:
- case UNGE:
- case UNLT:
- case UNGT:
- case UNLE:
- scc_insn:
- /* SCC insns. In the case where the comparison has already been
- performed, then they cost 2 instructions. Otherwise they need
- an additional comparison before them. */
- *total = COSTS_N_INSNS (2);
- if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) == CC_REGNUM)
- {
- return true;
- }
-
- /* Fall through */
- case COMPARE:
- if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) == CC_REGNUM)
- {
- *total = 0;
- return true;
- }
-
- *total += COSTS_N_INSNS (1);
- if (CONST_INT_P (XEXP (x, 1))
- && const_ok_for_op (INTVAL (XEXP (x, 1)), code))
- {
- *total += rtx_cost (XEXP (x, 0), VOIDmode, code, 0, speed);
- return true;
- }
-
- subcode = GET_CODE (XEXP (x, 0));
- if (subcode == ASHIFT || subcode == ASHIFTRT
- || subcode == LSHIFTRT
- || subcode == ROTATE || subcode == ROTATERT)
- {
- mode = GET_MODE (XEXP (x, 0));
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
- *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
- return true;
- }
-
- if (subcode == MULT
- && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
- {
- mode = GET_MODE (XEXP (x, 0));
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
- *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, subcode, 0, speed);
- return true;
- }
-
- return false;
-
- case UMIN:
- case UMAX:
- case SMIN:
- case SMAX:
- *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- if (!CONST_INT_P (XEXP (x, 1))
- || !const_ok_for_arm (INTVAL (XEXP (x, 1))))
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
- return true;
-
- case ABS:
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- if (TARGET_HARD_FLOAT
- && (mode == SFmode
- || (mode == DFmode && !TARGET_VFP_SINGLE)))
- {
- *total = COSTS_N_INSNS (1);
- return false;
- }
- *total = COSTS_N_INSNS (20);
- return false;
- }
- *total = COSTS_N_INSNS (1);
- if (mode == DImode)
- *total += COSTS_N_INSNS (3);
- return false;
-
- case SIGN_EXTEND:
- case ZERO_EXTEND:
- *total = 0;
- if (GET_MODE_CLASS (mode) == MODE_INT)
- {
- rtx op = XEXP (x, 0);
- machine_mode opmode = GET_MODE (op);
-
- if (mode == DImode)
- *total += COSTS_N_INSNS (1);
-
- if (opmode != SImode)
- {
- if (MEM_P (op))
- {
- /* If !arm_arch4, we use one of the extendhisi2_mem
- or movhi_bytes patterns for HImode. For a QImode
- sign extension, we first zero-extend from memory
- and then perform a shift sequence. */
- if (!arm_arch4 && (opmode != QImode || code == SIGN_EXTEND))
- *total += COSTS_N_INSNS (2);
- }
- else if (arm_arch6)
- *total += COSTS_N_INSNS (1);
-
- /* We don't have the necessary insn, so we need to perform some
- other operation. */
- else if (TARGET_ARM && code == ZERO_EXTEND && mode == QImode)
- /* An and with constant 255. */
- *total += COSTS_N_INSNS (1);
- else
- /* A shift sequence. Increase costs slightly to avoid
- combining two shifts into an extend operation. */
- *total += COSTS_N_INSNS (2) + 1;
- }
-
- return false;
- }
-
- switch (GET_MODE (XEXP (x, 0)))
- {
- case V8QImode:
- case V4HImode:
- case V2SImode:
- case V4QImode:
- case V2HImode:
- *total = COSTS_N_INSNS (1);
- return false;
-
- default:
- gcc_unreachable ();
- }
- gcc_unreachable ();
-
- case ZERO_EXTRACT:
- case SIGN_EXTRACT:
- mode = GET_MODE (XEXP (x, 0));
- *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- return true;
-
- case CONST_INT:
- if (const_ok_for_arm (INTVAL (x))
- || const_ok_for_arm (~INTVAL (x)))
- *total = COSTS_N_INSNS (1);
- else
- *total = COSTS_N_INSNS (arm_gen_constant (SET, mode, NULL_RTX,
- INTVAL (x), NULL_RTX,
- NULL_RTX, 0, 0));
- return true;
-
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- *total = COSTS_N_INSNS (3);
- return true;
-
- case HIGH:
- *total = COSTS_N_INSNS (1);
- return true;
-
- case LO_SUM:
- *total = COSTS_N_INSNS (1);
- *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- return true;
-
- case CONST_DOUBLE:
- if (TARGET_HARD_FLOAT && vfp3_const_double_rtx (x)
- && (mode == SFmode || !TARGET_VFP_SINGLE))
- *total = COSTS_N_INSNS (1);
- else
- *total = COSTS_N_INSNS (4);
- return true;
-
- case SET:
- /* The vec_extract patterns accept memory operands that require an
- address reload. Account for the cost of that reload to give the
- auto-inc-dec pass an incentive to try to replace them. */
- if (TARGET_NEON && MEM_P (SET_DEST (x))
- && GET_CODE (SET_SRC (x)) == VEC_SELECT)
- {
- mode = GET_MODE (SET_DEST (x));
- *total = rtx_cost (SET_DEST (x), mode, code, 0, speed);
- if (!neon_vector_mem_operand (SET_DEST (x), 2, true))
- *total += COSTS_N_INSNS (1);
- return true;
- }
- /* Likewise for the vec_set patterns. */
- if (TARGET_NEON && GET_CODE (SET_SRC (x)) == VEC_MERGE
- && GET_CODE (XEXP (SET_SRC (x), 0)) == VEC_DUPLICATE
- && MEM_P (XEXP (XEXP (SET_SRC (x), 0), 0)))
- {
- rtx mem = XEXP (XEXP (SET_SRC (x), 0), 0);
- mode = GET_MODE (SET_DEST (x));
- *total = rtx_cost (mem, mode, code, 0, speed);
- if (!neon_vector_mem_operand (mem, 2, true))
- *total += COSTS_N_INSNS (1);
- return true;
- }
- return false;
-
- case UNSPEC:
- /* We cost this as high as our memory costs to allow this to
- be hoisted from loops. */
- if (XINT (x, 1) == UNSPEC_PIC_UNIFIED)
- {
- *total = COSTS_N_INSNS (2 + ARM_NUM_REGS (mode));
- }
- return true;
-
- case CONST_VECTOR:
- if (TARGET_NEON
- && TARGET_HARD_FLOAT
- && outer == SET
- && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode))
- && neon_immediate_valid_for_move (x, mode, NULL, NULL))
- *total = COSTS_N_INSNS (1);
- else
- *total = COSTS_N_INSNS (4);
- return true;
-
- default:
- *total = COSTS_N_INSNS (4);
- return false;
- }
-}
-
/* Estimates the size cost of thumb1 instructions.
For now most of the code is copied from thumb1_rtx_costs. We need more
fine grain tuning when we have more related test cases. */
@@ -9251,245 +8602,6 @@ thumb1_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer)
}
}
-/* RTX costs when optimizing for size. */
-static bool
-arm_size_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
- int *total)
-{
- machine_mode mode = GET_MODE (x);
- if (TARGET_THUMB1)
- {
- *total = thumb1_size_rtx_costs (x, code, outer_code);
- return true;
- }
-
- /* FIXME: This makes no attempt to prefer narrow Thumb-2 instructions. */
- switch (code)
- {
- case MEM:
- /* A memory access costs 1 insn if the mode is small, or the address is
- a single register, otherwise it costs one insn per word. */
- if (REG_P (XEXP (x, 0)))
- *total = COSTS_N_INSNS (1);
- else if (flag_pic
- && GET_CODE (XEXP (x, 0)) == PLUS
- && will_be_in_index_register (XEXP (XEXP (x, 0), 1)))
- /* This will be split into two instructions.
- See arm.md:calculate_pic_address. */
- *total = COSTS_N_INSNS (2);
- else
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- return true;
-
- case DIV:
- case MOD:
- case UDIV:
- case UMOD:
- /* Needs a libcall, so it costs about this. */
- *total = COSTS_N_INSNS (2);
- return false;
-
- case ROTATE:
- if (mode == SImode && REG_P (XEXP (x, 1)))
- {
- *total = COSTS_N_INSNS (2) + rtx_cost (XEXP (x, 0), mode, code,
- 0, false);
- return true;
- }
- /* Fall through */
- case ROTATERT:
- case ASHIFT:
- case LSHIFTRT:
- case ASHIFTRT:
- if (mode == DImode && CONST_INT_P (XEXP (x, 1)))
- {
- *total = COSTS_N_INSNS (3) + rtx_cost (XEXP (x, 0), mode, code,
- 0, false);
- return true;
- }
- else if (mode == SImode)
- {
- *total = COSTS_N_INSNS (1) + rtx_cost (XEXP (x, 0), mode, code,
- 0, false);
- /* Slightly disparage register shifts, but not by much. */
- if (!CONST_INT_P (XEXP (x, 1)))
- *total += 1 + rtx_cost (XEXP (x, 1), mode, code, 1, false);
- return true;
- }
-
- /* Needs a libcall. */
- *total = COSTS_N_INSNS (2);
- return false;
-
- case MINUS:
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
- && (mode == SFmode || !TARGET_VFP_SINGLE))
- {
- *total = COSTS_N_INSNS (1);
- return false;
- }
-
- if (mode == SImode)
- {
- enum rtx_code subcode0 = GET_CODE (XEXP (x, 0));
- enum rtx_code subcode1 = GET_CODE (XEXP (x, 1));
-
- if (subcode0 == ROTATE || subcode0 == ROTATERT || subcode0 == ASHIFT
- || subcode0 == LSHIFTRT || subcode0 == ASHIFTRT
- || subcode1 == ROTATE || subcode1 == ROTATERT
- || subcode1 == ASHIFT || subcode1 == LSHIFTRT
- || subcode1 == ASHIFTRT)
- {
- /* It's just the cost of the two operands. */
- *total = 0;
- return false;
- }
-
- *total = COSTS_N_INSNS (1);
- return false;
- }
-
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- return false;
-
- case PLUS:
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
- && (mode == SFmode || !TARGET_VFP_SINGLE))
- {
- *total = COSTS_N_INSNS (1);
- return false;
- }
-
- /* A shift as a part of ADD costs nothing. */
- if (GET_CODE (XEXP (x, 0)) == MULT
- && power_of_two_operand (XEXP (XEXP (x, 0), 1), SImode))
- {
- *total = COSTS_N_INSNS (TARGET_THUMB2 ? 2 : 1);
- *total += rtx_cost (XEXP (XEXP (x, 0), 0), mode, code, 0, false);
- *total += rtx_cost (XEXP (x, 1), mode, code, 1, false);
- return true;
- }
-
- /* Fall through */
- case AND: case XOR: case IOR:
- if (mode == SImode)
- {
- enum rtx_code subcode = GET_CODE (XEXP (x, 0));
-
- if (subcode == ROTATE || subcode == ROTATERT || subcode == ASHIFT
- || subcode == LSHIFTRT || subcode == ASHIFTRT
- || (code == AND && subcode == NOT))
- {
- /* It's just the cost of the two operands. */
- *total = 0;
- return false;
- }
- }
-
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- return false;
-
- case MULT:
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- return false;
-
- case NEG:
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
- && (mode == SFmode || !TARGET_VFP_SINGLE))
- {
- *total = COSTS_N_INSNS (1);
- return false;
- }
-
- /* Fall through */
- case NOT:
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
-
- return false;
-
- case IF_THEN_ELSE:
- *total = 0;
- return false;
-
- case COMPARE:
- if (cc_register (XEXP (x, 0), VOIDmode))
- * total = 0;
- else
- *total = COSTS_N_INSNS (1);
- return false;
-
- case ABS:
- if (TARGET_HARD_FLOAT && GET_MODE_CLASS (mode) == MODE_FLOAT
- && (mode == SFmode || !TARGET_VFP_SINGLE))
- *total = COSTS_N_INSNS (1);
- else
- *total = COSTS_N_INSNS (1 + ARM_NUM_REGS (mode));
- return false;
-
- case SIGN_EXTEND:
- case ZERO_EXTEND:
- return arm_rtx_costs_1 (x, outer_code, total, 0);
-
- case CONST_INT:
- if (const_ok_for_arm (INTVAL (x)))
- /* A multiplication by a constant requires another instruction
- to load the constant to a register. */
- *total = COSTS_N_INSNS ((outer_code == SET || outer_code == MULT)
- ? 1 : 0);
- else if (const_ok_for_arm (~INTVAL (x)))
- *total = COSTS_N_INSNS (outer_code == AND ? 0 : 1);
- else if (const_ok_for_arm (-INTVAL (x)))
- {
- if (outer_code == COMPARE || outer_code == PLUS
- || outer_code == MINUS)
- *total = 0;
- else
- *total = COSTS_N_INSNS (1);
- }
- else
- *total = COSTS_N_INSNS (2);
- return true;
-
- case CONST:
- case LABEL_REF:
- case SYMBOL_REF:
- *total = COSTS_N_INSNS (2);
- return true;
-
- case CONST_DOUBLE:
- *total = COSTS_N_INSNS (4);
- return true;
-
- case CONST_VECTOR:
- if (TARGET_NEON
- && TARGET_HARD_FLOAT
- && outer_code == SET
- && (VALID_NEON_DREG_MODE (mode) || VALID_NEON_QREG_MODE (mode))
- && neon_immediate_valid_for_move (x, mode, NULL, NULL))
- *total = COSTS_N_INSNS (1);
- else
- *total = COSTS_N_INSNS (4);
- return true;
-
- case HIGH:
- case LO_SUM:
- /* We prefer constant pool entries to MOVW/MOVT pairs, so bump the
- cost of these slightly. */
- *total = COSTS_N_INSNS (1) + 1;
- return true;
-
- case SET:
- return false;
-
- default:
- if (mode != VOIDmode)
- *total = COSTS_N_INSNS (ARM_NUM_REGS (mode));
- else
- *total = COSTS_N_INSNS (4); /* How knows? */
- return false;
- }
-}
-
/* Helper function for arm_rtx_costs. If the operand is a valid shift
operand, then return the operand that is being shifted. If the shift
is not by a constant, then set SHIFT_REG to point to the operand.
@@ -9613,7 +8725,7 @@ arm_unspec_cost (rtx x, enum rtx_code /* outer_code */, bool speed_p, int *cost)
flags are live or not, and thus no realistic way to determine what
the size will eventually be. */
static bool
-arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
+arm_rtx_costs_internal (rtx x, enum rtx_code code, enum rtx_code outer_code,
const struct cpu_cost_table *extra_cost,
int *cost, bool speed_p)
{
@@ -11296,41 +10408,20 @@ arm_new_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
#undef HANDLE_NARROW_SHIFT_ARITH
-/* RTX costs when optimizing for size. */
+/* RTX costs entry point. */
+
static bool
arm_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
int opno ATTRIBUTE_UNUSED, int *total, bool speed)
{
bool result;
int code = GET_CODE (x);
+ gcc_assert (current_tune->insn_extra_cost);
- if (TARGET_OLD_RTX_COSTS
- || (!current_tune->insn_extra_cost && !TARGET_NEW_GENERIC_COSTS))
- {
- /* Old way. (Deprecated.) */
- if (!speed)
- result = arm_size_rtx_costs (x, (enum rtx_code) code,
- (enum rtx_code) outer_code, total);
- else
- result = current_tune->rtx_costs (x, (enum rtx_code) code,
- (enum rtx_code) outer_code, total,
- speed);
- }
- else
- {
- /* New way. */
- if (current_tune->insn_extra_cost)
- result = arm_new_rtx_costs (x, (enum rtx_code) code,
- (enum rtx_code) outer_code,
- current_tune->insn_extra_cost,
- total, speed);
- /* TARGET_NEW_GENERIC_COSTS && !TARGET_OLD_RTX_COSTS
- && current_tune->insn_extra_cost != NULL */
- else
- result = arm_new_rtx_costs (x, (enum rtx_code) code,
- (enum rtx_code) outer_code,
- &generic_extra_costs, total, speed);
- }
+ result = arm_rtx_costs_internal (x, (enum rtx_code) code,
+ (enum rtx_code) outer_code,
+ current_tune->insn_extra_cost,
+ total, speed);
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -11341,305 +10432,6 @@ arm_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code,
return result;
}
-/* RTX costs for cores with a slow MUL implementation. Thumb-2 is not
- supported on any "slowmul" cores, so it can be ignored. */
-
-static bool
-arm_slowmul_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
- int *total, bool speed)
-{
- machine_mode mode = GET_MODE (x);
-
- if (TARGET_THUMB)
- {
- *total = thumb1_rtx_costs (x, code, outer_code);
- return true;
- }
-
- switch (code)
- {
- case MULT:
- if (GET_MODE_CLASS (mode) == MODE_FLOAT
- || mode == DImode)
- {
- *total = COSTS_N_INSNS (20);
- return false;
- }
-
- if (CONST_INT_P (XEXP (x, 1)))
- {
- unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
- & (unsigned HOST_WIDE_INT) 0xffffffff);
- int cost, const_ok = const_ok_for_arm (i);
- int j, booth_unit_size;
-
- /* Tune as appropriate. */
- cost = const_ok ? 4 : 8;
- booth_unit_size = 2;
- for (j = 0; i && j < 32; j += booth_unit_size)
- {
- i >>= booth_unit_size;
- cost++;
- }
-
- *total = COSTS_N_INSNS (cost);
- *total += rtx_cost (XEXP (x, 0), mode, code, 0, speed);
- return true;
- }
-
- *total = COSTS_N_INSNS (20);
- return false;
-
- default:
- return arm_rtx_costs_1 (x, outer_code, total, speed);;
- }
-}
-
-
-/* RTX cost for cores with a fast multiply unit (M variants). */
-
-static bool
-arm_fastmul_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
- int *total, bool speed)
-{
- machine_mode mode = GET_MODE (x);
-
- if (TARGET_THUMB1)
- {
- *total = thumb1_rtx_costs (x, code, outer_code);
- return true;
- }
-
- /* ??? should thumb2 use different costs? */
- switch (code)
- {
- case MULT:
- /* There is no point basing this on the tuning, since it is always the
- fast variant if it exists at all. */
- if (mode == DImode
- && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
- && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
- {
- *total = COSTS_N_INSNS(2);
- return false;
- }
-
-
- if (mode == DImode)
- {
- *total = COSTS_N_INSNS (5);
- return false;
- }
-
- if (CONST_INT_P (XEXP (x, 1)))
- {
- unsigned HOST_WIDE_INT i = (INTVAL (XEXP (x, 1))
- & (unsigned HOST_WIDE_INT) 0xffffffff);
- int cost, const_ok = const_ok_for_arm (i);
- int j, booth_unit_size;
-
- /* Tune as appropriate. */
- cost = const_ok ? 4 : 8;
- booth_unit_size = 8;
- for (j = 0; i && j < 32; j += booth_unit_size)
- {
- i >>= booth_unit_size;
- cost++;
- }
-
- *total = COSTS_N_INSNS(cost);
- return false;
- }
-
- if (mode == SImode)
- {
- *total = COSTS_N_INSNS (4);
- return false;
- }
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- if (TARGET_HARD_FLOAT
- && (mode == SFmode
- || (mode == DFmode && !TARGET_VFP_SINGLE)))
- {
- *total = COSTS_N_INSNS (1);
- return false;
- }
- }
-
- /* Requires a lib call */
- *total = COSTS_N_INSNS (20);
- return false;
-
- default:
- return arm_rtx_costs_1 (x, outer_code, total, speed);
- }
-}
-
-
-/* RTX cost for XScale CPUs. Thumb-2 is not supported on any xscale cores,
- so it can be ignored. */
-
-static bool
-arm_xscale_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
- int *total, bool speed)
-{
- machine_mode mode = GET_MODE (x);
-
- if (TARGET_THUMB)
- {
- *total = thumb1_rtx_costs (x, code, outer_code);
- return true;
- }
-
- switch (code)
- {
- case COMPARE:
- if (GET_CODE (XEXP (x, 0)) != MULT)
- return arm_rtx_costs_1 (x, outer_code, total, speed);
-
- /* A COMPARE of a MULT is slow on XScale; the muls instruction
- will stall until the multiplication is complete. */
- *total = COSTS_N_INSNS (3);
- return false;
-
- case MULT:
- /* There is no point basing this on the tuning, since it is always the
- fast variant if it exists at all. */
- if (mode == DImode
- && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
- && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
- {
- *total = COSTS_N_INSNS (2);
- return false;
- }
-
-
- if (mode == DImode)
- {
- *total = COSTS_N_INSNS (5);
- return false;
- }
-
- if (CONST_INT_P (XEXP (x, 1)))
- {
- /* If operand 1 is a constant we can more accurately
- calculate the cost of the multiply. The multiplier can
- retire 15 bits on the first cycle and a further 12 on the
- second. We do, of course, have to load the constant into
- a register first. */
- unsigned HOST_WIDE_INT i = INTVAL (XEXP (x, 1));
- /* There's a general overhead of one cycle. */
- int cost = 1;
- unsigned HOST_WIDE_INT masked_const;
-
- if (i & 0x80000000)
- i = ~i;
-
- i &= (unsigned HOST_WIDE_INT) 0xffffffff;
-
- masked_const = i & 0xffff8000;
- if (masked_const != 0)
- {
- cost++;
- masked_const = i & 0xf8000000;
- if (masked_const != 0)
- cost++;
- }
- *total = COSTS_N_INSNS (cost);
- return false;
- }
-
- if (mode == SImode)
- {
- *total = COSTS_N_INSNS (3);
- return false;
- }
-
- /* Requires a lib call */
- *total = COSTS_N_INSNS (20);
- return false;
-
- default:
- return arm_rtx_costs_1 (x, outer_code, total, speed);
- }
-}
-
-
-/* RTX costs for 9e (and later) cores. */
-
-static bool
-arm_9e_rtx_costs (rtx x, enum rtx_code code, enum rtx_code outer_code,
- int *total, bool speed)
-{
- machine_mode mode = GET_MODE (x);
-
- if (TARGET_THUMB1)
- {
- switch (code)
- {
- case MULT:
- /* Small multiply: 32 cycles for an integer multiply inst. */
- if (arm_arch6m && arm_m_profile_small_mul)
- *total = COSTS_N_INSNS (32);
- else
- *total = COSTS_N_INSNS (3);
- return true;
-
- default:
- *total = thumb1_rtx_costs (x, code, outer_code);
- return true;
- }
- }
-
- switch (code)
- {
- case MULT:
- /* There is no point basing this on the tuning, since it is always the
- fast variant if it exists at all. */
- if (mode == DImode
- && (GET_CODE (XEXP (x, 0)) == GET_CODE (XEXP (x, 1)))
- && (GET_CODE (XEXP (x, 0)) == ZERO_EXTEND
- || GET_CODE (XEXP (x, 0)) == SIGN_EXTEND))
- {
- *total = COSTS_N_INSNS (2);
- return false;
- }
-
-
- if (mode == DImode)
- {
- *total = COSTS_N_INSNS (5);
- return false;
- }
-
- if (mode == SImode)
- {
- *total = COSTS_N_INSNS (2);
- return false;
- }
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
- {
- if (TARGET_HARD_FLOAT
- && (mode == SFmode
- || (mode == DFmode && !TARGET_VFP_SINGLE)))
- {
- *total = COSTS_N_INSNS (1);
- return false;
- }
- }
-
- *total = COSTS_N_INSNS (20);
- return false;
-
- default:
- return arm_rtx_costs_1 (x, outer_code, total, speed);
- }
-}
/* All address computations that can be done are free, but rtx cost returns
the same for practically all of them. So we weight the different types
of address here in the order (most pref first):
@@ -30150,9 +28942,9 @@ arm_const_not_ok_for_debug_p (rtx p)
&& GET_CODE (XEXP (p, 0)) == SYMBOL_REF
&& (decl_op0 = SYMBOL_REF_DECL (XEXP (p, 0))))
{
- if ((TREE_CODE (decl_op1) == VAR_DECL
+ if ((VAR_P (decl_op1)
|| TREE_CODE (decl_op1) == CONST_DECL)
- && (TREE_CODE (decl_op0) == VAR_DECL
+ && (VAR_P (decl_op0)
|| TREE_CODE (decl_op0) == CONST_DECL))
return (get_variable_section (decl_op1, false)
!= get_variable_section (decl_op0, false));
@@ -30845,4 +29637,33 @@ arm_elf_section_type_flags (tree decl, const char *name, int reloc)
return flags;
}
+/* Generate call to __aeabi_[mode]divmod (op0, op1). */
+
+static void
+arm_expand_divmod_libfunc (rtx libfunc, machine_mode mode,
+ rtx op0, rtx op1,
+ rtx *quot_p, rtx *rem_p)
+{
+ if (mode == SImode)
+ gcc_assert (!TARGET_IDIV);
+
+ machine_mode libval_mode = smallest_mode_for_size (2 * GET_MODE_BITSIZE (mode),
+ MODE_INT);
+
+ rtx libval = emit_library_call_value (libfunc, NULL_RTX, LCT_CONST,
+ libval_mode, 2,
+ op0, GET_MODE (op0),
+ op1, GET_MODE (op1));
+
+ rtx quotient = simplify_gen_subreg (mode, libval, libval_mode, 0);
+ rtx remainder = simplify_gen_subreg (mode, libval, libval_mode,
+ GET_MODE_SIZE (mode));
+
+ gcc_assert (quotient);
+ gcc_assert (remainder);
+
+ *quot_p = quotient;
+ *rem_p = remainder;
+}
+
#include "gt-arm.h"
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index b2d8422d494..3d11555d647 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -55,7 +55,8 @@ enum target_cpus
TARGET_CPU_##INTERNAL_IDENT,
#include "arm-cores.def"
#undef ARM_CORE
- TARGET_CPU_generic
+ /* Total number of CPUs we handle. */
+ TARGET_CPU_num_cores
};
/* The processor for which instructions should be scheduled. */
@@ -83,12 +84,6 @@ extern GTY(()) rtx arm_target_insn;
/* Callback to output language specific object attributes. */
extern void (*arm_lang_output_object_attributes_hook)(void);
-/* Just in case configure has failed to define anything. */
-#ifndef TARGET_CPU_DEFAULT
-#define TARGET_CPU_DEFAULT TARGET_CPU_generic
-#endif
-
-
#undef CPP_SPEC
#define CPP_SPEC "%(subtarget_cpp_spec) \
%{mfloat-abi=soft:%{mfloat-abi=hard: \
diff --git a/gcc/config/arm/arm.opt b/gcc/config/arm/arm.opt
index 35f047e2de1..54d84dc9f3a 100644
--- a/gcc/config/arm/arm.opt
+++ b/gcc/config/arm/arm.opt
@@ -253,14 +253,6 @@ mrestrict-it
Target Report Var(arm_restrict_it) Init(2) Save
Generate IT blocks appropriate for ARMv8.
-mold-rtx-costs
-Target Report Mask(OLD_RTX_COSTS)
-Use the old RTX costing tables (transitional).
-
-mnew-generic-costs
-Target Report Mask(NEW_GENERIC_COSTS)
-Use the new generic RTX cost tables if new core-specific cost table not available (transitional).
-
mfix-cortex-m3-ldrd
Target Report Var(fix_cm3_ldrd) Init(2)
Avoid overlapping destination and address registers on LDRD instructions
diff --git a/gcc/config/arm/arm_neon.h b/gcc/config/arm/arm_neon.h
index 54bbc7dd83c..3898ff7302d 100644
--- a/gcc/config/arm/arm_neon.h
+++ b/gcc/config/arm/arm_neon.h
@@ -2956,6 +2956,34 @@ vmaxq_f32 (float32x4_t __a, float32x4_t __b)
return (float32x4_t)__builtin_neon_vmaxfv4sf (__a, __b);
}
+#pragma GCC push_options
+#pragma GCC target ("fpu=neon-fp-armv8")
+__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
+vmaxnm_f32 (float32x2_t a, float32x2_t b)
+{
+ return (float32x2_t)__builtin_neon_vmaxnmv2sf (a, b);
+}
+
+__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
+vmaxnmq_f32 (float32x4_t a, float32x4_t b)
+{
+ return (float32x4_t)__builtin_neon_vmaxnmv4sf (a, b);
+}
+
+__extension__ static __inline float32x2_t __attribute__ ((__always_inline__))
+vminnm_f32 (float32x2_t a, float32x2_t b)
+{
+ return (float32x2_t)__builtin_neon_vminnmv2sf (a, b);
+}
+
+__extension__ static __inline float32x4_t __attribute__ ((__always_inline__))
+vminnmq_f32 (float32x4_t a, float32x4_t b)
+{
+ return (float32x4_t)__builtin_neon_vminnmv4sf (a, b);
+}
+#pragma GCC pop_options
+
+
__extension__ static __inline uint8x16_t __attribute__ ((__always_inline__))
vmaxq_u8 (uint8x16_t __a, uint8x16_t __b)
{
diff --git a/gcc/config/arm/arm_neon_builtins.def b/gcc/config/arm/arm_neon_builtins.def
index b29aa91a64e..58b10207c1f 100644
--- a/gcc/config/arm/arm_neon_builtins.def
+++ b/gcc/config/arm/arm_neon_builtins.def
@@ -147,12 +147,12 @@ VAR6 (BINOP, vmaxs, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR6 (BINOP, vmaxu, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR2 (BINOP, vmaxf, v2sf, v4sf)
VAR2 (BINOP, vmaxf, v8hf, v4hf)
-VAR2 (BINOP, vmaxnm, v4hf, v8hf)
+VAR4 (BINOP, vmaxnm, v2sf, v4sf, v4hf, v8hf)
VAR6 (BINOP, vmins, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR6 (BINOP, vminu, v8qi, v4hi, v2si, v16qi, v8hi, v4si)
VAR2 (BINOP, vminf, v2sf, v4sf)
VAR2 (BINOP, vminf, v4hf, v8hf)
-VAR2 (BINOP, vminnm, v8hf, v4hf)
+VAR4 (BINOP, vminnm, v2sf, v4sf, v8hf, v4hf)
VAR3 (BINOP, vpmaxs, v8qi, v4hi, v2si)
VAR3 (BINOP, vpmaxu, v8qi, v4hi, v2si)
diff --git a/gcc/config/arm/bpabi.h b/gcc/config/arm/bpabi.h
index 0da98fb711b..d45a1ca4219 100644
--- a/gcc/config/arm/bpabi.h
+++ b/gcc/config/arm/bpabi.h
@@ -95,9 +95,9 @@
|march=armv8.1-a+crc \
|march=armv8.2-a \
|march=armv8.2-a+fp16 \
- |march=armv8-m.base \
+ |march=armv8-m.base|mcpu=cortex-m23 \
|march=armv8-m.main \
- |march=armv8-m.main+dsp \
+ |march=armv8-m.main+dsp|mcpu=cortex-m33 \
:%{!r:--be8}}}"
#else
#define BE8_LINK_SPEC \
@@ -134,9 +134,9 @@
|march=armv8.1-a+crc \
|march=armv8.2-a \
|march=armv8.2-a+fp16 \
- |march=armv8-m.base \
+ |march=armv8-m.base|mcpu=cortex-m23 \
|march=armv8-m.main \
- |march=armv8-m.main+dsp \
+ |march=armv8-m.main+dsp|mcpu=cortex-m33 \
:%{!r:--be8}}}"
#endif
diff --git a/gcc/config/arm/freebsd.h b/gcc/config/arm/freebsd.h
index 0ade4e99be1..949c397521c 100644
--- a/gcc/config/arm/freebsd.h
+++ b/gcc/config/arm/freebsd.h
@@ -112,14 +112,6 @@
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE BITS_PER_WORD
-#if defined (TARGET_FREEBSD_ARMv6)
-#undef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm1176jzs
-#else
-#undef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm9
-#endif
-
/* FreeBSD 10 does not support unaligned access for armv6 and up.
Unaligned access support was added in FreeBSD 11. */
#if FBSD_MAJOR < 11
diff --git a/gcc/config/arm/linux-eabi.h b/gcc/config/arm/linux-eabi.h
index ace84816e06..9cfcf9fffd9 100644
--- a/gcc/config/arm/linux-eabi.h
+++ b/gcc/config/arm/linux-eabi.h
@@ -41,12 +41,6 @@
#undef ARM_DEFAULT_ABI
#define ARM_DEFAULT_ABI ARM_ABI_AAPCS_LINUX
-/* Default to armv5t so that thumb shared libraries work.
- The ARM10TDMI core is the default for armv5t, so set
- SUBTARGET_CPU_DEFAULT to achieve this. */
-#undef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm10tdmi
-
/* TARGET_BIG_ENDIAN_DEFAULT is set in
config.gcc for big endian configurations. */
#undef TARGET_LINKER_EMULATION
diff --git a/gcc/config/arm/linux-elf.h b/gcc/config/arm/linux-elf.h
index a94bd2d2f8d..cc17b51eeab 100644
--- a/gcc/config/arm/linux-elf.h
+++ b/gcc/config/arm/linux-elf.h
@@ -45,8 +45,6 @@
#undef TARGET_DEFAULT
#define TARGET_DEFAULT (TARGET_ENDIAN_DEFAULT)
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm6
-
#define SUBTARGET_EXTRA_LINK_SPEC " -m " TARGET_LINKER_EMULATION " -p"
/* We do not have any MULTILIB_OPTIONS specified, so there are no
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 59316de0041..4297511c186 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -2845,6 +2845,17 @@
[(set_attr "type" "neon_fp_minmax_s<q>")]
)
+;; v<maxmin>nm intrinsics.
+(define_insn "neon_<fmaxmin_op><mode>"
+ [(set (match_operand:VCVTF 0 "s_register_operand" "=w")
+ (unspec:VCVTF [(match_operand:VCVTF 1 "s_register_operand" "w")
+ (match_operand:VCVTF 2 "s_register_operand" "w")]
+ VMAXMINFNM))]
+ "TARGET_NEON && TARGET_FPU_ARMV8"
+ "<fmaxmin_op>.<V_s_elem>\t%<V_reg>0, %<V_reg>1, %<V_reg>2"
+ [(set_attr "type" "neon_fp_minmax_s<q>")]
+)
+
;; Vector forms for the IEEE-754 fmax()/fmin() functions
(define_insn "<fmaxmin><mode>3"
[(set (match_operand:VCVTF 0 "s_register_operand" "=w")
diff --git a/gcc/config/arm/symbian.h b/gcc/config/arm/symbian.h
index fc9c350cd08..af078d57a2c 100644
--- a/gcc/config/arm/symbian.h
+++ b/gcc/config/arm/symbian.h
@@ -59,12 +59,6 @@
/* Support the "dllimport" attribute. */
#define TARGET_DLLIMPORT_DECL_ATTRIBUTES 1
-/* Symbian OS assumes ARM V5 or above. Since -march=armv5 is
- equivalent to making the ARM 10TDMI core the default, we can set
- SUBTARGET_CPU_DEFAULT and get an equivalent effect. */
-#undef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm10tdmi
-
/* The assembler should assume VFP FPU format, and armv5t. */
#undef SUBTARGET_ASM_FLOAT_SPEC
#define SUBTARGET_ASM_FLOAT_SPEC \
diff --git a/gcc/config/arm/unknown-elf.h b/gcc/config/arm/unknown-elf.h
index fafe0574ee1..e5c050785a6 100644
--- a/gcc/config/arm/unknown-elf.h
+++ b/gcc/config/arm/unknown-elf.h
@@ -88,10 +88,6 @@
} \
while (0)
-#ifndef SUBTARGET_CPU_DEFAULT
-#define SUBTARGET_CPU_DEFAULT TARGET_CPU_arm7tdmi
-#endif
-
/* The libgcc udivmod functions may throw exceptions. If newlib is
configured to support long longs in I/O, then printf will depend on
udivmoddi4, which will depend on the exception unwind routines,
diff --git a/gcc/config/bfin/bfin.c b/gcc/config/bfin/bfin.c
index 2dfd03865d9..5f0efd9b544 100644
--- a/gcc/config/bfin/bfin.c
+++ b/gcc/config/bfin/bfin.c
@@ -3432,7 +3432,8 @@ hwloop_optimize (hwloop_info loop)
basic_block bb;
rtx_insn *insn, *last_insn;
rtx loop_init, start_label, end_label;
- rtx iter_reg, scratchreg, scratch_init, scratch_init_insn;
+ rtx iter_reg, scratchreg, scratch_init;
+ rtx_insn *scratch_init_insn;
rtx lc_reg, lt_reg, lb_reg;
rtx seq_end;
rtx_insn *seq;
@@ -3453,7 +3454,7 @@ hwloop_optimize (hwloop_info loop)
scratchreg = NULL_RTX;
scratch_init = iter_reg;
- scratch_init_insn = NULL_RTX;
+ scratch_init_insn = NULL;
if (!PREG_P (iter_reg) && loop->incoming_src)
{
basic_block bb_in = loop->incoming_src;
@@ -3977,7 +3978,7 @@ bfin_gen_bundles (void)
for (insn = BB_HEAD (bb);; insn = next)
{
int at_end;
- rtx delete_this = NULL_RTX;
+ rtx_insn *delete_this = NULL;
if (NONDEBUG_INSN_P (insn))
{
diff --git a/gcc/config/c6x/c6x.c b/gcc/config/c6x/c6x.c
index f8c3d668dbe..6cb9185ca02 100644
--- a/gcc/config/c6x/c6x.c
+++ b/gcc/config/c6x/c6x.c
@@ -4856,7 +4856,7 @@ find_last_same_clock (rtx_insn *insn)
the SEQUENCEs that represent execute packets. */
static void
-reorg_split_calls (rtx *call_labels)
+reorg_split_calls (rtx_insn **call_labels)
{
unsigned int reservation_mask = 0;
rtx_insn *insn = get_insns ();
@@ -4878,7 +4878,7 @@ reorg_split_calls (rtx *call_labels)
if (returning_call_p (insn))
{
- rtx label = gen_label_rtx ();
+ rtx_code_label *label = gen_label_rtx ();
rtx labelref = gen_rtx_LABEL_REF (Pmode, label);
rtx reg = gen_rtx_REG (SImode, RETURN_ADDR_REGNO);
@@ -5029,7 +5029,7 @@ reorg_split_calls (rtx *call_labels)
scheduling was run earlier. */
static void
-reorg_emit_nops (rtx *call_labels)
+reorg_emit_nops (rtx_insn **call_labels)
{
bool first;
rtx last_call;
@@ -5921,7 +5921,6 @@ static void
c6x_reorg (void)
{
basic_block bb;
- rtx *call_labels;
bool do_selsched = (c6x_flag_schedule_insns2 && flag_selective_scheduling2
&& !maybe_skip_selective_scheduling ());
@@ -5967,7 +5966,7 @@ c6x_reorg (void)
}
sched_no_dce = false;
- call_labels = XCNEWVEC (rtx, get_max_uid () + 1);
+ rtx_insn **call_labels = XCNEWVEC (rtx_insn *, get_max_uid () + 1);
reorg_split_calls (call_labels);
diff --git a/gcc/config/frv/frv.c b/gcc/config/frv/frv.c
index 50899a7e487..fb01685fb89 100644
--- a/gcc/config/frv/frv.c
+++ b/gcc/config/frv/frv.c
@@ -7594,7 +7594,7 @@ static void
frv_reorder_packet (void)
{
unsigned int cursor[NUM_GROUPS];
- rtx insns[ARRAY_SIZE (frv_unit_groups)];
+ rtx_insn *insns[ARRAY_SIZE (frv_unit_groups)];
unsigned int unit, to, from;
enum frv_insn_group group;
struct frv_packet_group *packet_group;
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f70eb43c922..a5c4ba7b630 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -80,6 +80,8 @@ along with GCC; see the file COPYING3. If not see
#include "fold-const-call.h"
#include "tree-vrp.h"
#include "tree-ssanames.h"
+#include "selftest.h"
+#include "selftest-rtl.h"
/* This file should be included last. */
#include "target-def.h"
@@ -2803,11 +2805,24 @@ dimode_scalar_to_vector_candidate_p (rtx_insn *insn)
switch (GET_CODE (src))
{
+ case ASHIFT:
+ case LSHIFTRT:
+ /* Consider only non-variable shifts narrower
+ than general register width. */
+ if (!(CONST_INT_P (XEXP (src, 1))
+ && IN_RANGE (INTVAL (XEXP (src, 1)), 0, 31)))
+ return false;
+ break;
+
case PLUS:
case MINUS:
case IOR:
case XOR:
case AND:
+ if (!REG_P (XEXP (src, 1))
+ && !MEM_P (XEXP (src, 1))
+ && !CONST_INT_P (XEXP (src, 1)))
+ return false;
break;
case REG:
@@ -2830,11 +2845,6 @@ dimode_scalar_to_vector_candidate_p (rtx_insn *insn)
|| !REG_P (XEXP (XEXP (src, 0), 0))))
return false;
- if (!REG_P (XEXP (src, 1))
- && !MEM_P (XEXP (src, 1))
- && !CONST_INT_P (XEXP (src, 1)))
- return false;
-
if ((GET_MODE (XEXP (src, 0)) != DImode
&& !CONST_INT_P (XEXP (src, 0)))
|| (GET_MODE (XEXP (src, 1)) != DImode
@@ -3385,6 +3395,13 @@ dimode_scalar_chain::compute_convert_gain ()
gain += 2 * ix86_cost->int_store[2] - ix86_cost->sse_store[1];
else if (MEM_P (src) && REG_P (dst))
gain += 2 * ix86_cost->int_load[2] - ix86_cost->sse_load[1];
+ else if (GET_CODE (src) == ASHIFT
+ || GET_CODE (src) == LSHIFTRT)
+ {
+ gain += ix86_cost->add;
+ if (CONST_INT_P (XEXP (src, 0)))
+ gain -= vector_const_cost (XEXP (src, 0));
+ }
else if (GET_CODE (src) == PLUS
|| GET_CODE (src) == MINUS
|| GET_CODE (src) == IOR
@@ -3736,6 +3753,12 @@ dimode_scalar_chain::convert_insn (rtx_insn *insn)
switch (GET_CODE (src))
{
+ case ASHIFT:
+ case LSHIFTRT:
+ convert_op (&XEXP (src, 0), insn);
+ PUT_MODE (src, V2DImode);
+ break;
+
case PLUS:
case MINUS:
case IOR:
@@ -20376,7 +20399,8 @@ ix86_split_idivmod (machine_mode mode, rtx operands[],
bool signed_p)
{
rtx_code_label *end_label, *qimode_label;
- rtx insn, div, mod;
+ rtx div, mod;
+ rtx_insn *insn;
rtx scratch, tmp0, tmp1, tmp2;
rtx (*gen_divmod4_1) (rtx, rtx, rtx, rtx);
rtx (*gen_zero_extend) (rtx, rtx);
@@ -23558,6 +23582,7 @@ ix86_expand_sse_cmp (rtx dest, enum rtx_code code, rtx cmp_op0, rtx cmp_op1,
cmp_op1 = force_reg (cmp_ops_mode, cmp_op1);
if (optimize
+ || (maskcmp && cmp_mode != mode)
|| (op_true && reg_overlap_mentioned_p (dest, op_true))
|| (op_false && reg_overlap_mentioned_p (dest, op_false)))
dest = gen_reg_rtx (maskcmp ? cmp_mode : mode);
@@ -33515,7 +33540,7 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi)
gsi_insert_before (gsi, g, GSI_SAME_STMT);
g = gimple_build_assign (gimple_call_lhs (stmt), NOP_EXPR, lhs);
gimple_set_location (g, loc);
- gsi_replace (gsi, g, true);
+ gsi_replace (gsi, g, false);
return true;
}
break;
@@ -33533,7 +33558,7 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi)
location_t loc = gimple_location (stmt);
gimple *g = gimple_build_assign (gimple_call_lhs (stmt), arg0);
gimple_set_location (g, loc);
- gsi_replace (gsi, g, true);
+ gsi_replace (gsi, g, false);
return true;
}
break;
@@ -33550,7 +33575,7 @@ ix86_gimple_fold_builtin (gimple_stmt_iterator *gsi)
arg0 = gimple_call_arg (stmt, 0);
gimple *g = gimple_build_assign (gimple_call_lhs (stmt), arg0);
gimple_set_location (g, loc);
- gsi_replace (gsi, g, true);
+ gsi_replace (gsi, g, false);
return true;
}
break;
@@ -50571,8 +50596,70 @@ ix86_addr_space_zero_address_valid (addr_space_t as)
{
return as != ADDR_SPACE_GENERIC;
}
-#undef TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID
-#define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID ix86_addr_space_zero_address_valid
+
+static void
+ix86_init_libfuncs (void)
+{
+ if (TARGET_64BIT)
+ {
+ set_optab_libfunc (sdivmod_optab, TImode, "__divmodti4");
+ set_optab_libfunc (udivmod_optab, TImode, "__udivmodti4");
+ }
+ else
+ {
+ set_optab_libfunc (sdivmod_optab, DImode, "__divmoddi4");
+ set_optab_libfunc (udivmod_optab, DImode, "__udivmoddi4");
+ }
+
+#if TARGET_MACHO
+ darwin_rename_builtins ();
+#endif
+}
+
+/* Generate call to __divmoddi4. */
+
+static void
+ix86_expand_divmod_libfunc (rtx libfunc, machine_mode mode,
+ rtx op0, rtx op1,
+ rtx *quot_p, rtx *rem_p)
+{
+ rtx rem = assign_386_stack_local (mode, SLOT_TEMP);
+
+ rtx quot = emit_library_call_value (libfunc, NULL_RTX, LCT_NORMAL,
+ mode, 3,
+ op0, GET_MODE (op0),
+ op1, GET_MODE (op1),
+ XEXP (rem, 0), Pmode);
+ *quot_p = quot;
+ *rem_p = rem;
+}
+
+/* Target-specific selftests. */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that hard regs are dumped as expected (in compact mode). */
+
+static void
+ix86_test_dumping_hard_regs ()
+{
+ ASSERT_RTL_DUMP_EQ ("(reg:SI ax)", gen_raw_REG (SImode, 0));
+ ASSERT_RTL_DUMP_EQ ("(reg:SI dx)", gen_raw_REG (SImode, 1));
+}
+
+/* Run all target-specific selftests. */
+
+static void
+ix86_run_selftests (void)
+{
+ ix86_test_dumping_hard_regs ();
+}
+
+} // namespace selftest
+
+#endif /* CHECKING_P */
/* Initialize the GCC target structure. */
#undef TARGET_RETURN_IN_MEMORY
@@ -50957,11 +51044,6 @@ ix86_addr_space_zero_address_valid (addr_space_t as)
#undef TARGET_CONDITIONAL_REGISTER_USAGE
#define TARGET_CONDITIONAL_REGISTER_USAGE ix86_conditional_register_usage
-#if TARGET_MACHO
-#undef TARGET_INIT_LIBFUNCS
-#define TARGET_INIT_LIBFUNCS darwin_rename_builtins
-#endif
-
#undef TARGET_LOOP_UNROLL_ADJUST
#define TARGET_LOOP_UNROLL_ADJUST ix86_loop_unroll_adjust
@@ -51052,6 +51134,20 @@ ix86_addr_space_zero_address_valid (addr_space_t as)
#undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
+#undef TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID
+#define TARGET_ADDR_SPACE_ZERO_ADDRESS_VALID ix86_addr_space_zero_address_valid
+
+#undef TARGET_INIT_LIBFUNCS
+#define TARGET_INIT_LIBFUNCS ix86_init_libfuncs
+
+#undef TARGET_EXPAND_DIVMOD_LIBFUNC
+#define TARGET_EXPAND_DIVMOD_LIBFUNC ix86_expand_divmod_libfunc
+
+#if CHECKING_P
+#undef TARGET_RUN_TARGET_SELFTESTS
+#define TARGET_RUN_TARGET_SELFTESTS selftest::ix86_run_selftests
+#endif /* #if CHECKING_P */
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-i386.h"
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index 31a2267a0f8..85571571599 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -1803,7 +1803,7 @@ ia64_expand_compare (rtx *expr, rtx *op0, rtx *op1)
};
int magic;
enum rtx_code ncode;
- rtx ret, insns;
+ rtx ret;
gcc_assert (cmptf_libfunc && GET_MODE (*op1) == TFmode);
switch (code)
@@ -1842,7 +1842,7 @@ ia64_expand_compare (rtx *expr, rtx *op0, rtx *op1)
emit_insn (gen_rtx_SET (cmp, gen_rtx_fmt_ee (ncode, BImode,
ret, const0_rtx)));
- insns = get_insns ();
+ rtx_insn *insns = get_insns ();
end_sequence ();
emit_libcall_block (insns, cmp, cmp,
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index ccd9675d3ba..6077201a3b0 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -3781,13 +3781,13 @@ m32c_prepare_shift (rtx * operands, int scale, int shift_code)
undefined to skip one of the comparisons. */
rtx count;
- rtx label, tempvar;
+ rtx tempvar;
rtx_insn *insn;
emit_move_insn (operands[0], operands[1]);
count = temp;
- label = gen_label_rtx ();
+ rtx_code_label *label = gen_label_rtx ();
LABEL_NUSES (label) ++;
tempvar = gen_reg_rtx (mode);
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index ec37bd76f55..3d7895d264c 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -706,7 +706,7 @@
(minus:SI (const_int 31)
(match_operand:SI 1 "general_operand" "di")))
(const_int 0)))]
- ""
+ "!(CONST_INT_P (operands[1]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
{
return output_btst (operands, operands[1], operands[0], insn, 31);
})
@@ -765,9 +765,10 @@
(cc0)
(compare (zero_extract:SI (match_operand:SI 0 "register_operand" "do")
(const_int 1)
- (match_operand:SI 1 "const_int_operand" "n"))
+ (match_operand:SI 1 "const_int_operand" "n"))
(const_int 0)))]
- "!TARGET_COLDFIRE"
+ "!TARGET_COLDFIRE
+ && !(REG_P (operands[0]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
{
if (GET_CODE (operands[0]) == MEM)
{
@@ -790,7 +791,8 @@
(const_int 1)
(match_operand:SI 1 "const_int_operand" "n"))
(const_int 0)))]
- "TARGET_COLDFIRE"
+ "TARGET_COLDFIRE
+ && !(REG_P (operands[0]) && !IN_RANGE (INTVAL (operands[1]), 0, 31))"
{
if (GET_CODE (operands[0]) == MEM)
{
@@ -5397,6 +5399,7 @@
(match_operand:SI 2 "const_int_operand" "n"))
(match_operand:SI 3 "register_operand" "d"))]
"TARGET_68020 && TARGET_BITFIELD
+ && IN_RANGE (INTVAL (operands[2]), 0, 31)
&& (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
&& INTVAL (operands[2]) % INTVAL (operands[1]) == 0"
{
@@ -5438,6 +5441,7 @@
(match_operand:SI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n")))]
"TARGET_68020 && TARGET_BITFIELD
+ && IN_RANGE (INTVAL (operands[3]), 0, 31)
&& (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
{
@@ -5480,6 +5484,7 @@
(match_operand:SI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n")))]
"TARGET_68020 && TARGET_BITFIELD
+ && IN_RANGE (INTVAL (operands[3]), 0, 31)
&& (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
&& INTVAL (operands[3]) % INTVAL (operands[2]) == 0"
{
@@ -5610,7 +5615,7 @@
(sign_extract:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n")))]
- "TARGET_68020 && TARGET_BITFIELD"
+ "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[3]), 0, 31)"
"bfexts %1{%b3:%b2},%0")
(define_insn "*extv_bfextu_reg"
@@ -5618,7 +5623,7 @@
(zero_extract:SI (match_operand:SI 1 "register_operand" "d")
(match_operand:SI 2 "const_int_operand" "n")
(match_operand:SI 3 "const_int_operand" "n")))]
- "TARGET_68020 && TARGET_BITFIELD"
+ "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[3]), 0, 31)"
{
if (GET_CODE (operands[2]) == CONST_INT)
{
@@ -5637,7 +5642,7 @@
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))
(const_int 0))]
- "TARGET_68020 && TARGET_BITFIELD"
+ "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
{
CC_STATUS_INIT;
return "bfclr %0{%b2:%b1}";
@@ -5648,7 +5653,7 @@
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))
(const_int -1))]
- "TARGET_68020 && TARGET_BITFIELD"
+ "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
{
CC_STATUS_INIT;
return "bfset %0{%b2:%b1}";
@@ -5659,7 +5664,7 @@
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "const_int_operand" "n"))
(match_operand:SI 3 "register_operand" "d"))]
- "TARGET_68020 && TARGET_BITFIELD"
+ "TARGET_68020 && TARGET_BITFIELD && IN_RANGE (INTVAL (operands[2]), 0, 31)"
{
#if 0
/* These special cases are now recognized by a specific pattern. */
@@ -5707,7 +5712,8 @@
(match_operand:SI 1 "const_int_operand" "n")
(match_operand:SI 2 "general_operand" "dn"))
(const_int 0)))]
- "TARGET_68020 && TARGET_BITFIELD"
+ "TARGET_68020 && TARGET_BITFIELD
+ && !(CONST_INT_P (operands[2]) && !IN_RANGE (INTVAL (operands[2]), 0, 31))"
{
if (operands[1] == const1_rtx
&& GET_CODE (operands[2]) == CONST_INT)
diff --git a/gcc/config/microblaze/linux.h b/gcc/config/microblaze/linux.h
index ae8523c19c3..b3bf43a8a84 100644
--- a/gcc/config/microblaze/linux.h
+++ b/gcc/config/microblaze/linux.h
@@ -29,6 +29,7 @@
#define TLS_NEEDS_GOT 1
#define GLIBC_DYNAMIC_LINKER "/lib/ld.so.1"
+#define UCLIBC_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
#if TARGET_BIG_ENDIAN_DEFAULT == 0 /* LE */
#define MUSL_DYNAMIC_LINKER_E "%{mbig-endian:;:el}"
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 5c1a35a4f86..552b73adaf7 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -3396,10 +3396,11 @@ static GTY(()) rtx mips_tls_symbol;
(either global dynamic or local dynamic). V0 is an RTX for the
return value location. */
-static rtx
+static rtx_insn *
mips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0)
{
- rtx insn, loc, a0;
+ rtx loc, a0;
+ rtx_insn *insn;
a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST);
@@ -3455,7 +3456,7 @@ mips_get_tp (void)
static rtx
mips_legitimize_tls_address (rtx loc)
{
- rtx dest, insn, v0, tp, tmp1, tmp2, eqv, offset;
+ rtx dest, v0, tp, tmp1, tmp2, eqv, offset;
enum tls_model model;
model = SYMBOL_REF_TLS_MODEL (loc);
@@ -3468,33 +3469,37 @@ mips_legitimize_tls_address (rtx loc)
switch (model)
{
case TLS_MODEL_GLOBAL_DYNAMIC:
- v0 = gen_rtx_REG (Pmode, GP_RETURN);
- insn = mips_call_tls_get_addr (loc, SYMBOL_TLSGD, v0);
- dest = gen_reg_rtx (Pmode);
- emit_libcall_block (insn, dest, v0, loc);
- break;
+ {
+ v0 = gen_rtx_REG (Pmode, GP_RETURN);
+ rtx_insn *insn = mips_call_tls_get_addr (loc, SYMBOL_TLSGD, v0);
+ dest = gen_reg_rtx (Pmode);
+ emit_libcall_block (insn, dest, v0, loc);
+ break;
+ }
case TLS_MODEL_LOCAL_DYNAMIC:
- v0 = gen_rtx_REG (Pmode, GP_RETURN);
- insn = mips_call_tls_get_addr (loc, SYMBOL_TLSLDM, v0);
- tmp1 = gen_reg_rtx (Pmode);
-
- /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
- share the LDM result with other LD model accesses. */
- eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
- UNSPEC_TLS_LDM);
- emit_libcall_block (insn, tmp1, v0, eqv);
-
- offset = mips_unspec_address (loc, SYMBOL_DTPREL);
- if (mips_split_p[SYMBOL_DTPREL])
- {
- tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL);
- dest = gen_rtx_LO_SUM (Pmode, tmp2, offset);
- }
- else
- dest = expand_binop (Pmode, add_optab, tmp1, offset,
- 0, 0, OPTAB_DIRECT);
- break;
+ {
+ v0 = gen_rtx_REG (Pmode, GP_RETURN);
+ rtx_insn *insn = mips_call_tls_get_addr (loc, SYMBOL_TLSLDM, v0);
+ tmp1 = gen_reg_rtx (Pmode);
+
+ /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+ share the LDM result with other LD model accesses. */
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_TLS_LDM);
+ emit_libcall_block (insn, tmp1, v0, eqv);
+
+ offset = mips_unspec_address (loc, SYMBOL_DTPREL);
+ if (mips_split_p[SYMBOL_DTPREL])
+ {
+ tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL);
+ dest = gen_rtx_LO_SUM (Pmode, tmp2, offset);
+ }
+ else
+ dest = expand_binop (Pmode, add_optab, tmp1, offset,
+ 0, 0, OPTAB_DIRECT);
+ break;
+ }
case TLS_MODEL_INITIAL_EXEC:
tp = mips_get_tp ();
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index dbbc4db1410..e61bf408d5a 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -3163,7 +3163,7 @@ mn10300_bundle_liw (void)
Insert a SETLB insn just before LABEL. */
static void
-mn10300_insert_setlb_lcc (rtx label, rtx branch)
+mn10300_insert_setlb_lcc (rtx_insn *label, rtx branch)
{
rtx lcc, comparison, cmp_reg;
diff --git a/gcc/config/nvptx/nvptx.c b/gcc/config/nvptx/nvptx.c
index 8d86aa87545..68bf0a89a81 100644
--- a/gcc/config/nvptx/nvptx.c
+++ b/gcc/config/nvptx/nvptx.c
@@ -4515,7 +4515,7 @@ nvptx_expand_builtin (tree exp, rtx target, rtx ARG_UNUSED (subtarget),
/* Define dimension sizes for known hardware. */
#define PTX_VECTOR_LENGTH 32
#define PTX_WORKER_LENGTH 32
-#define PTX_GANG_DEFAULT 32
+#define PTX_GANG_DEFAULT 0 /* Defer to runtime. */
/* Implement TARGET_SIMT_VF target hook: number of threads in a warp. */
diff --git a/gcc/config/pa/pa.h b/gcc/config/pa/pa.h
index f0aa1ae68c6..77874821314 100644
--- a/gcc/config/pa/pa.h
+++ b/gcc/config/pa/pa.h
@@ -295,17 +295,19 @@ typedef struct GTY(()) machine_function
/* No data type wants to be aligned rounder than this. The long double
type has 16-byte alignment on the 64-bit target even though it was never
implemented in hardware. The software implementation only needs 8-byte
- alignment. This is to match the HP compilers. */
+ alignment. This matches the biggest alignment of the HP compilers. */
#define BIGGEST_ALIGNMENT (2 * BITS_PER_WORD)
/* Alignment, in bits, a C conformant malloc implementation has to provide.
The HP-UX malloc implementation provides a default alignment of 8 bytes.
- This can be increased with mallopt. The glibc implementation also provides
- 8-byte alignment. Note that this isn't enough for various POSIX types such
- as pthread_mutex_t. However, since we no longer need the 16-byte alignment
- for atomic operations, we ignore the nominal alignment specified for these
- types. The same is true for long double on 64-bit HP-UX. */
-#define MALLOC_ABI_ALIGNMENT (64)
+ It should be 16 bytes on the 64-bit target since long double has 16-byte
+ alignment. It can be increased with mallopt but it's non critical since
+ long double was never implemented in hardware. The glibc implementation
+ currently provides 8-byte alignment. It should be 16 bytes since various
+ POSIX types such as pthread_mutex_t require 16-byte alignment. Again,
+ this is non critical since 16-byte alignment is no longer needed for
+ atomic operations. */
+#define MALLOC_ABI_ALIGNMENT (TARGET_SOM ? 64 : 128)
/* Get around hp-ux assembler bug, and make strcpy of constants fast. */
#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
diff --git a/gcc/config/pa/pa.md b/gcc/config/pa/pa.md
index e4c806f84a8..6725504fce9 100644
--- a/gcc/config/pa/pa.md
+++ b/gcc/config/pa/pa.md
@@ -6249,6 +6249,21 @@
(set_attr "length" "4")])
(define_insn ""
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (plus:SI (mult:SI (match_operand:SI 2 "register_operand" "r")
+ (match_operand:SI 3 "mem_shadd_operand" ""))
+ (match_operand:SI 1 "register_operand" "r")))]
+ ""
+ "*
+{
+ int shift_val = exact_log2 (INTVAL (operands[3]));
+ operands[3] = GEN_INT (shift_val);
+ return \"{sh%o3addl %2,%1,%0|shladd,l %2,%o3,%1,%0}\";
+}"
+ [(set_attr "type" "binary")
+ (set_attr "length" "4")])
+
+(define_insn ""
[(set (match_operand:DI 0 "register_operand" "=r")
(plus:DI (ashift:DI (match_operand:DI 2 "register_operand" "r")
(match_operand:DI 3 "shadd_operand" ""))
@@ -6258,6 +6273,21 @@
[(set_attr "type" "binary")
(set_attr "length" "4")])
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=r")
+ (plus:DI (mult:DI (match_operand:DI 2 "register_operand" "r")
+ (match_operand:DI 3 "mem_shadd_operand" ""))
+ (match_operand:DI 1 "register_operand" "r")))]
+ "TARGET_64BIT"
+ "*
+{
+ int shift_val = exact_log2 (INTVAL (operands[3]));
+ operands[3] = GEN_INT (shift_val);
+ return \"shladd,l %2,%o3,%1,%0\";
+}"
+ [(set_attr "type" "binary")
+ (set_attr "length" "4")])
+
(define_expand "ashlsi3"
[(set (match_operand:SI 0 "register_operand" "")
(ashift:SI (match_operand:SI 1 "lhs_lshift_operand" "")
diff --git a/gcc/config/pa/pa64-hpux.h b/gcc/config/pa/pa64-hpux.h
index c6cbc5f582c..8c09ede6104 100644
--- a/gcc/config/pa/pa64-hpux.h
+++ b/gcc/config/pa/pa64-hpux.h
@@ -336,7 +336,7 @@ do { \
#undef INIT_SECTION_ASM_OP
#define INIT_SECTION_ASM_OP ""
#undef FINI_SECTION_ASM_OP
-#define FINI_SECTION_ASM_OP
+#define FINI_SECTION_ASM_OP ""
/* We are using array initializers and don't want calls in the INIT
and FINI sections. */
diff --git a/gcc/config/rl78/rl78.c b/gcc/config/rl78/rl78.c
index 5375e18dd95..b8fe4c97550 100644
--- a/gcc/config/rl78/rl78.c
+++ b/gcc/config/rl78/rl78.c
@@ -2778,7 +2778,7 @@ process_postponed_content_update (void)
after WHERE. If TO already contains FROM then do nothing. Returns TO if
BEFORE is true, FROM otherwise. */
static rtx
-gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
+gen_and_emit_move (rtx to, rtx from, rtx_insn *where, bool before)
{
machine_mode mode = GET_MODE (to);
@@ -2833,7 +2833,7 @@ gen_and_emit_move (rtx to, rtx from, rtx where, bool before)
copy it into NEWBASE and return the updated MEM. Otherwise just
return M. Any needed insns are emitted before BEFORE. */
static rtx
-transcode_memory_rtx (rtx m, rtx newbase, rtx before)
+transcode_memory_rtx (rtx m, rtx newbase, rtx_insn *before)
{
rtx base, index, addendr;
int addend = 0;
@@ -2934,7 +2934,7 @@ transcode_memory_rtx (rtx m, rtx newbase, rtx before)
/* Copy SRC to accumulator (A or AX), placing any generated insns
before BEFORE. Returns accumulator RTX. */
static rtx
-move_to_acc (int opno, rtx before)
+move_to_acc (int opno, rtx_insn *before)
{
rtx src = OP (opno);
machine_mode mode = GET_MODE (src);
@@ -2949,7 +2949,7 @@ move_to_acc (int opno, rtx before)
}
static void
-force_into_acc (rtx src, rtx before)
+force_into_acc (rtx src, rtx_insn *before)
{
machine_mode mode = GET_MODE (src);
rtx move;
@@ -2968,7 +2968,7 @@ force_into_acc (rtx src, rtx before)
/* Copy accumulator (A or AX) to DEST, placing any generated insns
after AFTER. Returns accumulator RTX. */
static rtx
-move_from_acc (unsigned int opno, rtx after)
+move_from_acc (unsigned int opno, rtx_insn *after)
{
rtx dest = OP (opno);
machine_mode mode = GET_MODE (dest);
@@ -2982,7 +2982,7 @@ move_from_acc (unsigned int opno, rtx after)
/* Copy accumulator (A or AX) to REGNO, placing any generated insns
before BEFORE. Returns reg RTX. */
static rtx
-move_acc_to_reg (rtx acc, int regno, rtx before)
+move_acc_to_reg (rtx acc, int regno, rtx_insn *before)
{
machine_mode mode = GET_MODE (acc);
rtx reg;
@@ -2995,7 +2995,7 @@ move_acc_to_reg (rtx acc, int regno, rtx before)
/* Copy SRC to X, placing any generated insns before BEFORE.
Returns X RTX. */
static rtx
-move_to_x (int opno, rtx before)
+move_to_x (int opno, rtx_insn *before)
{
rtx src = OP (opno);
machine_mode mode = GET_MODE (src);
@@ -3018,7 +3018,7 @@ move_to_x (int opno, rtx before)
/* Copy OP (opno) to H or HL, placing any generated insns before BEFORE.
Returns H/HL RTX. */
static rtx
-move_to_hl (int opno, rtx before)
+move_to_hl (int opno, rtx_insn *before)
{
rtx src = OP (opno);
machine_mode mode = GET_MODE (src);
@@ -3041,7 +3041,7 @@ move_to_hl (int opno, rtx before)
/* Copy OP (opno) to E or DE, placing any generated insns before BEFORE.
Returns E/DE RTX. */
static rtx
-move_to_de (int opno, rtx before)
+move_to_de (int opno, rtx_insn *before)
{
rtx src = OP (opno);
machine_mode mode = GET_MODE (src);
diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h
index 8f07450d72b..989557f76c9 100644
--- a/gcc/config/rs6000/rs6000-protos.h
+++ b/gcc/config/rs6000/rs6000-protos.h
@@ -187,8 +187,13 @@ extern rtx rs6000_libcall_value (machine_mode);
extern rtx rs6000_va_arg (tree, tree);
extern int function_ok_for_sibcall (tree);
extern int rs6000_reg_parm_stack_space (tree, bool);
+extern void rs6000_asm_weaken_decl (FILE *, tree, const char *, const char *);
extern void rs6000_xcoff_declare_function_name (FILE *, const char *, tree);
extern void rs6000_xcoff_declare_object_name (FILE *, const char *, tree);
+extern void rs6000_xcoff_asm_output_aligned_decl_common (FILE *, tree,
+ const char *,
+ unsigned HOST_WIDE_INT,
+ unsigned HOST_WIDE_INT);
extern void rs6000_elf_declare_function_name (FILE *, const char *, tree);
extern bool rs6000_elf_in_small_data_p (const_tree);
#ifdef ARGS_SIZE_RTX
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index f9e47393288..b0c2b2e69ee 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -56,6 +56,7 @@
#include "sched-int.h"
#include "gimplify.h"
#include "gimple-iterator.h"
+#include "gimple-ssa.h"
#include "gimple-walk.h"
#include "intl.h"
#include "params.h"
@@ -1632,6 +1633,8 @@ static const struct attribute_spec rs6000_attribute_table[] =
#undef TARGET_FOLD_BUILTIN
#define TARGET_FOLD_BUILTIN rs6000_fold_builtin
+#undef TARGET_GIMPLE_FOLD_BUILTIN
+#define TARGET_GIMPLE_FOLD_BUILTIN rs6000_gimple_fold_builtin
#undef TARGET_EXPAND_BUILTIN
#define TARGET_EXPAND_BUILTIN rs6000_expand_builtin
@@ -16391,6 +16394,46 @@ rs6000_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED,
#endif
}
+/* Fold a machine-dependent built-in in GIMPLE. (For folding into
+ a constant, use rs6000_fold_builtin.) */
+
+bool
+rs6000_gimple_fold_builtin (gimple_stmt_iterator *gsi)
+{
+ gimple *stmt = gsi_stmt (*gsi);
+ tree fndecl = gimple_call_fndecl (stmt);
+ gcc_checking_assert (fndecl && DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD);
+ enum rs6000_builtins fn_code
+ = (enum rs6000_builtins) DECL_FUNCTION_CODE (fndecl);
+ tree arg0, arg1, lhs;
+
+ switch (fn_code)
+ {
+ /* Flavors of vec_add. We deliberately don't expand
+ P8V_BUILTIN_VADDUQM as it gets lowered from V1TImode to
+ TImode, resulting in much poorer code generation. */
+ case ALTIVEC_BUILTIN_VADDUBM:
+ case ALTIVEC_BUILTIN_VADDUHM:
+ case ALTIVEC_BUILTIN_VADDUWM:
+ case P8V_BUILTIN_VADDUDM:
+ case ALTIVEC_BUILTIN_VADDFP:
+ case VSX_BUILTIN_XVADDDP:
+ {
+ arg0 = gimple_call_arg (stmt, 0);
+ arg1 = gimple_call_arg (stmt, 1);
+ lhs = gimple_call_lhs (stmt);
+ gimple *g = gimple_build_assign (lhs, PLUS_EXPR, arg0, arg1);
+ gimple_set_location (g, gimple_location (stmt));
+ gsi_replace (gsi, g, true);
+ return true;
+ }
+ default:
+ break;
+ }
+
+ return false;
+}
+
/* Expand an expression EXP that calls a built-in function,
with result going to TARGET if that's convenient
(and in mode MODE if that's convenient).
@@ -16939,11 +16982,10 @@ rs6000_init_builtins (void)
def_builtin ("__builtin_cpu_is", ftype, RS6000_BUILTIN_CPU_IS);
def_builtin ("__builtin_cpu_supports", ftype, RS6000_BUILTIN_CPU_SUPPORTS);
-#if TARGET_XCOFF
/* AIX libm provides clog as __clog. */
- if ((tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
+ if (TARGET_XCOFF &&
+ (tdecl = builtin_decl_explicit (BUILT_IN_CLOG)) != NULL_TREE)
set_user_assembler_name (tdecl, "__clog");
-#endif
#ifdef SUBTARGET_INIT_BUILTINS
SUBTARGET_INIT_BUILTINS;
@@ -26996,8 +27038,8 @@ output_probe_stack_range (rtx reg1, rtx reg2)
pointer. That fails when saving regs off r1, and sched moves the
r31 setup past the reg saves. */
-static rtx
-rs6000_frame_related (rtx insn, rtx reg, HOST_WIDE_INT val,
+static rtx_insn *
+rs6000_frame_related (rtx_insn *insn, rtx reg, HOST_WIDE_INT val,
rtx reg2, rtx repl2)
{
rtx repl;
@@ -27161,11 +27203,11 @@ gen_frame_store (rtx reg, rtx frame_reg, int offset)
/* Save a register into the frame, and emit RTX_FRAME_RELATED_P notes.
Save REGNO into [FRAME_REG + OFFSET] in mode MODE. */
-static rtx
+static rtx_insn *
emit_frame_save (rtx frame_reg, machine_mode mode,
unsigned int regno, int offset, HOST_WIDE_INT frame_reg_to_sp)
{
- rtx reg, insn;
+ rtx reg;
/* Some cases that need register indexed addressing. */
gcc_checking_assert (!((TARGET_ALTIVEC_ABI && ALTIVEC_VECTOR_MODE (mode))
@@ -27176,7 +27218,7 @@ emit_frame_save (rtx frame_reg, machine_mode mode,
&& !SPE_CONST_OFFSET_OK (offset))));
reg = gen_rtx_REG (mode, regno);
- insn = emit_insn (gen_frame_store (reg, frame_reg, offset));
+ rtx_insn *insn = emit_insn (gen_frame_store (reg, frame_reg, offset));
return rs6000_frame_related (insn, frame_reg, frame_reg_to_sp,
NULL_RTX, NULL_RTX);
}
@@ -27444,7 +27486,7 @@ ptr_regno_for_savres (int sel)
out-of-line register save/restore routine, and emit the insn
or jump_insn as appropriate. */
-static rtx
+static rtx_insn *
rs6000_emit_savres_rtx (rs6000_stack_t *info,
rtx frame_reg_rtx, int save_area_offset, int lr_offset,
machine_mode reg_mode, int sel)
@@ -27454,7 +27496,8 @@ rs6000_emit_savres_rtx (rs6000_stack_t *info,
int reg_size = GET_MODE_SIZE (reg_mode);
rtx sym;
rtvec p;
- rtx par, insn;
+ rtx par;
+ rtx_insn *insn;
offset = 0;
start_reg = ((sel & SAVRES_REG) == SAVRES_GPR
@@ -27633,6 +27676,9 @@ rs6000_get_separate_components (void)
if (WORLD_SAVE_P (info))
return NULL;
+ if (TARGET_SPE_ABI)
+ return NULL;
+
sbitmap components = sbitmap_alloc (32);
bitmap_clear (components);
@@ -27854,7 +27900,7 @@ rs6000_emit_prologue (void)
rtx frame_reg_rtx = sp_reg_rtx;
unsigned int cr_save_regno;
rtx cr_save_rtx = NULL_RTX;
- rtx insn;
+ rtx_insn *insn;
int strategy;
int using_static_chain_p = (cfun->static_chain_decl != NULL_TREE
&& df_regs_ever_live_p (STATIC_CHAIN_REGNUM)
@@ -28360,12 +28406,12 @@ rs6000_emit_prologue (void)
if (regno == INVALID_REGNUM)
break;
- insn
+ rtx set
= gen_frame_store (gen_rtx_REG (reg_mode, regno),
sp_reg_rtx,
info->ehrd_offset + sp_off + reg_size * (int) i);
- RTVEC_ELT (p, i) = insn;
- RTX_FRAME_RELATED_P (insn) = 1;
+ RTVEC_ELT (p, i) = set;
+ RTX_FRAME_RELATED_P (set) = 1;
}
insn = emit_insn (gen_blockage ());
@@ -28377,7 +28423,8 @@ rs6000_emit_prologue (void)
if (TARGET_AIX && crtl->calls_eh_return)
{
rtx tmp_reg, tmp_reg_si, hi, lo, compare_result, toc_save_done, jump;
- rtx save_insn, join_insn, note;
+ rtx join_insn, note;
+ rtx_insn *save_insn;
long toc_restore_insn;
tmp_reg = gen_rtx_REG (Pmode, 11);
@@ -35316,6 +35363,31 @@ rs6000_declare_alias (struct symtab_node *n, void *d)
return false;
}
+
+#ifdef HAVE_GAS_HIDDEN
+/* Helper function to calculate visibility of a DECL
+ and return the value as a const string. */
+
+static const char *
+rs6000_xcoff_visibility (tree decl)
+{
+ static const char * const visibility_types[] = {
+ "", ",protected", ",hidden", ",internal"
+ };
+
+ enum symbol_visibility vis = DECL_VISIBILITY (decl);
+
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && cgraph_node::get (decl)
+ && cgraph_node::get (decl)->instrumentation_clone
+ && cgraph_node::get (decl)->instrumented_version)
+ vis = DECL_VISIBILITY (cgraph_node::get (decl)->instrumented_version->decl);
+
+ return visibility_types[vis];
+}
+#endif
+
+
/* This macro produces the initial definition of a function name.
On the RS/6000, we need to place an extra '.' in the function name and
output the function descriptor.
@@ -35355,6 +35427,9 @@ rs6000_xcoff_declare_function_name (FILE *file, const char *name, tree decl)
}
fputs ("\t.globl .", file);
RS6000_OUTPUT_BASENAME (file, buffer);
+#ifdef HAVE_GAS_HIDDEN
+ fputs (rs6000_xcoff_visibility (decl), file);
+#endif
putc ('\n', file);
}
}
@@ -35399,6 +35474,52 @@ rs6000_xcoff_declare_function_name (FILE *file, const char *name, tree decl)
return;
}
+
+/* Output assembly language to globalize a symbol from a DECL,
+ possibly with visibility. */
+
+void
+rs6000_xcoff_asm_globalize_decl_name (FILE *stream, tree decl)
+{
+ const char *name = XSTR (XEXP (DECL_RTL (decl), 0), 0);
+ fputs (GLOBAL_ASM_OP, stream);
+ RS6000_OUTPUT_BASENAME (stream, name);
+#ifdef HAVE_GAS_HIDDEN
+ fputs (rs6000_xcoff_visibility (decl), stream);
+#endif
+ putc ('\n', stream);
+}
+
+/* Output assembly language to define a symbol as COMMON from a DECL,
+ possibly with visibility. */
+
+void
+rs6000_xcoff_asm_output_aligned_decl_common (FILE *stream,
+ tree decl ATTRIBUTE_UNUSED,
+ const char *name,
+ unsigned HOST_WIDE_INT size,
+ unsigned HOST_WIDE_INT align)
+{
+ unsigned HOST_WIDE_INT align2 = 2;
+
+ if (align > 32)
+ align2 = floor_log2 (align / BITS_PER_UNIT);
+ else if (size > 4)
+ align2 = 3;
+
+ fputs (COMMON_ASM_OP, stream);
+ RS6000_OUTPUT_BASENAME (stream, name);
+
+ fprintf (stream,
+ "," HOST_WIDE_INT_PRINT_UNSIGNED "," HOST_WIDE_INT_PRINT_UNSIGNED,
+ size, align2);
+
+#ifdef HAVE_GAS_HIDDEN
+ fputs (rs6000_xcoff_visibility (decl), stream);
+#endif
+ putc ('\n', stream);
+}
+
/* This macro produces the initial definition of a object (variable) name.
Because AIX assembler's .set command has unexpected semantics, we output
all aliases as alternative labels in front of the definition. */
@@ -35409,8 +35530,8 @@ rs6000_xcoff_declare_object_name (FILE *file, const char *name, tree decl)
struct declare_alias_data data = {file, false};
RS6000_OUTPUT_BASENAME (file, name);
fputs (":\n", file);
- symtab_node::get (decl)->call_for_symbol_and_aliases (rs6000_declare_alias,
- &data, true);
+ symtab_node::get_create (decl)->call_for_symbol_and_aliases (rs6000_declare_alias,
+ &data, true);
}
/* Overide the default 'SYMBOL-.' syntax with AIX compatible 'SYMBOL-$'. */
@@ -35480,6 +35601,45 @@ rs6000_xcoff_encode_section_info (tree decl, rtx rtl, int first)
#endif /* HAVE_AS_TLS */
#endif /* TARGET_XCOFF */
+void
+rs6000_asm_weaken_decl (FILE *stream, tree decl,
+ const char *name, const char *val)
+{
+ fputs ("\t.weak\t", stream);
+ RS6000_OUTPUT_BASENAME (stream, name);
+ if (decl && TREE_CODE (decl) == FUNCTION_DECL
+ && DEFAULT_ABI == ABI_AIX && DOT_SYMBOLS)
+ {
+ if (TARGET_XCOFF)
+ fputs ("[DS]", stream);
+#if TARGET_XCOFF && HAVE_GAS_HIDDEN
+ if (TARGET_XCOFF)
+ fputs (rs6000_xcoff_visibility (decl), stream);
+#endif
+ fputs ("\n\t.weak\t.", stream);
+ RS6000_OUTPUT_BASENAME (stream, name);
+ }
+#if TARGET_XCOFF && HAVE_GAS_HIDDEN
+ if (TARGET_XCOFF)
+ fputs (rs6000_xcoff_visibility (decl), stream);
+#endif
+ fputc ('\n', stream);
+ if (val)
+ {
+ ASM_OUTPUT_DEF (stream, name, val);
+ if (decl && TREE_CODE (decl) == FUNCTION_DECL
+ && DEFAULT_ABI == ABI_AIX && DOT_SYMBOLS)
+ {
+ fputs ("\t.set\t.", stream);
+ RS6000_OUTPUT_BASENAME (stream, name);
+ fputs (",.", stream);
+ RS6000_OUTPUT_BASENAME (stream, val);
+ fputc ('\n', stream);
+ }
+ }
+}
+
+
/* Return true if INSN should not be copied. */
static bool
@@ -38651,7 +38811,7 @@ rs6000_code_end (void)
TREE_STATIC (decl) = 1;
#if RS6000_WEAK
- if (USE_HIDDEN_LINKONCE)
+ if (USE_HIDDEN_LINKONCE && !TARGET_XCOFF)
{
cgraph_node::create (decl)->set_comdat_group (DECL_ASSEMBLER_NAME (decl));
targetm.asm_out.unique_section (decl, 0);
diff --git a/gcc/config/rs6000/rs6000.h b/gcc/config/rs6000/rs6000.h
index 4b83abdf753..1148212c7ff 100644
--- a/gcc/config/rs6000/rs6000.h
+++ b/gcc/config/rs6000/rs6000.h
@@ -442,14 +442,15 @@ extern const char *host_detect_local_cpu (int argc, const char **argv);
point. KFmode was added as a way to represent IEEE 128-bit floating point,
even if the default for long double is the IBM long double format.
Similarly IFmode is the IBM long double format even if the default is IEEE
- 128-bit. */
+ 128-bit. Don't allow IFmode if -msoft-float. */
#define FLOAT128_IEEE_P(MODE) \
((TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode)) \
|| ((MODE) == KFmode) || ((MODE) == KCmode))
#define FLOAT128_IBM_P(MODE) \
((!TARGET_IEEEQUAD && ((MODE) == TFmode || (MODE) == TCmode)) \
- || ((MODE) == IFmode) || ((MODE) == ICmode))
+ || (TARGET_HARD_FLOAT && TARGET_FPRS \
+ && ((MODE) == IFmode || (MODE) == ICmode)))
/* Helper macros to say whether a 128-bit floating point type can go in a
single vector register, or whether it needs paired scalar values. */
@@ -2281,35 +2282,8 @@ extern int toc_initialized;
#if RS6000_WEAK
/* Used in lieu of ASM_WEAKEN_LABEL. */
-#define ASM_WEAKEN_DECL(FILE, DECL, NAME, VAL) \
- do \
- { \
- fputs ("\t.weak\t", (FILE)); \
- RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
- if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL \
- && DEFAULT_ABI == ABI_AIX && DOT_SYMBOLS) \
- { \
- if (TARGET_XCOFF) \
- fputs ("[DS]", (FILE)); \
- fputs ("\n\t.weak\t.", (FILE)); \
- RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
- } \
- fputc ('\n', (FILE)); \
- if (VAL) \
- { \
- ASM_OUTPUT_DEF ((FILE), (NAME), (VAL)); \
- if ((DECL) && TREE_CODE (DECL) == FUNCTION_DECL \
- && DEFAULT_ABI == ABI_AIX && DOT_SYMBOLS) \
- { \
- fputs ("\t.set\t.", (FILE)); \
- RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
- fputs (",.", (FILE)); \
- RS6000_OUTPUT_BASENAME ((FILE), (VAL)); \
- fputc ('\n', (FILE)); \
- } \
- } \
- } \
- while (0)
+#define ASM_WEAKEN_DECL(FILE, DECL, NAME, VAL) \
+ rs6000_asm_weaken_decl ((FILE), (DECL), (NAME), (VAL))
#endif
#if HAVE_GAS_WEAKREF
diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md
index bc8e52d6f6a..d4095498981 100644
--- a/gcc/config/rs6000/rs6000.md
+++ b/gcc/config/rs6000/rs6000.md
@@ -376,7 +376,7 @@
(TF "TARGET_HARD_FLOAT
&& (TARGET_FPRS || TARGET_E500_DOUBLE)
&& TARGET_LONG_DOUBLE_128")
- (IF "TARGET_LONG_DOUBLE_128")
+ (IF "TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128")
(KF "TARGET_FLOAT128_TYPE")
(DD "TARGET_DFP")
(TD "TARGET_DFP")])
@@ -398,7 +398,7 @@
(define_mode_iterator FMOVE64 [DF DD])
(define_mode_iterator FMOVE64X [DI DF DD])
(define_mode_iterator FMOVE128 [(TF "TARGET_LONG_DOUBLE_128")
- (IF "TARGET_LONG_DOUBLE_128")
+ (IF "FLOAT128_IBM_P (IFmode)")
(TD "TARGET_HARD_FLOAT && TARGET_FPRS")])
(define_mode_iterator FMOVE128_FPR [(TF "FLOAT128_2REG_P (TFmode)")
@@ -4460,7 +4460,15 @@
(div:SFDF (match_operand:SFDF 1 "gpc_reg_operand" "")
(match_operand:SFDF 2 "gpc_reg_operand" "")))]
"TARGET_<MODE>_INSN && !TARGET_SIMPLE_FPU"
- "")
+{
+ if (RS6000_RECIP_AUTO_RE_P (<MODE>mode)
+ && can_create_pseudo_p () && flag_finite_math_only
+ && !flag_trapping_math && flag_reciprocal_math)
+ {
+ rs6000_emit_swdiv (operands[0], operands[1], operands[2], true);
+ DONE;
+ }
+})
(define_insn "*div<mode>3_fpr"
[(set (match_operand:SFDF 0 "gpc_reg_operand" "=<Ff>,<Fv2>")
diff --git a/gcc/config/rs6000/vector.md b/gcc/config/rs6000/vector.md
index 7240345bce0..05f3bdbee56 100644
--- a/gcc/config/rs6000/vector.md
+++ b/gcc/config/rs6000/vector.md
@@ -248,7 +248,15 @@
(div:VEC_F (match_operand:VEC_F 1 "vfloat_operand" "")
(match_operand:VEC_F 2 "vfloat_operand" "")))]
"VECTOR_UNIT_VSX_P (<MODE>mode)"
- "")
+{
+ if (RS6000_RECIP_AUTO_RE_P (<MODE>mode)
+ && can_create_pseudo_p () && flag_finite_math_only
+ && !flag_trapping_math && flag_reciprocal_math)
+ {
+ rs6000_emit_swdiv (operands[0], operands[1], operands[2], true);
+ DONE;
+ }
+})
(define_expand "neg<mode>2"
[(set (match_operand:VEC_F 0 "vfloat_operand" "")
diff --git a/gcc/config/rs6000/vsx.md b/gcc/config/rs6000/vsx.md
index 18f3e86e29f..2c74a8ebbe2 100644
--- a/gcc/config/rs6000/vsx.md
+++ b/gcc/config/rs6000/vsx.md
@@ -288,6 +288,16 @@
(V8HI "v")
(V4SI "wa")])
+;; Mode iterator for binary floating types other than double to
+;; optimize convert to that floating point type from an extract
+;; of an integer type
+(define_mode_iterator VSX_EXTRACT_FL [SF
+ (IF "FLOAT128_2REG_P (IFmode)")
+ (KF "TARGET_FLOAT128_HW")
+ (TF "FLOAT128_2REG_P (TFmode)
+ || (FLOAT128_IEEE_P (TFmode)
+ && TARGET_FLOAT128_HW)")])
+
;; Iterator for the 2 short vector types to do a splat from an integer
(define_mode_iterator VSX_SPLAT_I [V16QI V8HI])
@@ -1907,6 +1917,7 @@
[(set_attr "type" "vecdouble")])
;; Convert from 32-bit to 64-bit types
+;; Provide both vector and scalar targets
(define_insn "vsx_xvcvsxwdp"
[(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
(unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
@@ -1915,6 +1926,14 @@
"xvcvsxwdp %x0,%x1"
[(set_attr "type" "vecdouble")])
+(define_insn "vsx_xvcvsxwdp_df"
+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
+ (unspec:DF [(match_operand:V4SI 1 "vsx_register_operand" "wa")]
+ UNSPEC_VSX_CVSXWDP))]
+ "TARGET_VSX"
+ "xvcvsxwdp %x0,%x1"
+ [(set_attr "type" "vecdouble")])
+
(define_insn "vsx_xvcvuxwdp"
[(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,?wa")
(unspec:V2DF [(match_operand:V4SI 1 "vsx_register_operand" "wf,wa")]
@@ -1923,6 +1942,14 @@
"xvcvuxwdp %x0,%x1"
[(set_attr "type" "vecdouble")])
+(define_insn "vsx_xvcvuxwdp_df"
+ [(set (match_operand:DF 0 "vsx_register_operand" "=ws")
+ (unspec:DF [(match_operand:V4SI 1 "vsx_register_operand" "wa")]
+ UNSPEC_VSX_CVUXWDP))]
+ "TARGET_VSX"
+ "xvcvuxwdp %x0,%x1"
+ [(set_attr "type" "vecdouble")])
+
(define_insn "vsx_xvcvspsxds"
[(set (match_operand:V2DI 0 "vsx_register_operand" "=v,?wa")
(unspec:V2DI [(match_operand:V4SF 1 "vsx_register_operand" "wd,wa")]
@@ -2559,11 +2586,10 @@
(parallel [(match_operand:QI 2 "<VSX_EXTRACT_PREDICATE>" "n")]))))]
"VECTOR_MEM_VSX_P (<MODE>mode) && TARGET_VEXTRACTUB"
{
- int element = INTVAL (operands[2]);
+ /* Note, the element number has already been adjusted for endianness, so we
+ don't have to adjust it here. */
int unit_size = GET_MODE_UNIT_SIZE (<MODE>mode);
- int offset = ((VECTOR_ELT_ORDER_BIG)
- ? unit_size * element
- : unit_size * (GET_MODE_NUNITS (<MODE>mode) - 1 - element));
+ HOST_WIDE_INT offset = unit_size * INTVAL (operands[2]);
operands[2] = GEN_INT (offset);
if (unit_size == 4)
@@ -2574,11 +2600,11 @@
[(set_attr "type" "vecsimple")])
(define_insn_and_split "*vsx_extract_si"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,Z,Z,wJwK")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,wHwI,Z")
(vec_select:SI
- (match_operand:V4SI 1 "gpc_reg_operand" "v,wJwK,v,v")
- (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n,n,n,n")])))
- (clobber (match_scratch:V4SI 3 "=v,wJwK,v,v"))]
+ (match_operand:V4SI 1 "gpc_reg_operand" "wJv,wJv,wJv")
+ (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n,n,n")])))
+ (clobber (match_scratch:V4SI 3 "=wJv,wJv,wJv"))]
"VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
"#"
"&& reload_completed"
@@ -2628,7 +2654,7 @@
DONE;
}
- [(set_attr "type" "mftgpr,fpstore,fpstore,vecsimple")
+ [(set_attr "type" "mftgpr,vecperm,fpstore")
(set_attr "length" "8")])
(define_insn_and_split "*vsx_extract_<mode>_p8"
@@ -2714,6 +2740,107 @@
DONE;
})
+;; VSX_EXTRACT optimizations
+;; Optimize double d = (double) vec_extract (vi, <n>)
+;; Get the element into the top position and use XVCVSWDP/XVCVUWDP
+(define_insn_and_split "*vsx_extract_si_<uns>float_df"
+ [(set (match_operand:DF 0 "gpc_reg_operand" "=ws")
+ (any_float:DF
+ (vec_select:SI
+ (match_operand:V4SI 1 "gpc_reg_operand" "v")
+ (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n")]))))
+ (clobber (match_scratch:V4SI 3 "=v"))]
+ "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx element = operands[2];
+ rtx v4si_tmp = operands[3];
+ int value;
+
+ if (!VECTOR_ELT_ORDER_BIG)
+ element = GEN_INT (GET_MODE_NUNITS (V4SImode) - 1 - INTVAL (element));
+
+ /* If the value is in the correct position, we can avoid doing the VSPLT<x>
+ instruction. */
+ value = INTVAL (element);
+ if (value != 0)
+ {
+ if (GET_CODE (v4si_tmp) == SCRATCH)
+ v4si_tmp = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vspltw_direct (v4si_tmp, src, element));
+ }
+ else
+ v4si_tmp = src;
+
+ emit_insn (gen_vsx_xvcv<su>xwdp_df (dest, v4si_tmp));
+ DONE;
+})
+
+;; Optimize <type> f = (<type>) vec_extract (vi, <n>)
+;; where <type> is a floating point type that supported by the hardware that is
+;; not double. First convert the value to double, and then to the desired
+;; type.
+(define_insn_and_split "*vsx_extract_si_<uns>float_<mode>"
+ [(set (match_operand:VSX_EXTRACT_FL 0 "gpc_reg_operand" "=ww")
+ (any_float:VSX_EXTRACT_FL
+ (vec_select:SI
+ (match_operand:V4SI 1 "gpc_reg_operand" "v")
+ (parallel [(match_operand:QI 2 "const_0_to_3_operand" "n")]))))
+ (clobber (match_scratch:V4SI 3 "=v"))
+ (clobber (match_scratch:DF 4 "=ws"))]
+ "VECTOR_MEM_VSX_P (V4SImode) && TARGET_DIRECT_MOVE_64BIT"
+ "#"
+ "&& 1"
+ [(const_int 0)]
+{
+ rtx dest = operands[0];
+ rtx src = operands[1];
+ rtx element = operands[2];
+ rtx v4si_tmp = operands[3];
+ rtx df_tmp = operands[4];
+ int value;
+
+ if (!VECTOR_ELT_ORDER_BIG)
+ element = GEN_INT (GET_MODE_NUNITS (V4SImode) - 1 - INTVAL (element));
+
+ /* If the value is in the correct position, we can avoid doing the VSPLT<x>
+ instruction. */
+ value = INTVAL (element);
+ if (value != 0)
+ {
+ if (GET_CODE (v4si_tmp) == SCRATCH)
+ v4si_tmp = gen_reg_rtx (V4SImode);
+ emit_insn (gen_altivec_vspltw_direct (v4si_tmp, src, element));
+ }
+ else
+ v4si_tmp = src;
+
+ if (GET_CODE (df_tmp) == SCRATCH)
+ df_tmp = gen_reg_rtx (DFmode);
+
+ emit_insn (gen_vsx_xvcv<su>xwdp_df (df_tmp, v4si_tmp));
+
+ if (<MODE>mode == SFmode)
+ emit_insn (gen_truncdfsf2 (dest, df_tmp));
+ else if (<MODE>mode == TFmode && FLOAT128_IBM_P (TFmode))
+ emit_insn (gen_extenddftf2_vsx (dest, df_tmp));
+ else if (<MODE>mode == TFmode && FLOAT128_IEEE_P (TFmode)
+ && TARGET_FLOAT128_HW)
+ emit_insn (gen_extenddftf2_hw (dest, df_tmp));
+ else if (<MODE>mode == IFmode && FLOAT128_IBM_P (IFmode))
+ emit_insn (gen_extenddfif2 (dest, df_tmp));
+ else if (<MODE>mode == KFmode && TARGET_FLOAT128_HW)
+ emit_insn (gen_extenddfkf2_hw (dest, df_tmp));
+ else
+ gcc_unreachable ();
+
+ DONE;
+})
+
;; Expanders for builtins
(define_expand "vsx_mergel_<mode>"
[(use (match_operand:VSX_D 0 "vsx_register_operand" ""))
diff --git a/gcc/config/rs6000/xcoff.h b/gcc/config/rs6000/xcoff.h
index cfdc528ef95..f63d28720ce 100644
--- a/gcc/config/rs6000/xcoff.h
+++ b/gcc/config/rs6000/xcoff.h
@@ -89,6 +89,7 @@
#undef TARGET_DEBUG_UNWIND_INFO
#define TARGET_DEBUG_UNWIND_INFO rs6000_xcoff_debug_unwind_info
#define TARGET_ASM_OUTPUT_ANCHOR rs6000_xcoff_asm_output_anchor
+#define TARGET_ASM_GLOBALIZE_DECL_NAME rs6000_xcoff_asm_globalize_decl_name
#define TARGET_ASM_GLOBALIZE_LABEL rs6000_xcoff_asm_globalize_label
#define TARGET_ASM_INIT_SECTIONS rs6000_xcoff_asm_init_sections
#define TARGET_ASM_RELOC_RW_MASK rs6000_xcoff_reloc_rw_mask
@@ -102,6 +103,7 @@
#ifdef HAVE_AS_TLS
#define TARGET_ENCODE_SECTION_INFO rs6000_xcoff_encode_section_info
#endif
+#define ASM_OUTPUT_ALIGNED_DECL_COMMON rs6000_xcoff_asm_output_aligned_decl_common
/* FP save and restore routines. */
#define SAVE_FP_PREFIX "._savef"
@@ -217,18 +219,6 @@
#define COMMON_ASM_OP "\t.comm "
-#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
- do { fputs (COMMON_ASM_OP, (FILE)); \
- RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \
- if ((ALIGN) > 32) \
- fprintf ((FILE), "," HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", (SIZE), \
- floor_log2 ((ALIGN) / BITS_PER_UNIT)); \
- else if ((SIZE) > 4) \
- fprintf ((FILE), "," HOST_WIDE_INT_PRINT_UNSIGNED",3\n", (SIZE)); \
- else \
- fprintf ((FILE), "," HOST_WIDE_INT_PRINT_UNSIGNED"\n", (SIZE)); \
- } while (0)
-
/* This says how to output an assembler line
to define a local common symbol.
The assembler in AIX 6.1 and later supports an alignment argument.
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 3554f339f3f..3f98cd820d5 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -4840,7 +4840,8 @@ s390_emit_tls_call_insn (rtx result_reg, rtx tls_call)
static rtx
legitimize_tls_address (rtx addr, rtx reg)
{
- rtx new_rtx, tls_call, temp, base, r2, insn;
+ rtx new_rtx, tls_call, temp, base, r2;
+ rtx_insn *insn;
if (GET_CODE (addr) == SYMBOL_REF)
switch (tls_symbolic_operand (addr))
@@ -13280,7 +13281,7 @@ static bool
s390_fix_long_loop_prediction (rtx_insn *insn)
{
rtx set = single_set (insn);
- rtx code_label, label_ref, new_label;
+ rtx code_label, label_ref;
rtx_insn *uncond_jump;
rtx_insn *cur_insn;
rtx tmp;
@@ -13317,7 +13318,7 @@ s390_fix_long_loop_prediction (rtx_insn *insn)
if (!cur_insn || JUMP_P (cur_insn) || LABEL_P (cur_insn))
return false;
- new_label = gen_label_rtx ();
+ rtx_code_label *new_label = gen_label_rtx ();
uncond_jump = emit_jump_insn_after (
gen_rtx_SET (pc_rtx,
gen_rtx_LABEL_REF (VOIDmode, code_label)),
diff --git a/gcc/config/sh/sh-mem.cc b/gcc/config/sh/sh-mem.cc
index 1773f1df4d3..b965aed1684 100644
--- a/gcc/config/sh/sh-mem.cc
+++ b/gcc/config/sh/sh-mem.cc
@@ -204,7 +204,7 @@ sh_expand_cmpstr (rtx *operands)
rtx tmp2 = gen_reg_rtx (SImode);
rtx tmp3 = gen_reg_rtx (SImode);
- rtx jump;
+ rtx_insn *jump;
rtx_code_label *L_return = gen_label_rtx ();
rtx_code_label *L_loop_byte = gen_label_rtx ();
rtx_code_label *L_end_loop_byte = gen_label_rtx ();
@@ -342,7 +342,7 @@ sh_expand_cmpnstr (rtx *operands)
rtx tmp1 = gen_reg_rtx (SImode);
rtx tmp2 = gen_reg_rtx (SImode);
- rtx jump;
+ rtx_insn *jump;
rtx_code_label *L_return = gen_label_rtx ();
rtx_code_label *L_loop_byte = gen_label_rtx ();
rtx_code_label *L_end_loop_byte = gen_label_rtx ();
@@ -583,7 +583,7 @@ sh_expand_strlen (rtx *operands)
rtx_code_label *L_return = gen_label_rtx ();
rtx_code_label *L_loop_byte = gen_label_rtx ();
- rtx jump;
+ rtx_insn *jump;
rtx_code_label *L_loop_long = gen_label_rtx ();
rtx_code_label *L_end_loop_long = gen_label_rtx ();
@@ -669,7 +669,7 @@ sh_expand_setmem (rtx *operands)
rtx_code_label *L_loop_byte = gen_label_rtx ();
rtx_code_label *L_loop_word = gen_label_rtx ();
rtx_code_label *L_return = gen_label_rtx ();
- rtx jump;
+ rtx_insn *jump;
rtx dest = copy_rtx (operands[0]);
rtx dest_addr = copy_addr_to_reg (XEXP (dest, 0));
rtx val = force_reg (SImode, operands[2]);
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index e80ef581b2d..c6956a056b4 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -3044,7 +3044,7 @@
"&& 1"
[(const_int 0)]
{
- rtx prev_set_t_insn = NULL_RTX;
+ rtx_insn *prev_set_t_insn = NULL;
if (!arith_reg_operand (operands[3], SImode))
{
@@ -3105,7 +3105,7 @@
&& ! reg_referenced_p (get_t_reg_rtx (),
PATTERN (prev_set_t_insn))))
{
- prev_set_t_insn = NULL_RTX;
+ prev_set_t_insn = NULL;
tmp_t_reg = gen_reg_rtx (SImode);
emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
}
@@ -3174,7 +3174,7 @@
if (INTVAL (operands[2]) > 1)
{
const rtx shift_count = GEN_INT (INTVAL (operands[2]) - 1);
- rtx prev_set_t_insn = NULL_RTX;
+ rtx_insn *prev_set_t_insn = NULL;
rtx tmp_t_reg = NULL_RTX;
/* If we're going to emit a shift sequence that clobbers the T_REG,
@@ -3205,7 +3205,7 @@
&& ! reg_referenced_p (get_t_reg_rtx (),
PATTERN (prev_set_t_insn))))
{
- prev_set_t_insn = NULL_RTX;
+ prev_set_t_insn = NULL;
tmp_t_reg = gen_reg_rtx (SImode);
emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
}
@@ -4518,7 +4518,7 @@
"TARGET_SH1 && ! TARGET_ZDCBRANCH"
[(const_int 0)]
{
- rtx skip_neg_label = gen_label_rtx ();
+ rtx_code_label *skip_neg_label = gen_label_rtx ();
emit_move_insn (operands[0], operands[1]);
@@ -4545,7 +4545,7 @@
"&& can_create_pseudo_p ()"
[(const_int 0)]
{
- rtx skip_neg_label = gen_label_rtx ();
+ rtx_code_label *skip_neg_label = gen_label_rtx ();
emit_move_insn (operands[0], operands[1]);
@@ -7456,7 +7456,7 @@
[(match_operand 0 "" "") (match_operand 1 "" "")]
""
{
- rtx gotoffsym, insn;
+ rtx gotoffsym;
rtx t = (!can_create_pseudo_p ()
? operands[0]
: gen_reg_rtx (GET_MODE (operands[0])));
@@ -7467,7 +7467,7 @@
gotoffsym = gen_sym2GOTOFF (operands[1]);
PUT_MODE (gotoffsym, Pmode);
emit_move_insn (t, gotoffsym);
- insn = emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, picreg));
+ rtx_insn *insn = emit_move_insn (operands[0], gen_rtx_PLUS (Pmode, t, picreg));
set_unique_reg_note (insn, REG_EQUAL, operands[1]);
@@ -8825,7 +8825,7 @@
"&& 1"
[(const_int 0)]
{
- rtx skip_label = gen_label_rtx ();
+ rtx_code_label *skip_label = gen_label_rtx ();
emit_move_insn (operands[0], operands[1]);
rtx cmp_val = operands[2];
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index c5638ccd2aa..2d1f598434b 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -648,6 +648,7 @@ static reg_class_t sparc_secondary_reload (bool, rtx, reg_class_t,
static machine_mode sparc_cstore_mode (enum insn_code icode);
static void sparc_atomic_assign_expand_fenv (tree *, tree *, tree *);
static bool sparc_fixed_condition_code_regs (unsigned int *, unsigned int *);
+static unsigned int sparc_min_arithmetic_precision (void);
#ifdef SUBTARGET_ATTRIBUTE_TABLE
/* Table of valid machine attributes. */
@@ -866,6 +867,9 @@ char sparc_hard_reg_printed[8];
#undef TARGET_FIXED_CONDITION_CODE_REGS
#define TARGET_FIXED_CONDITION_CODE_REGS sparc_fixed_condition_code_regs
+#undef TARGET_MIN_ARITHMETIC_PRECISION
+#define TARGET_MIN_ARITHMETIC_PRECISION sparc_min_arithmetic_precision
+
#undef TARGET_CUSTOM_FUNCTION_DESCRIPTORS
#define TARGET_CUSTOM_FUNCTION_DESCRIPTORS 1
@@ -2749,6 +2753,14 @@ sparc_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
return true;
}
+/* Implement TARGET_MIN_ARITHMETIC_PRECISION. */
+
+static unsigned int
+sparc_min_arithmetic_precision (void)
+{
+ return 32;
+}
+
/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
return the mode to be used for the comparison. For floating-point,
CCFP[E]mode is used. CCNZmode should be used when the first operand
diff --git a/gcc/config/sparc/sparc.md b/gcc/config/sparc/sparc.md
index 3fbc23cb6e7..b5793d3c053 100644
--- a/gcc/config/sparc/sparc.md
+++ b/gcc/config/sparc/sparc.md
@@ -8844,34 +8844,6 @@
[(set_attr "type" "fga")
(set_attr "fptype" "double")])
-(define_insn "vec_interleave_lowv8qi"
- [(set (match_operand:V8QI 0 "register_operand" "=e")
- (vec_select:V8QI
- (vec_concat:V16QI (match_operand:V8QI 1 "register_operand" "f")
- (match_operand:V8QI 2 "register_operand" "f"))
- (parallel [(const_int 0) (const_int 8)
- (const_int 1) (const_int 9)
- (const_int 2) (const_int 10)
- (const_int 3) (const_int 11)])))]
- "TARGET_VIS"
- "fpmerge\t%L1, %L2, %0"
- [(set_attr "type" "fga")
- (set_attr "fptype" "double")])
-
-(define_insn "vec_interleave_highv8qi"
- [(set (match_operand:V8QI 0 "register_operand" "=e")
- (vec_select:V8QI
- (vec_concat:V16QI (match_operand:V8QI 1 "register_operand" "f")
- (match_operand:V8QI 2 "register_operand" "f"))
- (parallel [(const_int 4) (const_int 12)
- (const_int 5) (const_int 13)
- (const_int 6) (const_int 14)
- (const_int 7) (const_int 15)])))]
- "TARGET_VIS"
- "fpmerge\t%H1, %H2, %0"
- [(set_attr "type" "fga")
- (set_attr "fptype" "double")])
-
;; Partitioned multiply instructions
(define_insn "fmul8x16_vis"
[(set (match_operand:V4HI 0 "register_operand" "=e")
diff --git a/gcc/config/spu/spu.h b/gcc/config/spu/spu.h
index c2c31e78900..7b6bad1500d 100644
--- a/gcc/config/spu/spu.h
+++ b/gcc/config/spu/spu.h
@@ -205,7 +205,8 @@ enum reg_class {
{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x3}, /* general regs */ \
{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0x3}} /* all regs */
-#define REGNO_REG_CLASS(REGNO) (GENERAL_REGS)
+#define REGNO_REG_CLASS(REGNO) ((void)(REGNO), GENERAL_REGS)
+
#define BASE_REG_CLASS GENERAL_REGS
diff --git a/gcc/config/vax/vax.h b/gcc/config/vax/vax.h
index 427c352bc22..dc77aa99223 100644
--- a/gcc/config/vax/vax.h
+++ b/gcc/config/vax/vax.h
@@ -226,7 +226,7 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
reg number REGNO. This could be a conditional expression
or could index an array. */
-#define REGNO_REG_CLASS(REGNO) ALL_REGS
+#define REGNO_REG_CLASS(REGNO) ((void)(REGNO), ALL_REGS)
/* The class value for index registers, and the one for base regs. */
diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h
index f2ca526aa17..873557f03f6 100644
--- a/gcc/config/xtensa/xtensa-protos.h
+++ b/gcc/config/xtensa/xtensa-protos.h
@@ -68,6 +68,7 @@ extern rtx xtensa_return_addr (int, rtx);
extern void xtensa_setup_frame_addresses (void);
extern int xtensa_dbx_register_number (int);
extern long compute_frame_size (int);
+extern bool xtensa_use_return_instruction_p (void);
extern void xtensa_expand_prologue (void);
extern void xtensa_expand_epilogue (void);
extern void order_regs_for_local_alloc (void);
diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c
index 60e50296d34..6e8a25d0307 100644
--- a/gcc/config/xtensa/xtensa.c
+++ b/gcc/config/xtensa/xtensa.c
@@ -79,11 +79,6 @@ enum internal_test
can support a given mode. */
char xtensa_hard_regno_mode_ok[(int) MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER];
-/* Current frame size calculated by compute_frame_size. */
-unsigned xtensa_current_frame_size;
-/* Callee-save area size in the current frame calculated by compute_frame_size. */
-int xtensa_callee_save_size;
-
/* Largest block move to handle in-line. */
#define LARGEST_MOVE_RATIO 15
@@ -95,6 +90,13 @@ struct GTY(()) machine_function
bool vararg_a7;
rtx vararg_a7_copy;
rtx_insn *set_frame_ptr_insn;
+ /* Current frame size calculated by compute_frame_size. */
+ unsigned current_frame_size;
+ /* Callee-save area size in the current frame calculated by
+ compute_frame_size. */
+ int callee_save_size;
+ bool frame_laid_out;
+ bool epilogue_done;
};
/* Vector, indexed by hard register number, which contains 1 for a
@@ -2533,13 +2535,32 @@ xtensa_output_addr_const_extra (FILE *fp, rtx x)
return false;
}
+static void
+xtensa_output_integer_literal_parts (FILE *file, rtx x, int size)
+{
+ if (size > 4 && !(size & (size - 1)))
+ {
+ rtx first, second;
+
+ split_double (x, &first, &second);
+ xtensa_output_integer_literal_parts (file, first, size / 2);
+ fputs (", ", file);
+ xtensa_output_integer_literal_parts (file, second, size / 2);
+ }
+ else if (size == 4)
+ {
+ output_addr_const (file, x);
+ }
+ else
+ {
+ gcc_unreachable();
+ }
+}
void
xtensa_output_literal (FILE *file, rtx x, machine_mode mode, int labelno)
{
long value_long[2];
- int size;
- rtx first, second;
fprintf (file, "\t.literal .LC%u, ", (unsigned) labelno);
@@ -2578,25 +2599,8 @@ xtensa_output_literal (FILE *file, rtx x, machine_mode mode, int labelno)
case MODE_INT:
case MODE_PARTIAL_INT:
- size = GET_MODE_SIZE (mode);
- switch (size)
- {
- case 4:
- output_addr_const (file, x);
- fputs ("\n", file);
- break;
-
- case 8:
- split_double (x, &first, &second);
- output_addr_const (file, first);
- fputs (", ", file);
- output_addr_const (file, second);
- fputs ("\n", file);
- break;
-
- default:
- gcc_unreachable ();
- }
+ xtensa_output_integer_literal_parts (file, x, GET_MODE_SIZE (mode));
+ fputs ("\n", file);
break;
default:
@@ -2632,24 +2636,29 @@ compute_frame_size (int size)
{
int regno;
+ if (reload_completed && cfun->machine->frame_laid_out)
+ return cfun->machine->current_frame_size;
+
/* Add space for the incoming static chain value. */
if (cfun->static_chain_decl != NULL)
size += (1 * UNITS_PER_WORD);
- xtensa_callee_save_size = 0;
+ cfun->machine->callee_save_size = 0;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
{
if (xtensa_call_save_reg(regno))
- xtensa_callee_save_size += UNITS_PER_WORD;
+ cfun->machine->callee_save_size += UNITS_PER_WORD;
}
- xtensa_current_frame_size =
+ cfun->machine->current_frame_size =
XTENSA_STACK_ALIGN (size
- + xtensa_callee_save_size
+ + cfun->machine->callee_save_size
+ crtl->outgoing_args_size
+ (WINDOW_SIZE * UNITS_PER_WORD));
- xtensa_callee_save_size = XTENSA_STACK_ALIGN (xtensa_callee_save_size);
- return xtensa_current_frame_size;
+ cfun->machine->callee_save_size =
+ XTENSA_STACK_ALIGN (cfun->machine->callee_save_size);
+ cfun->machine->frame_laid_out = true;
+ return cfun->machine->current_frame_size;
}
@@ -2703,6 +2712,7 @@ xtensa_expand_prologue (void)
{
int regno;
HOST_WIDE_INT offset = 0;
+ int callee_save_size = cfun->machine->callee_save_size;
/* -128 is a limit of single addi instruction. */
if (total_size > 0 && total_size <= 128)
@@ -2716,7 +2726,7 @@ xtensa_expand_prologue (void)
add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
offset = total_size - UNITS_PER_WORD;
}
- else if (xtensa_callee_save_size)
+ else if (callee_save_size)
{
/* 1020 is maximal s32i offset, if the frame is bigger than that
* we move sp to the end of callee-saved save area, save and then
@@ -2724,13 +2734,13 @@ xtensa_expand_prologue (void)
if (total_size > 1024)
{
insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-xtensa_callee_save_size)));
+ GEN_INT (-callee_save_size)));
RTX_FRAME_RELATED_P (insn) = 1;
note_rtx = gen_rtx_SET (stack_pointer_rtx,
plus_constant (Pmode, stack_pointer_rtx,
- -xtensa_callee_save_size));
+ -callee_save_size));
add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
- offset = xtensa_callee_save_size - UNITS_PER_WORD;
+ offset = callee_save_size - UNITS_PER_WORD;
}
else
{
@@ -2766,13 +2776,13 @@ xtensa_expand_prologue (void)
{
rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
emit_move_insn (tmp_reg, GEN_INT (total_size -
- xtensa_callee_save_size));
+ callee_save_size));
insn = emit_insn (gen_subsi3 (stack_pointer_rtx,
stack_pointer_rtx, tmp_reg));
RTX_FRAME_RELATED_P (insn) = 1;
note_rtx = gen_rtx_SET (stack_pointer_rtx,
plus_constant (Pmode, stack_pointer_rtx,
- xtensa_callee_save_size -
+ callee_save_size -
total_size));
add_reg_note (insn, REG_FRAME_RELATED_EXPR, note_rtx);
}
@@ -2840,21 +2850,21 @@ xtensa_expand_epilogue (void)
int regno;
HOST_WIDE_INT offset;
- if (xtensa_current_frame_size > (frame_pointer_needed ? 127 : 1024))
+ if (cfun->machine->current_frame_size > (frame_pointer_needed ? 127 : 1024))
{
rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
- emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size -
- xtensa_callee_save_size));
+ emit_move_insn (tmp_reg, GEN_INT (cfun->machine->current_frame_size -
+ cfun->machine->callee_save_size));
emit_insn (gen_addsi3 (stack_pointer_rtx, frame_pointer_needed ?
hard_frame_pointer_rtx : stack_pointer_rtx,
tmp_reg));
- offset = xtensa_callee_save_size - UNITS_PER_WORD;
+ offset = cfun->machine->callee_save_size - UNITS_PER_WORD;
}
else
{
if (frame_pointer_needed)
emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx);
- offset = xtensa_current_frame_size - UNITS_PER_WORD;
+ offset = cfun->machine->current_frame_size - UNITS_PER_WORD;
}
/* Prevent reordering of saved a0 update and loading it back from
@@ -2874,16 +2884,16 @@ xtensa_expand_epilogue (void)
}
}
- if (xtensa_current_frame_size > 0)
+ if (cfun->machine->current_frame_size > 0)
{
if (frame_pointer_needed || /* always reachable with addi */
- xtensa_current_frame_size > 1024 ||
- xtensa_current_frame_size <= 127)
+ cfun->machine->current_frame_size > 1024 ||
+ cfun->machine->current_frame_size <= 127)
{
- if (xtensa_current_frame_size <= 127)
- offset = xtensa_current_frame_size;
+ if (cfun->machine->current_frame_size <= 127)
+ offset = cfun->machine->current_frame_size;
else
- offset = xtensa_callee_save_size;
+ offset = cfun->machine->callee_save_size;
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
@@ -2892,7 +2902,8 @@ xtensa_expand_epilogue (void)
else
{
rtx tmp_reg = gen_rtx_REG (Pmode, A9_REG);
- emit_move_insn (tmp_reg, GEN_INT (xtensa_current_frame_size));
+ emit_move_insn (tmp_reg,
+ GEN_INT (cfun->machine->current_frame_size));
emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
tmp_reg));
}
@@ -2903,11 +2914,22 @@ xtensa_expand_epilogue (void)
stack_pointer_rtx,
EH_RETURN_STACKADJ_RTX));
}
- xtensa_current_frame_size = 0;
- xtensa_callee_save_size = 0;
+ cfun->machine->epilogue_done = true;
emit_jump_insn (gen_return ());
}
+bool
+xtensa_use_return_instruction_p (void)
+{
+ if (!reload_completed)
+ return false;
+ if (TARGET_WINDOWED_ABI)
+ return true;
+ if (compute_frame_size (get_frame_size ()) == 0)
+ return true;
+ return cfun->machine->epilogue_done;
+}
+
void
xtensa_set_return_address (rtx address, rtx scratch)
{
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index 82e9900b42a..58eb1b2604a 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -23,8 +23,6 @@ along with GCC; see the file COPYING3. If not see
/* External variables defined in xtensa.c. */
-extern unsigned xtensa_current_frame_size;
-
/* Macros used in the machine description to select various Xtensa
configuration options. */
#ifndef XCHAL_HAVE_MUL32_HIGH
@@ -477,14 +475,14 @@ enum reg_class
/* Specify the initial difference between the specified pair of registers. */
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
do { \
- compute_frame_size (get_frame_size ()); \
+ long frame_size = compute_frame_size (get_frame_size ()); \
switch (FROM) \
{ \
case FRAME_POINTER_REGNUM: \
(OFFSET) = 0; \
break; \
case ARG_POINTER_REGNUM: \
- (OFFSET) = xtensa_current_frame_size; \
+ (OFFSET) = frame_size; \
break; \
default: \
gcc_unreachable (); \
diff --git a/gcc/config/xtensa/xtensa.md b/gcc/config/xtensa/xtensa.md
index db54a12b7bc..fcdb6c8ecad 100644
--- a/gcc/config/xtensa/xtensa.md
+++ b/gcc/config/xtensa/xtensa.md
@@ -1663,7 +1663,7 @@
(define_insn "return"
[(return)
(use (reg:SI A0_REG))]
- "(TARGET_WINDOWED_ABI || !xtensa_current_frame_size) && reload_completed"
+ "xtensa_use_return_instruction_p ()"
{
return TARGET_WINDOWED_ABI ?
(TARGET_DENSITY ? "retw.n" : "retw") :
diff --git a/gcc/configure b/gcc/configure
index 80fc5c71a0e..0f04033bc1d 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -22662,6 +22662,15 @@ fi
# ld, we don't know its patchlevel version, so we set the baseline at 2.13
# to be safe.
# The gcc_GAS_CHECK_FEATURE call just sets a cache variable.
+case "${target}" in
+ *-*-aix*)
+ conftest_s=' .globl foobar,hidden'
+ ;;
+ *)
+ conftest_s=' .hidden foobar
+foobar:'
+ ;;
+esac
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .hidden" >&5
$as_echo_n "checking assembler for .hidden... " >&6; }
if test "${gcc_cv_as_hidden+set}" = set; then :
@@ -22674,8 +22683,7 @@ else
then gcc_cv_as_hidden=yes
fi
elif test x$gcc_cv_as != x; then
- $as_echo ' .hidden foobar
-foobar:' > conftest.s
+ $as_echo "$conftest_s" > conftest.s
if { ac_try='$gcc_cv_as $gcc_cv_as_flags -o conftest.o conftest.s >&5'
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
(eval $ac_try) 2>&5
@@ -22809,6 +22817,9 @@ else
fi
else
case "${target}" in
+ *-*-aix[789]*)
+ gcc_cv_ld_hidden=yes
+ ;;
*-*-darwin*)
# Darwin ld has some visibility support.
gcc_cv_ld_hidden=yes
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 338956f644a..2f9b859eafb 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -2537,10 +2537,17 @@ gcc_GAS_CHECK_FEATURE([.nsubspa comdat], gcc_cv_as_nsubspa_comdat,
# ld, we don't know its patchlevel version, so we set the baseline at 2.13
# to be safe.
# The gcc_GAS_CHECK_FEATURE call just sets a cache variable.
+case "${target}" in
+ *-*-aix*)
+ conftest_s=' .globl foobar,hidden'
+ ;;
+ *)
+ conftest_s=' .hidden foobar
+foobar:'
+ ;;
+esac
gcc_GAS_CHECK_FEATURE([.hidden], gcc_cv_as_hidden,
- [elf,2,13,0],,
-[ .hidden foobar
-foobar:])
+ [elf,2,13,0],, [$conftest_s])
case "${target}" in
*-*-darwin*)
# Darwin as has some visibility support, though with a different syntax.
@@ -2649,6 +2656,9 @@ else
fi
else
case "${target}" in
+ *-*-aix[789]*)
+ gcc_cv_ld_hidden=yes
+ ;;
*-*-darwin*)
# Darwin ld has some visibility support.
gcc_cv_ld_hidden=yes
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index efce361f880..f325ccc8932 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,172 @@
+2016-11-07 Jason Merrill <jason@redhat.com>
+
+ Implement P0012R1, Make exception specifications part of the type
+ system.
+ * cp-tree.h (enum tsubst_flags): Add tf_fndecl_type.
+ (flag_noexcept_type, ce_type): New.
+ * call.c (build_conv): Add ck_fnptr.
+ (enum conversion_kind): Change ck_tsafe to ck_fnptr.
+ (convert_like_real): Likewise.
+ (standard_conversion): Likewise. Allow function pointer
+ conversions for pointers to member functions.
+ (reference_compatible_p): Allow function pointer conversions.
+ (direct_reference_binding): Likewise.
+ (reference_binding): Reference-compatible is no longer a subset of
+ reference-related.
+ (is_subseq): Also strip ck_lvalue after next_conversion.
+ * class.c (instantiate_type): Check fnptr_conv_p.
+ (resolve_address_of_overloaded_function): Likewise.
+ * cvt.c (can_convert_tx_safety): Now static.
+ (noexcept_conv_p, fnptr_conv_p, strip_fnptr_conv): New.
+ * decl.c (flag_noexcept_type): Define.
+ (cxx_init_decl_processing): Set it.
+ (bad_specifiers): Check it.
+ (grokdeclarator) [cdk_function]: Add exception-spec to type here.
+ * lambda.c (maybe_add_lambda_conv_op): Add exception-spec to
+ returned pointer.
+ * mangle.c (struct globals): Add need_cxx1z_warning.
+ (mangle_decl): Check it.
+ (write_exception_spec): New.
+ (write_function_type): Call it.
+ (canonicalize_for_substitution): Handle exception spec.
+ (write_type): Likewise.
+ (write_encoding): Set processing_template_decl across mangling of
+ partially-instantiated type.
+ * pt.c (determine_specialization): Pass tf_fndecl_type.
+ (tsubst_decl, fn_type_unification): Likewise.
+ (tsubst): Strip tf_fndecl_type, pass it to
+ tsubst_exception_specification.
+ (convert_nontype_argument_function): Handle function pointer
+ conversion.
+ (convert_nontype_argument): Likewise.
+ (unify, for_each_template_parm_r): Walk into noexcept-specifier.
+ * rtti.c (ptr_initializer): Encode noexcept.
+ * tree.c (canonical_eh_spec): New.
+ (build_exception_variant): Use it.
+ * typeck.c (composite_pointer_type): Handle fnptr conversion.
+ (comp_except_specs): Compare canonical EH specs.
+ (structural_comptypes): Call it.
+
+ * call.c (standard_conversion): Reorganize pointer conversions.
+ * pt.c (convert_nontype_argument_function): Convert to ref here.
+ (convert_nontype_argument): Not here.
+ (convert_template_argument): Add original type to error message.
+ (RECUR_AND_CHECK_FAILURE): Remove trailing semicolon.
+ (unify): Compare function-qualifiers.
+ * typeck.c (same_type_ignoring_top_level_qualifiers_p): Use
+ cp_build_qualified_type rather than TYPE_MAIN_VARIANT.
+
+ * pt.c (push_tinst_level_loc): Add template instantiations to the
+ announce_function stream.
+
+2016-11-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/67980
+ * pt.c (tsubst_expr, case IF_STMT): Use fold_non_dependent_expr
+ to suppress unwanted warnings.
+
+2016-11-03 Jason Merrill <jason@redhat.com>
+
+ PR c++/78198
+ * call.c (convert_default_arg): Look through inheriting ctors.
+
+2016-11-03 Jakub Jelinek <jakub@redhat.com>
+ Alexandre Oliva <aoliva@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR debug/28767
+ PR debug/56974
+ * tree.c (cp_check_qualified_type): Use check_base_type and
+ TYPE_QUALS comparison instead of check_qualified_type.
+ (cxx_type_hash_eq): Return false if type_memfn_rqual don't match.
+ * cp-objcp-common.c (cp_get_debug_type): New function.
+ (cp_decl_dwarf_attribute): Don't handle types here.
+ (cp_type_dwarf_attribute): New function.
+ * cp-objcp-common.h (cp_get_debug_type, cp_type_dwarf_attribute):
+ Declare.
+ (LANG_HOOKS_GET_DEBUG_TYPE, LANG_HOOKS_TYPE_DWARF_ATTRIBUTE):
+ Define.
+
+2016-11-03 Jason Merrill <jason@redhat.com>
+
+ * tree.c (cp_check_qualified_type): Call check_base_type instead
+ of check_qualified_type.
+ (cxx_type_hash_eq): Check ref-qualifiers.
+ * typeck.c (apply_memfn_quals): No need to mess with TYPE_CANONICAL.
+
+2016-11-01 Jason Merrill <jason@redhat.com>
+
+ Implement P0136R1, Rewording inheriting constructors.
+ * call.c (enum rejection_reason_code): Add rr_inherited_ctor.
+ (inherited_ctor_rejection): New.
+ (add_function_candidate): Reject inherited ctors for copying.
+ (enforce_access): Use strip_inheriting_ctors.
+ (print_z_candidate): Likewise. Handle rr_inherited_ctor.
+ (convert_like_real): Avoid copying inheriting ctor parameters.
+ (build_over_call): Likewise. A base ctor inheriting from vbase
+ has no parms. Sorry about varargs.
+ (joust): A local constructor beats inherited with the same convs.
+ * class.c (add_method): Handle hiding inheriting ctors.
+ (one_inherited_ctor): Handle new semantics.
+ (add_implicitly_declared_members): Pass using_decl down.
+ (build_clone): A base ctor inheriting from vbase has no parms.
+ * cp-tree.h (DECL_INHERITED_CTOR): Store this instead of the base.
+ (SET_DECL_INHERITED_CTOR): Likewise.
+ (DECL_INHERITED_CTOR_BASE): Adjust.
+ * constexpr.c: Adjust.
+ * error.c (dump_function_decl): Decorate inheriting ctors.
+ * init.c (emit_mem_initializers): Suppress access control in
+ inheriting ctor.
+ * mangle.c (write_special_name_constructor): Handle new inheriting
+ ctor mangling.
+ * method.c (strip_inheriting_ctors, inherited_ctor_binfo)
+ (ctor_omit_inherited_parms, binfo_inherited_from): New.
+ (synthesized_method_walk): Use binfo_inherited_from. Suppress
+ access control in inheriting ctor.
+ (deduce_inheriting_ctor): Deleted if ambiguous ctor inheritance.
+ (maybe_explain_implicit_delete): Explain ambigous ctor inheritance.
+ (add_one_base_init, do_build_copy_constructor): Adjust.
+ (locate_fn_flags, explain_implicit_non_constexpr): Adjust.
+ (implicitly_declare_fn): Adjust.
+ (get_inherited_ctor): Remove.
+ * name-lookup.c (do_class_using_decl): Check for indirect ctor
+ inheritance.
+ * optimize.c (cdtor_comdat_group): Adjust for new mangling.
+ (maybe_clone_body): Handle omitted parms in base clone.
+ (maybe_thunk_body): Don't thunk if base clone omits parms.
+ * pt.c (tsubst_decl): Adjust.
+ (instantiate_template_1): Suppress access control in inheriting
+ ctor.
+ (fn_type_unification): Do deduction with inherited ctor.
+ * tree.c (special_function_p): Adjust.
+
+2016-11-01 Jakub Jelinek <jakub@redhat.com>
+
+ * cp-objcp-common.c (cp_decl_dwarf_attribute): Handle DW_AT_inline.
+
+2016-11-01 Jason Merrill <jason@redhat.com>
+
+ * class.c (declared_access): Split out from handle_using_decl.
+
+2016-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/78089
+ * parser.c (cp_parser_postfix_expression): Replace return statement in
+ the first switch with setting postfix_expression to the return
+ expression and break;.
+
+ PR c++/77886
+ * pt.c (tsubst_expr) <case CASE_LABEL_EXPR> Copy over
+ FALLTHROUGH_LABEL_P flag to the new LABEL_DECL.
+ (tsubst_expr) <case LABEL_EXPR>: Likewise.
+
+2016-09-11 Le-Chun Wu <lcwu@google.com>
+ Mark Wielaard <mjw@redhat.com>
+
+ * name-lookup.c (pushdecl_maybe_friend): When emitting a
+ shadowing warning, use the code corresponding to the
+ given -Wshadow= variant.
+
2016-10-26 Jason Merrill <jason@redhat.com>
* class.c (add_method): Allow using-declarations to coexist.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 4c19d2ffcd3..0dcf322344c 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -45,7 +45,7 @@ along with GCC; see the file COPYING3. If not see
enum conversion_kind {
ck_identity,
ck_lvalue,
- ck_tsafe,
+ ck_fnptr,
ck_qual,
ck_std,
ck_ptr,
@@ -414,6 +414,7 @@ enum rejection_reason_code {
rr_bad_arg_conversion,
rr_template_unification,
rr_invalid_copy,
+ rr_inherited_ctor,
rr_constraint_failure
};
@@ -689,6 +690,13 @@ invalid_copy_with_fn_template_rejection (void)
return r;
}
+static struct rejection_reason *
+inherited_ctor_rejection (void)
+{
+ struct rejection_reason *r = alloc_rejection (rr_inherited_ctor);
+ return r;
+}
+
// Build a constraint failure record, saving information into the
// template_instantiation field of the rejection. If FN is not a template
// declaration, the TMPL member is the FN declaration and TARGS is empty.
@@ -763,6 +771,7 @@ build_conv (conversion_kind code, tree type, conversion *from)
break;
case ck_qual:
+ case ck_fnptr:
if (rank < cr_exact)
rank = cr_exact;
break;
@@ -1204,19 +1213,40 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
tree to_pointee;
tree from_pointee;
+ if (tcode == POINTER_TYPE)
+ {
+ to_pointee = TREE_TYPE (to);
+ from_pointee = TREE_TYPE (from);
+
+ /* Since this is the target of a pointer, it can't have function
+ qualifiers, so any TYPE_QUALS must be for attributes const or
+ noreturn. Strip them. */
+ if (TREE_CODE (to_pointee) == FUNCTION_TYPE
+ && TYPE_QUALS (to_pointee))
+ to_pointee = build_qualified_type (to_pointee, TYPE_UNQUALIFIED);
+ if (TREE_CODE (from_pointee) == FUNCTION_TYPE
+ && TYPE_QUALS (from_pointee))
+ from_pointee = build_qualified_type (from_pointee, TYPE_UNQUALIFIED);
+ }
+ else
+ {
+ to_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (to);
+ from_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (from);
+ }
+
if (tcode == POINTER_TYPE
- && same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (from),
- TREE_TYPE (to)))
+ && same_type_ignoring_top_level_qualifiers_p (from_pointee,
+ to_pointee))
;
- else if (VOID_TYPE_P (TREE_TYPE (to))
+ else if (VOID_TYPE_P (to_pointee)
&& !TYPE_PTRDATAMEM_P (from)
- && TREE_CODE (TREE_TYPE (from)) != FUNCTION_TYPE)
+ && TREE_CODE (from_pointee) != FUNCTION_TYPE)
{
tree nfrom = TREE_TYPE (from);
/* Don't try to apply restrict to void. */
int quals = cp_type_quals (nfrom) & ~TYPE_QUAL_RESTRICT;
- from = build_pointer_type
- (cp_build_qualified_type (void_type_node, quals));
+ from_pointee = cp_build_qualified_type (void_type_node, quals);
+ from = build_pointer_type (from_pointee);
conv = build_conv (ck_ptr, from, conv);
}
else if (TYPE_PTRDATAMEM_P (from))
@@ -1226,18 +1256,16 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
if (DERIVED_FROM_P (fbase, tbase)
&& (same_type_ignoring_top_level_qualifiers_p
- (TYPE_PTRMEM_POINTED_TO_TYPE (from),
- TYPE_PTRMEM_POINTED_TO_TYPE (to))))
+ (from_pointee, to_pointee)))
{
- from = build_ptrmem_type (tbase,
- TYPE_PTRMEM_POINTED_TO_TYPE (from));
+ from = build_ptrmem_type (tbase, from_pointee);
conv = build_conv (ck_pmem, from, conv);
}
else if (!same_type_p (fbase, tbase))
return NULL;
}
- else if (CLASS_TYPE_P (TREE_TYPE (from))
- && CLASS_TYPE_P (TREE_TYPE (to))
+ else if (CLASS_TYPE_P (from_pointee)
+ && CLASS_TYPE_P (to_pointee)
/* [conv.ptr]
An rvalue of type "pointer to cv D," where D is a
@@ -1249,37 +1277,15 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
that necessitates this conversion is ill-formed.
Therefore, we use DERIVED_FROM_P, and do not check
access or uniqueness. */
- && DERIVED_FROM_P (TREE_TYPE (to), TREE_TYPE (from)))
+ && DERIVED_FROM_P (to_pointee, from_pointee))
{
- from =
- cp_build_qualified_type (TREE_TYPE (to),
- cp_type_quals (TREE_TYPE (from)));
- from = build_pointer_type (from);
+ from_pointee
+ = cp_build_qualified_type (to_pointee,
+ cp_type_quals (from_pointee));
+ from = build_pointer_type (from_pointee);
conv = build_conv (ck_ptr, from, conv);
conv->base_p = true;
}
- else if (tx_safe_fn_type_p (TREE_TYPE (from)))
- {
- /* A prvalue of type "pointer to transaction_safe function" can be
- converted to a prvalue of type "pointer to function". */
- tree unsafe = tx_unsafe_fn_variant (TREE_TYPE (from));
- if (same_type_p (unsafe, TREE_TYPE (to)))
- {
- from = build_pointer_type (unsafe);
- conv = build_conv (ck_tsafe, from, conv);
- }
- }
-
- if (tcode == POINTER_TYPE)
- {
- to_pointee = TREE_TYPE (to);
- from_pointee = TREE_TYPE (from);
- }
- else
- {
- to_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (to);
- from_pointee = TYPE_PTRMEM_POINTED_TO_TYPE (from);
- }
if (same_type_p (from, to))
/* OK */;
@@ -1293,6 +1299,8 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
else if (expr && string_conv_p (to, expr, 0))
/* converting from string constant to char *. */
conv = build_conv (ck_qual, to, conv);
+ else if (fnptr_conv_p (to, from))
+ conv = build_conv (ck_fnptr, to, conv);
/* Allow conversions among compatible ObjC pointer types (base
conversions have been already handled above). */
else if (c_dialect_objc ()
@@ -1315,18 +1323,29 @@ standard_conversion (tree to, tree from, tree expr, bool c_cast_p,
tree fbase = class_of_this_parm (fromfn);
tree tbase = class_of_this_parm (tofn);
- if (!DERIVED_FROM_P (fbase, tbase)
- || !same_type_p (static_fn_type (fromfn),
- static_fn_type (tofn)))
+ if (!DERIVED_FROM_P (fbase, tbase))
return NULL;
- from = build_memfn_type (fromfn,
- tbase,
- cp_type_quals (tbase),
- type_memfn_rqual (tofn));
- from = build_ptrmemfunc_type (build_pointer_type (from));
- conv = build_conv (ck_pmem, from, conv);
- conv->base_p = true;
+ tree fstat = static_fn_type (fromfn);
+ tree tstat = static_fn_type (tofn);
+ if (same_type_p (tstat, fstat)
+ || fnptr_conv_p (tstat, fstat))
+ /* OK */;
+ else
+ return NULL;
+
+ if (!same_type_p (fbase, tbase))
+ {
+ from = build_memfn_type (fstat,
+ tbase,
+ cp_type_quals (tbase),
+ type_memfn_rqual (tofn));
+ from = build_ptrmemfunc_type (build_pointer_type (from));
+ conv = build_conv (ck_pmem, from, conv);
+ conv->base_p = true;
+ }
+ if (fnptr_conv_p (tstat, fstat))
+ conv = build_conv (ck_fnptr, to, conv);
}
else if (tcode == BOOLEAN_TYPE)
{
@@ -1424,10 +1443,14 @@ reference_compatible_p (tree t1, tree t2)
{
/* [dcl.init.ref]
- "cv1 T1" is reference compatible with "cv2 T2" if T1 is
- reference-related to T2 and cv1 is the same cv-qualification as,
- or greater cv-qualification than, cv2. */
- return (reference_related_p (t1, t2)
+ "cv1 T1" is reference compatible with "cv2 T2" if
+ * T1 is reference-related to T2 or
+ * T2 is "noexcept function" and T1 is "function", where the
+ function types are otherwise the same,
+ and cv1 is the same cv-qualification as, or greater cv-qualification
+ than, cv2. */
+ return ((reference_related_p (t1, t2)
+ || fnptr_conv_p (t1, t2))
&& at_least_as_qualified_p (t1, t2));
}
@@ -1461,7 +1484,7 @@ direct_reference_binding (tree type, conversion *conv)
either an identity conversion or, if the conversion function
returns an entity of a type that is a derived class of the
parameter type, a derived-to-base conversion. */
- if (!same_type_ignoring_top_level_qualifiers_p (t, conv->type))
+ if (is_properly_derived_from (conv->type, t))
{
/* Represent the derived-to-base conversion. */
conv = build_conv (ck_base, t, conv);
@@ -1574,7 +1597,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags,
[8.5.3/5 dcl.init.ref] is changed to also require direct bindings for
const and rvalue references to rvalues of compatible class type.
We should also do direct bindings for non-class xvalues. */
- if (related_p && gl_kind)
+ if ((related_p || compatible_p) && gl_kind)
{
/* [dcl.init.ref]
@@ -2111,6 +2134,18 @@ add_function_candidate (struct z_candidate **candidates,
}
}
+ /* Don't consider inherited constructors for initialization from an
+ expression of the same or derived type. */
+ /* FIXME extend to operator=. */
+ if (i == 0 && len == 1
+ && DECL_INHERITED_CTOR (fn)
+ && reference_related_p (ctype, argtype))
+ {
+ viable = 0;
+ reason = inherited_ctor_rejection ();
+ goto out;
+ }
+
/* Core issue 899: When [copy-]initializing a temporary to be bound
to the first parameter of a copy constructor (12.8) called with
a single argument in the context of direct-initialization,
@@ -3393,32 +3428,40 @@ print_z_candidate (location_t loc, const char *msgstr,
const char *msg = (msgstr == NULL
? ""
: ACONCAT ((msgstr, " ", NULL)));
- location_t cloc = location_of (candidate->fn);
+ tree fn = candidate->fn;
+ if (flag_new_inheriting_ctors)
+ fn = strip_inheriting_ctors (fn);
+ location_t cloc = location_of (fn);
- if (identifier_p (candidate->fn))
+ if (identifier_p (fn))
{
cloc = loc;
if (candidate->num_convs == 3)
- inform (cloc, "%s%D(%T, %T, %T) <built-in>", msg, candidate->fn,
+ inform (cloc, "%s%D(%T, %T, %T) <built-in>", msg, fn,
candidate->convs[0]->type,
candidate->convs[1]->type,
candidate->convs[2]->type);
else if (candidate->num_convs == 2)
- inform (cloc, "%s%D(%T, %T) <built-in>", msg, candidate->fn,
+ inform (cloc, "%s%D(%T, %T) <built-in>", msg, fn,
candidate->convs[0]->type,
candidate->convs[1]->type);
else
- inform (cloc, "%s%D(%T) <built-in>", msg, candidate->fn,
+ inform (cloc, "%s%D(%T) <built-in>", msg, fn,
candidate->convs[0]->type);
}
- else if (TYPE_P (candidate->fn))
- inform (cloc, "%s%T <conversion>", msg, candidate->fn);
+ else if (TYPE_P (fn))
+ inform (cloc, "%s%T <conversion>", msg, fn);
else if (candidate->viable == -1)
- inform (cloc, "%s%#D <near match>", msg, candidate->fn);
- else if (DECL_DELETED_FN (candidate->fn))
- inform (cloc, "%s%#D <deleted>", msg, candidate->fn);
+ inform (cloc, "%s%#D <near match>", msg, fn);
+ else if (DECL_DELETED_FN (fn))
+ inform (cloc, "%s%#D <deleted>", msg, fn);
else
- inform (cloc, "%s%#D", msg, candidate->fn);
+ inform (cloc, "%s%#D", msg, fn);
+ if (fn != candidate->fn)
+ {
+ cloc = location_of (candidate->fn);
+ inform (cloc, " inherited here");
+ }
/* Give the user some information about why this candidate failed. */
if (candidate->reason != NULL)
{
@@ -3483,6 +3526,11 @@ print_z_candidate (location_t loc, const char *msgstr,
diagnose_constraints (cloc, tmpl, args);
}
break;
+ case rr_inherited_ctor:
+ inform (cloc, " an inherited constructor is not a candidate for "
+ "initialization from an expression of the same or derived "
+ "type");
+ break;
case rr_none:
default:
/* This candidate didn't have any issues or we failed to
@@ -6338,10 +6386,22 @@ enforce_access (tree basetype_path, tree decl, tree diag_decl,
{
gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO);
+ if (flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (decl))
+ {
+ /* 7.3.3/18: The additional constructors are accessible if they would be
+ accessible when used to construct an object of the corresponding base
+ class. */
+ decl = strip_inheriting_ctors (decl);
+ basetype_path = TYPE_BINFO (DECL_CONTEXT (decl));
+ }
+
if (!accessible_p (basetype_path, decl, true))
{
if (complain & tf_error)
{
+ if (flag_new_inheriting_ctors)
+ diag_decl = strip_inheriting_ctors (diag_decl);
if (TREE_PRIVATE (decl))
{
error ("%q#D is private within this context", diag_decl);
@@ -6773,6 +6833,15 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (! MAYBE_CLASS_TYPE_P (totype))
return expr;
+
+ /* Don't introduce copies when passing arguments along to the inherited
+ constructor. */
+ if (current_function_decl
+ && flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (current_function_decl)
+ && TREE_ADDRESSABLE (totype))
+ return expr;
+
/* Fall through. */
case ck_base:
if (convs->kind == ck_base && !convs->need_temporary_p)
@@ -6915,9 +6984,9 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
case ck_lvalue:
return decay_conversion (expr, complain);
- case ck_tsafe:
+ case ck_fnptr:
/* ??? Should the address of a transaction-safe pointer point to the TM
- clone, and this conversion look up the primary function? */
+ clone, and this conversion look up the primary function? */
return build_nop (totype, expr);
case ck_qual:
@@ -7139,6 +7208,9 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum,
/* See through clones. */
fn = DECL_ORIGIN (fn);
+ /* And inheriting ctors. */
+ if (flag_new_inheriting_ctors)
+ fn = strip_inheriting_ctors (fn);
/* Detect recursion. */
FOR_EACH_VEC_SAFE_ELT (default_arg_context, i, t)
@@ -7800,6 +7872,29 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
check_function_arguments (input_location, TREE_TYPE (fn), nargs, fargs);
}
+ if (DECL_INHERITED_CTOR (fn))
+ {
+ /* Check for passing ellipsis arguments to an inherited constructor. We
+ could handle this by open-coding the inherited constructor rather than
+ defining it, but let's not bother now. */
+ if (!cp_unevaluated_operand
+ && cand->convs[cand->num_convs-1]->ellipsis_p)
+ {
+ if (complain & tf_error)
+ {
+ sorry ("passing arguments to ellipsis of inherited constructor "
+ "%qD", cand->fn);
+ inform (DECL_SOURCE_LOCATION (cand->fn), "declared here");
+ }
+ return error_mark_node;
+ }
+
+ /* A base constructor inheriting from a virtual base doesn't get the
+ inherited arguments, just this and __vtt. */
+ if (ctor_omit_inherited_parms (fn))
+ nargs = 2;
+ }
+
/* Avoid actually calling copy constructors and copy assignment operators,
if possible. */
@@ -7985,13 +8080,21 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
}
tree call = build_cxx_call (fn, nargs, argarray, complain|decltype_flag);
- if (call != error_mark_node
- && cand->flags & LOOKUP_LIST_INIT_CTOR)
+ if (call == error_mark_node)
+ return call;
+ if (cand->flags & LOOKUP_LIST_INIT_CTOR)
{
tree c = extract_call_expr (call);
/* build_new_op_1 will clear this when appropriate. */
CALL_EXPR_ORDERED_ARGS (c) = true;
}
+ if (current_function_decl
+ && flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (current_function_decl)
+ && cand->num_convs)
+ /* Don't introduce copies when passing arguments along to the inherited
+ constructor. */
+ CALL_FROM_THUNK_P (call) = true;
return call;
}
@@ -8766,10 +8869,15 @@ is_subseq (conversion *ics1, conversion *ics2)
ics2 = next_conversion (ics2);
+ while (ics2->kind == ck_rvalue
+ || ics2->kind == ck_lvalue)
+ ics2 = next_conversion (ics2);
+
if (ics2->kind == ics1->kind
&& same_type_p (ics2->type, ics1->type)
- && same_type_p (next_conversion (ics2)->type,
- next_conversion (ics1)->type))
+ && (ics1->kind == ck_identity
+ || same_type_p (next_conversion (ics2)->type,
+ next_conversion (ics1)->type)))
return true;
}
}
@@ -9539,6 +9647,34 @@ joust (struct z_candidate *cand1, struct z_candidate *cand2, bool warn,
return winner;
}
+ /* or, if not that, F2 is from a using-declaration, F1 is not, and the
+ conversion sequences are equivalent.
+ (proposed in http://lists.isocpp.org/core/2016/10/1142.php) */
+ if (DECL_P (cand1->fn) && DECL_CLASS_SCOPE_P (cand1->fn)
+ && !DECL_CONV_FN_P (cand1->fn)
+ && DECL_P (cand2->fn) && DECL_CLASS_SCOPE_P (cand2->fn)
+ && !DECL_CONV_FN_P (cand2->fn))
+ {
+ bool used1 = (DECL_INHERITED_CTOR (cand1->fn)
+ || (BINFO_TYPE (cand1->access_path)
+ != DECL_CONTEXT (cand1->fn)));
+ bool used2 = (DECL_INHERITED_CTOR (cand2->fn)
+ || (BINFO_TYPE (cand2->access_path)
+ != DECL_CONTEXT (cand2->fn)));
+ if (int diff = used2 - used1)
+ {
+ for (i = 0; i < len; ++i)
+ {
+ conversion *t1 = cand1->convs[i + off1];
+ conversion *t2 = cand2->convs[i + off2];
+ if (!same_type_p (t1->type, t2->type))
+ break;
+ }
+ if (i == len)
+ return diff;
+ }
+ }
+
/* Check whether we can discard a builtin candidate, either because we
have two identical ones or matching builtin and non-builtin candidates.
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index a2a93469151..5460ae5d626 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1016,7 +1016,6 @@ add_method (tree type, tree method, tree using_decl)
bool complete_p;
bool insert_p = false;
tree current_fns;
- tree fns;
if (method == error_mark_node)
return false;
@@ -1083,8 +1082,9 @@ add_method (tree type, tree method, tree using_decl)
current_fns = insert_p ? NULL_TREE : (*method_vec)[slot];
/* Check to see if we've already got this method. */
- for (fns = current_fns; fns; fns = OVL_NEXT (fns))
+ for (tree *p = &current_fns; *p; )
{
+ tree fns = *p;
tree fn = OVL_CURRENT (fns);
tree fn_type;
tree method_type;
@@ -1092,12 +1092,14 @@ add_method (tree type, tree method, tree using_decl)
tree parms2;
if (TREE_CODE (fn) != TREE_CODE (method))
- continue;
+ goto cont;
/* Two using-declarations can coexist, we'll complain about ambiguity in
overload resolution. */
- if (using_decl && TREE_CODE (fns) == OVERLOAD && OVL_USED (fns))
- continue;
+ if (using_decl && TREE_CODE (fns) == OVERLOAD && OVL_USED (fns)
+ /* Except handle inherited constructors specially. */
+ && ! DECL_CONSTRUCTOR_P (fn))
+ goto cont;
/* [over.load] Member function declarations with the
same name and the same parameter types cannot be
@@ -1131,7 +1133,7 @@ add_method (tree type, tree method, tree using_decl)
== FUNCTION_REF_QUALIFIED (method_type))
&& (type_memfn_quals (fn_type) != type_memfn_quals (method_type)
|| type_memfn_rqual (fn_type) != type_memfn_rqual (method_type)))
- continue;
+ goto cont;
/* For templates, the return type and template parameters
must be identical. */
@@ -1140,7 +1142,7 @@ add_method (tree type, tree method, tree using_decl)
TREE_TYPE (method_type))
|| !comp_template_parms (DECL_TEMPLATE_PARMS (fn),
DECL_TEMPLATE_PARMS (method))))
- continue;
+ goto cont;
if (! DECL_STATIC_FUNCTION_P (fn))
parms1 = TREE_CHAIN (parms1);
@@ -1178,18 +1180,38 @@ add_method (tree type, tree method, tree using_decl)
mangle_decl (method);
}
cgraph_node::record_function_versions (fn, method);
- continue;
+ goto cont;
}
- if (DECL_INHERITED_CTOR_BASE (method))
+ if (DECL_INHERITED_CTOR (method))
{
- if (DECL_INHERITED_CTOR_BASE (fn))
+ if (DECL_INHERITED_CTOR (fn))
{
+ tree basem = DECL_INHERITED_CTOR_BASE (method);
+ tree basef = DECL_INHERITED_CTOR_BASE (fn);
+ if (flag_new_inheriting_ctors)
+ {
+ if (basem == basef)
+ {
+ /* Inheriting the same constructor along different
+ paths, combine them. */
+ SET_DECL_INHERITED_CTOR
+ (fn, ovl_cons (DECL_INHERITED_CTOR (method),
+ DECL_INHERITED_CTOR (fn)));
+ /* Adjust deletedness and such. */
+ deduce_inheriting_ctor (fn);
+ /* And discard the new one. */
+ return false;
+ }
+ else
+ /* Inherited ctors can coexist until overload
+ resolution. */
+ goto cont;
+ }
error_at (DECL_SOURCE_LOCATION (method),
- "%q#D inherited from %qT", method,
- DECL_INHERITED_CTOR_BASE (method));
+ "%q#D", method);
error_at (DECL_SOURCE_LOCATION (fn),
"conflicts with version inherited from %qT",
- DECL_INHERITED_CTOR_BASE (fn));
+ basef);
}
/* Otherwise defer to the other function. */
return false;
@@ -1200,6 +1222,13 @@ add_method (tree type, tree method, tree using_decl)
/* Defer to the local function. */
return false;
}
+ else if (flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (fn))
+ {
+ /* Hide the inherited constructor. */
+ *p = OVL_NEXT (fns);
+ continue;
+ }
else
{
error ("%q+#D cannot be overloaded", method);
@@ -1212,6 +1241,12 @@ add_method (tree type, tree method, tree using_decl)
will crash while processing the definitions. */
return false;
}
+
+ cont:
+ if (TREE_CODE (fns) == OVERLOAD)
+ p = &OVL_CHAIN (fns);
+ else
+ break;
}
/* A class should never have more than one destructor. */
@@ -1299,6 +1334,16 @@ alter_access (tree t, tree fdecl, tree access)
return 0;
}
+/* Return the access node for DECL's access in its enclosing class. */
+
+tree
+declared_access (tree decl)
+{
+ return (TREE_PRIVATE (decl) ? access_private_node
+ : TREE_PROTECTED (decl) ? access_protected_node
+ : access_public_node);
+}
+
/* Process the USING_DECL, which is a member of T. */
static void
@@ -1306,10 +1351,7 @@ handle_using_decl (tree using_decl, tree t)
{
tree decl = USING_DECL_DECLS (using_decl);
tree name = DECL_NAME (using_decl);
- tree access
- = TREE_PRIVATE (using_decl) ? access_private_node
- : TREE_PROTECTED (using_decl) ? access_protected_node
- : access_public_node;
+ tree access = declared_access (using_decl);
tree flist = NULL_TREE;
tree old_value;
@@ -3301,10 +3343,19 @@ one_inheriting_sig (tree t, tree ctor, tree *parms, int nparms)
constructor CTOR. */
static void
-one_inherited_ctor (tree ctor, tree t)
+one_inherited_ctor (tree ctor, tree t, tree using_decl)
{
tree parms = FUNCTION_FIRST_USER_PARMTYPE (ctor);
+ if (flag_new_inheriting_ctors)
+ {
+ ctor = implicitly_declare_fn (sfk_inheriting_constructor,
+ t, /*const*/false, ctor, parms);
+ add_method (t, ctor, using_decl);
+ TYPE_HAS_USER_CONSTRUCTOR (t) = true;
+ return;
+ }
+
tree *new_parms = XALLOCAVEC (tree, list_length (parms));
int i = 0;
for (; parms && parms != void_list_node; parms = TREE_CHAIN (parms))
@@ -3405,7 +3456,7 @@ add_implicitly_declared_members (tree t, tree* access_decls,
input_location = DECL_SOURCE_LOCATION (using_decl);
if (ctor_list)
for (; ctor_list; ctor_list = OVL_NEXT (ctor_list))
- one_inherited_ctor (OVL_CURRENT (ctor_list), t);
+ one_inherited_ctor (OVL_CURRENT (ctor_list), t, using_decl);
*access_decls = TREE_CHAIN (*access_decls);
input_location = loc;
}
@@ -4765,6 +4816,11 @@ build_clone (tree fn, tree name)
}
}
+ /* A base constructor inheriting from a virtual base doesn't get the
+ arguments. */
+ if (ctor_omit_inherited_parms (fn))
+ DECL_CHAIN (DECL_CHAIN (DECL_ARGUMENTS (clone))) = NULL_TREE;
+
for (parms = DECL_ARGUMENTS (clone); parms; parms = DECL_CHAIN (parms))
{
DECL_CONTEXT (parms) = clone;
@@ -8121,10 +8177,14 @@ resolve_address_of_overloaded_function (tree target_type,
if (DECL_ANTICIPATED (fn))
continue;
+ /* In C++17 we need the noexcept-qualifier to compare types. */
+ if (flag_noexcept_type)
+ maybe_instantiate_noexcept (fn);
+
/* See if there's a match. */
tree fntype = static_fn_type (fn);
if (same_type_p (target_fn_type, fntype)
- || can_convert_tx_safety (target_fn_type, fntype))
+ || fnptr_conv_p (target_fn_type, fntype))
matches = tree_cons (fn, NULL_TREE, matches);
}
}
@@ -8201,10 +8261,14 @@ resolve_address_of_overloaded_function (tree target_type,
require_deduced_type (instantiation);
}
+ /* In C++17 we need the noexcept-qualifier to compare types. */
+ if (flag_noexcept_type)
+ maybe_instantiate_noexcept (instantiation);
+
/* See if there's a match. */
tree fntype = static_fn_type (instantiation);
if (same_type_p (target_fn_type, fntype)
- || can_convert_tx_safety (target_fn_type, fntype))
+ || fnptr_conv_p (target_fn_type, fntype))
matches = tree_cons (instantiation, fn, matches);
}
@@ -8368,6 +8432,8 @@ instantiate_type (tree lhstype, tree rhs, tsubst_flags_t complain)
tree fntype = non_reference (lhstype);
if (same_type_p (fntype, TREE_TYPE (rhs)))
return rhs;
+ if (fnptr_conv_p (fntype, TREE_TYPE (rhs)))
+ return rhs;
if (flag_ms_extensions
&& TYPE_PTRMEMFUNC_P (fntype)
&& !TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 1ebd647e7d1..43457d2463f 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -171,13 +171,13 @@ is_valid_constexpr_fn (tree fun, bool complain)
{
bool ret = true;
- if (DECL_INHERITED_CTOR_BASE (fun)
+ if (DECL_INHERITED_CTOR (fun)
&& TREE_CODE (fun) == TEMPLATE_DECL)
{
ret = false;
if (complain)
error ("inherited constructor %qD is not constexpr",
- get_inherited_ctor (fun));
+ DECL_INHERITED_CTOR (fun));
}
else
{
diff --git a/gcc/cp/cp-objcp-common.c b/gcc/cp/cp-objcp-common.c
index 070b64c5d82..633831ce4b3 100644
--- a/gcc/cp/cp-objcp-common.c
+++ b/gcc/cp/cp-objcp-common.c
@@ -131,6 +131,19 @@ cxx_types_compatible_p (tree x, tree y)
return same_type_ignoring_top_level_qualifiers_p (x, y);
}
+/* Return a type to use in the debug info instead of TYPE, or NULL_TREE to
+ keep TYPE. */
+
+tree
+cp_get_debug_type (const_tree type)
+{
+ if (TYPE_PTRMEMFUNC_P (type) && !typedef_variant_p (type))
+ return build_offset_type (TYPE_PTRMEMFUNC_OBJECT_TYPE (type),
+ TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (type)));
+
+ return NULL_TREE;
+}
+
/* Return -1 if dwarf ATTR shouldn't be added for DECL, or the attribute
value otherwise. */
int
@@ -179,11 +192,6 @@ cp_decl_dwarf_attribute (const_tree decl, int attr)
&& FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
&& !FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
return 1;
- if ((TREE_CODE (decl) == FUNCTION_TYPE
- || TREE_CODE (decl) == METHOD_TYPE)
- && FUNCTION_REF_QUALIFIED (decl)
- && !FUNCTION_RVALUE_QUALIFIED (decl))
- return 1;
break;
case DW_AT_rvalue_reference:
@@ -192,10 +200,48 @@ cp_decl_dwarf_attribute (const_tree decl, int attr)
&& FUNCTION_REF_QUALIFIED (TREE_TYPE (decl))
&& FUNCTION_RVALUE_QUALIFIED (TREE_TYPE (decl)))
return 1;
- if ((TREE_CODE (decl) == FUNCTION_TYPE
- || TREE_CODE (decl) == METHOD_TYPE)
- && FUNCTION_REF_QUALIFIED (decl)
- && FUNCTION_RVALUE_QUALIFIED (decl))
+ break;
+
+ case DW_AT_inline:
+ if (VAR_P (decl) && DECL_INLINE_VAR_P (decl))
+ {
+ if (DECL_VAR_DECLARED_INLINE_P (decl))
+ return DW_INL_declared_inlined;
+ else
+ return DW_INL_inlined;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+/* Return -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+ value otherwise. */
+int
+cp_type_dwarf_attribute (const_tree type, int attr)
+{
+ if (type == NULL_TREE)
+ return -1;
+
+ switch (attr)
+ {
+ case DW_AT_reference:
+ if ((TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ && FUNCTION_REF_QUALIFIED (type)
+ && !FUNCTION_RVALUE_QUALIFIED (type))
+ return 1;
+ break;
+
+ case DW_AT_rvalue_reference:
+ if ((TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ && FUNCTION_REF_QUALIFIED (type)
+ && FUNCTION_RVALUE_QUALIFIED (type))
return 1;
break;
diff --git a/gcc/cp/cp-objcp-common.h b/gcc/cp/cp-objcp-common.h
index 9dd847e4220..65ac95c2ee1 100644
--- a/gcc/cp/cp-objcp-common.h
+++ b/gcc/cp/cp-objcp-common.h
@@ -21,12 +21,14 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_CP_OBJCP_COMMON
#define GCC_CP_OBJCP_COMMON
-/* In cp/cp-lang.c and objcp/objcp-lang.c. */
+/* In cp/objcp-common.c, cp/cp-lang.c and objcp/objcp-lang.c. */
+extern tree cp_get_debug_type (const_tree);
extern tree objcp_tsubst_copy_and_build (tree, tree, tsubst_flags_t,
tree, bool);
extern int cp_decl_dwarf_attribute (const_tree, int);
+extern int cp_type_dwarf_attribute (const_tree, int);
extern void cp_common_init_ts (void);
/* Lang hooks that are shared between C++ and ObjC++ are defined here. Hooks
@@ -125,12 +127,16 @@ extern void cp_common_init_ts (void);
#define LANG_HOOKS_REGISTER_BUILTIN_TYPE c_register_builtin_type
#undef LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE
#define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE cp_reconstruct_complex_type
+#undef LANG_HOOKS_GET_DEBUG_TYPE
+#define LANG_HOOKS_GET_DEBUG_TYPE cp_get_debug_type
#undef LANG_HOOKS_TO_TARGET_CHARSET
#define LANG_HOOKS_TO_TARGET_CHARSET c_common_to_target_charset
#undef LANG_HOOKS_GIMPLIFY_EXPR
#define LANG_HOOKS_GIMPLIFY_EXPR cp_gimplify_expr
#undef LANG_HOOKS_DECL_DWARF_ATTRIBUTE
#define LANG_HOOKS_DECL_DWARF_ATTRIBUTE cp_decl_dwarf_attribute
+#undef LANG_HOOKS_TYPE_DWARF_ATTRIBUTE
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE cp_type_dwarf_attribute
#undef LANG_HOOKS_OMP_PREDETERMINED_SHARING
#define LANG_HOOKS_OMP_PREDETERMINED_SHARING cxx_omp_predetermined_sharing
#undef LANG_HOOKS_OMP_CLAUSE_DEFAULT_CTOR
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index c58996925c3..20b52ad675d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2730,12 +2730,21 @@ struct GTY(()) lang_decl {
(LANG_DECL_FN_CHECK (NODE)->context = (THUNKS))
/* If NODE, a FUNCTION_DECL, is a C++11 inheriting constructor, then this
- is the base it inherits from. */
-#define DECL_INHERITED_CTOR_BASE(NODE) \
- (DECL_CONSTRUCTOR_P (NODE) ? LANG_DECL_FN_CHECK (NODE)->context : NULL_TREE)
+ is the constructor it inherits from. */
+#define DECL_INHERITED_CTOR(NODE) \
+ (DECL_DECLARES_FUNCTION_P (NODE) && DECL_CONSTRUCTOR_P (NODE) \
+ ? LANG_DECL_FN_CHECK (NODE)->context : NULL_TREE)
+
+/* And this is the base that constructor comes from. */
+#define DECL_INHERITED_CTOR_BASE(NODE) \
+ (DECL_INHERITED_CTOR (NODE) \
+ ? DECL_CONTEXT (flag_new_inheriting_ctors \
+ ? strip_inheriting_ctors (NODE) \
+ : DECL_INHERITED_CTOR (NODE)) \
+ : NULL_TREE)
/* Set the inherited base. */
-#define SET_DECL_INHERITED_CTOR_BASE(NODE,INH) \
+#define SET_DECL_INHERITED_CTOR(NODE,INH) \
(LANG_DECL_FN_CHECK (NODE)->context = (INH))
/* Nonzero if NODE is a thunk, rather than an ordinary function. */
@@ -4735,6 +4744,8 @@ enum tsubst_flags {
for calls in decltype (5.2.2/11). */
tf_partial = 1 << 8, /* Doing initial explicit argument
substitution in fn_type_unification. */
+ tf_fndecl_type = 1 << 9, /* Substituting the type of a function
+ declaration. */
/* Convenient substitution flags combinations. */
tf_warning_or_error = tf_warning | tf_error
};
@@ -4940,6 +4951,10 @@ extern int at_eof;
extern bool defer_mangling_aliases;
+/* True if noexcept is part of the type (i.e. in C++17). */
+
+extern bool flag_noexcept_type;
+
/* A list of namespace-scope objects which have constructors or
destructors which reside in the global scope. The decl is stored
in the TREE_VALUE slot and the initializer is stored in the
@@ -5635,6 +5650,7 @@ extern tree get_vtable_decl (tree, int);
extern void resort_type_method_vec (void *, void *,
gt_pointer_operator, void *);
extern bool add_method (tree, tree, tree);
+extern tree declared_access (tree);
extern tree currently_open_class (tree);
extern tree currently_open_derived_class (tree);
extern tree outermost_open_class (void);
@@ -5727,7 +5743,8 @@ extern tree type_promotes_to (tree);
extern tree perform_qualification_conversions (tree, tree);
extern bool tx_safe_fn_type_p (tree);
extern tree tx_unsafe_fn_variant (tree);
-extern bool can_convert_tx_safety (tree, tree);
+extern bool fnptr_conv_p (tree, tree);
+extern tree strip_fnptr_conv (tree);
/* in name-lookup.c */
extern tree pushdecl (tree);
@@ -6035,7 +6052,9 @@ extern tree get_copy_ctor (tree, tsubst_flags_t);
extern tree get_copy_assign (tree);
extern tree get_default_ctor (tree);
extern tree get_dtor (tree, tsubst_flags_t);
-extern tree get_inherited_ctor (tree);
+extern tree strip_inheriting_ctors (tree);
+extern tree inherited_ctor_binfo (tree);
+extern bool ctor_omit_inherited_parms (tree);
extern tree locate_ctor (tree);
extern tree implicitly_declare_fn (special_function_kind, tree,
bool, tree, tree);
@@ -6565,6 +6584,7 @@ extern tree build_overload (tree, tree);
extern tree ovl_scope (tree);
extern const char *cxx_printable_name (tree, int);
extern const char *cxx_printable_name_translate (tree, int);
+extern tree canonical_eh_spec (tree);
extern tree build_exception_variant (tree, tree);
extern tree bind_template_template_parm (tree, tree);
extern tree array_type_nelts_total (tree);
@@ -6636,7 +6656,7 @@ extern tree complete_type (tree);
extern tree complete_type_or_else (tree, tree);
extern tree complete_type_or_maybe_complain (tree, tree, tsubst_flags_t);
extern int type_unknown_p (const_tree);
-enum { ce_derived, ce_normal, ce_exact };
+enum { ce_derived, ce_type, ce_normal, ce_exact };
extern bool comp_except_specs (const_tree, const_tree, int);
extern bool comptypes (tree, tree, int);
extern bool same_type_ignoring_top_level_qualifiers_p (tree, tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 2f5f15a2c82..400566f4e36 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1932,9 +1932,84 @@ tx_unsafe_fn_variant (tree t)
/* Return true iff FROM can convert to TO by a transaction-safety
conversion. */
-bool
+static bool
can_convert_tx_safety (tree to, tree from)
{
return (flag_tm && tx_safe_fn_type_p (from)
&& same_type_p (to, tx_unsafe_fn_variant (from)));
}
+
+/* Return true iff FROM can convert to TO by dropping noexcept. */
+
+static bool
+noexcept_conv_p (tree to, tree from)
+{
+ if (!flag_noexcept_type)
+ return false;
+
+ tree t = non_reference (to);
+ tree f = from;
+ if (TYPE_PTRMEMFUNC_P (t)
+ && TYPE_PTRMEMFUNC_P (f))
+ {
+ t = TYPE_PTRMEMFUNC_FN_TYPE (t);
+ f = TYPE_PTRMEMFUNC_FN_TYPE (f);
+ }
+ if (TREE_CODE (t) == POINTER_TYPE
+ && TREE_CODE (f) == POINTER_TYPE)
+ {
+ t = TREE_TYPE (t);
+ f = TREE_TYPE (f);
+ }
+ tree_code code = TREE_CODE (f);
+ if (TREE_CODE (t) != code)
+ return false;
+ if (code != FUNCTION_TYPE && code != METHOD_TYPE)
+ return false;
+ if (!type_throw_all_p (t)
+ || type_throw_all_p (f))
+ return false;
+ tree v = build_exception_variant (f, NULL_TREE);
+ return same_type_p (t, v);
+}
+
+/* Return true iff FROM can convert to TO by a function pointer conversion. */
+
+bool
+fnptr_conv_p (tree to, tree from)
+{
+ tree t = non_reference (to);
+ tree f = from;
+ if (TYPE_PTRMEMFUNC_P (t)
+ && TYPE_PTRMEMFUNC_P (f))
+ {
+ t = TYPE_PTRMEMFUNC_FN_TYPE (t);
+ f = TYPE_PTRMEMFUNC_FN_TYPE (f);
+ }
+ if (TREE_CODE (t) == POINTER_TYPE
+ && TREE_CODE (f) == POINTER_TYPE)
+ {
+ t = TREE_TYPE (t);
+ f = TREE_TYPE (f);
+ }
+
+ return (noexcept_conv_p (t, f)
+ || can_convert_tx_safety (t, f));
+}
+
+/* Return FN with any NOP_EXPRs that represent function pointer
+ conversions stripped. */
+
+tree
+strip_fnptr_conv (tree fn)
+{
+ while (TREE_CODE (fn) == NOP_EXPR)
+ {
+ tree op = TREE_OPERAND (fn, 0);
+ if (fnptr_conv_p (TREE_TYPE (fn), TREE_TYPE (op)))
+ fn = op;
+ else
+ break;
+ }
+ return fn;
+}
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ecf4d147d2a..c0321f9f959 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -73,8 +73,6 @@ static int check_static_variable_definition (tree, tree);
static void record_unknown_type (tree, const char *);
static tree builtin_function_1 (tree, tree, bool);
static int member_function_or_else (tree, tree, enum overload_flags);
-static void bad_specifiers (tree, enum bad_spec_place, int, int, int, int,
- int);
static void check_for_uninitialized_const_var (tree);
static tree local_variable_p_walkfn (tree *, int *, void *);
static const char *tag_name (enum tag_types);
@@ -227,6 +225,9 @@ struct GTY((for_user)) named_label_entry {
function, two inside the body of a function in a local class, etc.) */
int function_depth;
+/* Whether the exception-specifier is part of a function type (i.e. C++17). */
+bool flag_noexcept_type;
+
/* States indicating how grokdeclarator() should handle declspecs marked
with __attribute__((deprecated)). An object declared as
__attribute__((deprecated)) suppresses warnings of uses of other
@@ -4044,6 +4045,8 @@ cxx_init_decl_processing (void)
std_node = current_namespace;
pop_namespace ();
+ flag_noexcept_type = (cxx_dialect >= cxx1z);
+
c_common_nodes_and_builtins ();
integer_two_node = build_int_cst (NULL_TREE, 2);
@@ -7842,6 +7845,7 @@ bad_specifiers (tree object,
if (friendp)
error ("%q+D declared as a friend", object);
if (raises
+ && !flag_noexcept_type
&& (TREE_CODE (object) == TYPE_DECL
|| (!TYPE_PTRFN_P (TREE_TYPE (object))
&& !TYPE_REFFN_P (TREE_TYPE (object))
@@ -10477,6 +10481,9 @@ grokdeclarator (const cp_declarator *declarator,
The optional attribute-specifier-seq appertains to
the function type. */
decl_attributes (&type, attrs, 0);
+
+ if (raises)
+ type = build_exception_variant (type, raises);
}
break;
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 917a448ad34..aa92a7e6a6b 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -1617,6 +1617,13 @@ dump_function_decl (cxx_pretty_printer *pp, tree t, int flags)
pp_cxx_requires_clause (pp, reqs);
dump_substitution (pp, t, template_parms, template_args, flags);
+
+ if (tree base = DECL_INHERITED_CTOR_BASE (t))
+ {
+ pp_cxx_ws_string (pp, "[inherited from");
+ dump_type (pp, base, TFF_PLAIN_IDENTIFIER);
+ pp_character (pp, ']');
+ }
}
else if (template_args)
{
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 2418a9d48c1..5eba4c3e18c 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1117,7 +1117,7 @@ emit_mem_initializers (tree mem_inits)
}
if (DECL_DEFAULTED_FN (current_function_decl)
- && ! DECL_INHERITED_CTOR_BASE (current_function_decl))
+ && ! DECL_INHERITED_CTOR (current_function_decl))
flags |= LOOKUP_DEFAULTED;
/* Sort the mem-initializers into the order in which the
@@ -1138,6 +1138,13 @@ emit_mem_initializers (tree mem_inits)
if (arguments == error_mark_node)
continue;
+ /* Suppress access control when calling the inherited ctor. */
+ bool inherited_base = (DECL_INHERITED_CTOR (current_function_decl)
+ && flag_new_inheriting_ctors
+ && arguments);
+ if (inherited_base)
+ push_deferring_access_checks (dk_deferred);
+
if (arguments == NULL_TREE)
{
/* If these initializations are taking place in a copy constructor,
@@ -1172,6 +1179,9 @@ emit_mem_initializers (tree mem_inits)
/* C++14 DR1658 Means we do not have to construct vbases of
abstract classes. */
construct_virtual_base (subobject, arguments);
+
+ if (inherited_base)
+ pop_deferring_access_checks ();
}
in_base_initializer = 0;
diff --git a/gcc/cp/lambda.c b/gcc/cp/lambda.c
index d4284bfa48b..c48cd5201e0 100644
--- a/gcc/cp/lambda.c
+++ b/gcc/cp/lambda.c
@@ -1029,6 +1029,9 @@ maybe_add_lambda_conv_op (tree type)
tree stattype = build_function_type (fn_result, FUNCTION_ARG_CHAIN (callop));
stattype = (cp_build_type_attribute_variant
(stattype, TYPE_ATTRIBUTES (optype)));
+ if (flag_noexcept_type
+ && TYPE_NOTHROW_P (TREE_TYPE (callop)))
+ stattype = build_exception_variant (stattype, noexcept_true_spec);
/* First build up the conversion op. */
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index cb2f260c2d1..a354ec5ead3 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -114,6 +114,9 @@ struct GTY(()) globals {
/* True if the mangling will be different in a future version of the
ABI. */
bool need_abi_warning;
+
+ /* True if the mangling will be different in C++17 mode. */
+ bool need_cxx1z_warning;
};
static GTY (()) globals G;
@@ -344,6 +347,43 @@ dump_substitution_candidates (void)
}
}
+/* <exception-spec> ::=
+ Do -- non-throwing exception specification
+ DO <expression> E -- computed (instantiation-dependent) noexcept
+ Dw <type>* E -- throw (types) */
+
+static void
+write_exception_spec (tree spec)
+{
+
+ if (!spec || spec == noexcept_false_spec)
+ /* Nothing. */
+ return;
+
+ if (!flag_noexcept_type)
+ {
+ G.need_cxx1z_warning = true;
+ return;
+ }
+
+ if (nothrow_spec_p (spec))
+ write_string ("Do");
+ else if (TREE_PURPOSE (spec))
+ {
+ gcc_assert (uses_template_parms (TREE_PURPOSE (spec)));
+ write_string ("DO");
+ write_expression (TREE_PURPOSE (spec));
+ write_char ('E');
+ }
+ else
+ {
+ write_string ("Dw");
+ for (tree t = spec; t; t = TREE_CHAIN (t))
+ write_type (TREE_VALUE (t));
+ write_char ('E');
+ }
+}
+
/* Both decls and types can be substitution candidates, but sometimes
they refer to the same thing. For instance, a TYPE_DECL and
RECORD_TYPE for the same class refer to the same thing, and should
@@ -375,7 +415,15 @@ canonicalize_for_substitution (tree node)
cp_type_quals (node));
if (TREE_CODE (node) == FUNCTION_TYPE
|| TREE_CODE (node) == METHOD_TYPE)
- node = build_ref_qualified_type (node, type_memfn_rqual (orig));
+ {
+ node = build_ref_qualified_type (node, type_memfn_rqual (orig));
+ tree r = canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (orig));
+ if (flag_noexcept_type)
+ node = build_exception_variant (node, r);
+ else
+ /* Set the warning flag if appropriate. */
+ write_exception_spec (r);
+ }
}
return node;
}
@@ -777,9 +825,11 @@ write_encoding (const tree decl)
{
tree fn_type;
tree d;
+ bool tmpl = decl_is_template_id (decl, NULL);
- if (decl_is_template_id (decl, NULL))
+ if (tmpl)
{
+ ++processing_template_decl;
fn_type = get_mostly_instantiated_function_type (decl);
/* FN_TYPE will not have parameter types for in-charge or
VTT parameters. Therefore, we pass NULL_TREE to
@@ -796,6 +846,9 @@ write_encoding (const tree decl)
write_bare_function_type (fn_type,
mangle_return_type_p (decl),
d);
+
+ if (tmpl)
+ --processing_template_decl;
}
}
@@ -1786,18 +1839,25 @@ write_identifier (const char *identifier)
static void
write_special_name_constructor (const tree ctor)
{
+ write_char ('C');
+ bool new_inh = (flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (ctor));
+ if (new_inh)
+ write_char ('I');
if (DECL_BASE_CONSTRUCTOR_P (ctor))
- write_string ("C2");
+ write_char ('2');
/* This is the old-style "[unified]" constructor.
In some cases, we may emit this function and call
it from the clones in order to share code and save space. */
else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (ctor))
- write_string ("C4");
+ write_char ('4');
else
{
gcc_assert (DECL_COMPLETE_CONSTRUCTOR_P (ctor));
- write_string ("C1");
+ write_char ('1');
}
+ if (new_inh)
+ write_type (DECL_INHERITED_CTOR_BASE (ctor));
}
/* Handle destructor productions of non-terminal <special-name>.
@@ -2057,7 +2117,11 @@ write_type (tree type)
type = TYPE_MAIN_VARIANT (type);
if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
- type = build_ref_qualified_type (type, type_memfn_rqual (type_orig));
+ {
+ type = build_ref_qualified_type (type, type_memfn_rqual (type_orig));
+ type = build_exception_variant (type,
+ TYPE_RAISES_EXCEPTIONS (type_orig));
+ }
/* According to the C++ ABI, some library classes are passed the
same as the scalar type of their single member and use the same
@@ -2582,6 +2646,8 @@ write_function_type (const tree type)
write_CV_qualifiers_for_type (this_type);
}
+ write_exception_spec (TYPE_RAISES_EXCEPTIONS (type));
+
if (tx_safe_fn_type_p (type))
write_string ("Dx");
@@ -3769,6 +3835,12 @@ mangle_decl (const tree decl)
}
SET_DECL_ASSEMBLER_NAME (decl, id);
+ if (G.need_cxx1z_warning)
+ warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wc__1z_compat,
+ "mangled name for %qD will change in C++17 because the "
+ "exception specification is part of a function type",
+ decl);
+
if (id != DECL_NAME (decl)
/* Don't do this for a fake symbol we aren't going to emit anyway. */
&& TREE_CODE (decl) != TYPE_DECL
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 73a670b59c8..73d42b19d55 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -492,6 +492,118 @@ forward_parm (tree parm)
return exp;
}
+/* Strip all inheriting constructors, if any, to return the original
+ constructor from a (possibly indirect) base class. */
+
+tree
+strip_inheriting_ctors (tree fn)
+{
+ gcc_assert (flag_new_inheriting_ctors);
+ while (tree inh = DECL_INHERITED_CTOR (fn))
+ {
+ inh = OVL_CURRENT (inh);
+ fn = inh;
+ }
+ return fn;
+}
+
+/* Find the binfo for the base subobject of BINFO being initialized by
+ inherited constructor FNDECL (a member of a direct base of BINFO). */
+
+static tree inherited_ctor_binfo (tree, tree);
+static tree
+inherited_ctor_binfo_1 (tree binfo, tree fndecl)
+{
+ tree base = DECL_CONTEXT (fndecl);
+ tree base_binfo;
+ for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (BINFO_TYPE (base_binfo) == base)
+ return inherited_ctor_binfo (base_binfo, fndecl);
+
+ gcc_unreachable();
+}
+
+/* Find the binfo for the base subobject of BINFO being initialized by
+ inheriting constructor FNDECL (a member of BINFO), or BINFO if FNDECL is not
+ an inheriting constructor. */
+
+static tree
+inherited_ctor_binfo (tree binfo, tree fndecl)
+{
+ tree inh = DECL_INHERITED_CTOR (fndecl);
+ if (!inh)
+ return binfo;
+
+ tree results = NULL_TREE;
+ for (; inh; inh = OVL_NEXT (inh))
+ {
+ tree one = inherited_ctor_binfo_1 (binfo, OVL_CURRENT (inh));
+ if (!results)
+ results = one;
+ else if (one != results)
+ results = tree_cons (NULL_TREE, one, results);
+ }
+ return results;
+}
+
+/* Find the binfo for the base subobject being initialized by inheriting
+ constructor FNDECL, or NULL_TREE if FNDECL is not an inheriting
+ constructor. */
+
+tree
+inherited_ctor_binfo (tree fndecl)
+{
+ if (!DECL_INHERITED_CTOR (fndecl))
+ return NULL_TREE;
+ tree binfo = TYPE_BINFO (DECL_CONTEXT (fndecl));
+ return inherited_ctor_binfo (binfo, fndecl);
+}
+
+/* True if we should omit all user-declared parameters from constructor FN,
+ because it is a base clone of a ctor inherited from a virtual base. */
+
+bool
+ctor_omit_inherited_parms (tree fn)
+{
+ if (!flag_new_inheriting_ctors)
+ /* We only optimize away the parameters in the new model. */
+ return false;
+ if (!DECL_BASE_CONSTRUCTOR_P (fn)
+ || !CLASSTYPE_VBASECLASSES (DECL_CONTEXT (fn)))
+ return false;
+ tree binfo = inherited_ctor_binfo (fn);
+ for (; binfo; binfo = BINFO_INHERITANCE_CHAIN (binfo))
+ if (BINFO_VIRTUAL_P (binfo))
+ return true;
+ return false;
+}
+
+/* True iff constructor(s) INH inherited into BINFO initializes INIT_BINFO.
+ This can be true for multiple virtual bases as well as one direct
+ non-virtual base. */
+
+static bool
+binfo_inherited_from (tree binfo, tree init_binfo, tree inh)
+{
+ /* inh is an OVERLOAD if we inherited the same constructor along
+ multiple paths, check all of them. */
+ for (; inh; inh = OVL_NEXT (inh))
+ {
+ tree fn = OVL_CURRENT (inh);
+ tree base = DECL_CONTEXT (fn);
+ tree base_binfo = NULL_TREE;
+ for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
+ if (BINFO_TYPE (base_binfo) == base)
+ break;
+ if (base_binfo == init_binfo
+ || (flag_new_inheriting_ctors
+ && binfo_inherited_from (base_binfo, init_binfo,
+ DECL_INHERITED_CTOR (fn))))
+ return true;
+ }
+ return false;
+}
+
/* Subroutine of do_build_copy_constructor: Add a mem-initializer for BINFO
given the parameter or parameters PARM, possibly inherited constructor
base INH, or move flag MOVE_P. */
@@ -505,7 +617,7 @@ add_one_base_init (tree binfo, tree parm, bool move_p, tree inh,
{
/* An inheriting constructor only has a mem-initializer for
the base it inherits from. */
- if (BINFO_TYPE (binfo) != inh)
+ if (!binfo_inherited_from (TYPE_BINFO (current_class_type), binfo, inh))
return member_init_list;
tree *p = &init;
@@ -537,7 +649,7 @@ do_build_copy_constructor (tree fndecl)
tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
bool move_p = DECL_MOVE_CONSTRUCTOR_P (fndecl);
bool trivial = trivial_fn_p (fndecl);
- tree inh = DECL_INHERITED_CTOR_BASE (fndecl);
+ tree inh = DECL_INHERITED_CTOR (fndecl);
if (!inh)
parm = convert_from_reference (parm);
@@ -901,7 +1013,7 @@ locate_fn_flags (tree type, tree name, tree argtype, int flags,
{
if (TREE_CODE (argtype) == TREE_LIST)
{
- for (tree elt = argtype; elt != void_list_node;
+ for (tree elt = argtype; elt && elt != void_list_node;
elt = TREE_CHAIN (elt))
{
tree type = TREE_VALUE (elt);
@@ -996,25 +1108,6 @@ get_copy_assign (tree type)
return fn;
}
-/* Locate the inherited constructor of constructor CTOR. */
-
-tree
-get_inherited_ctor (tree ctor)
-{
- gcc_assert (DECL_INHERITED_CTOR_BASE (ctor));
-
- push_deferring_access_checks (dk_no_check);
- tree fn = locate_fn_flags (DECL_INHERITED_CTOR_BASE (ctor),
- complete_ctor_identifier,
- FUNCTION_FIRST_USER_PARMTYPE (ctor),
- LOOKUP_NORMAL|LOOKUP_SPECULATIVE,
- tf_none);
- pop_deferring_access_checks ();
- if (fn == error_mark_node)
- return NULL_TREE;
- return fn;
-}
-
/* walk_tree helper function for is_trivially_xible. If *TP is a call,
return it if it calls something other than a trivial special member
function. */
@@ -1330,7 +1423,7 @@ static void
synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
tree *spec_p, bool *trivial_p, bool *deleted_p,
bool *constexpr_p, bool diag,
- tree inherited_base, tree inherited_parms)
+ tree inheriting_ctor, tree inherited_parms)
{
tree binfo, base_binfo, scope, fnname, rval, argtype;
bool move_p, copy_arg_p, assign_p, expected_trivial, check_vdtor;
@@ -1389,7 +1482,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
}
gcc_assert ((sfk == sfk_inheriting_constructor)
- == (inherited_base != NULL_TREE));
+ == (inheriting_ctor != NULL_TREE));
/* If that user-written default constructor would satisfy the
requirements of a constexpr constructor (7.1.5), the
@@ -1465,7 +1558,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
scope = push_scope (ctype);
flags = LOOKUP_NORMAL|LOOKUP_SPECULATIVE;
- if (!inherited_base)
+ if (!inheriting_ctor)
flags |= LOOKUP_DEFAULTED;
complain = diag ? tf_warning_or_error : tf_none;
@@ -1485,13 +1578,25 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
/* We'll handle virtual bases below. */
continue;
+ bool inherited_binfo = false;
+
if (copy_arg_p)
argtype = build_stub_type (basetype, quals, move_p);
- else if (basetype == inherited_base)
- argtype = inherited_parms;
+ else if ((inherited_binfo
+ = binfo_inherited_from (binfo, base_binfo, inheriting_ctor)))
+ {
+ /* Don't check access on the inherited constructor. */
+ argtype = inherited_parms;
+ if (flag_new_inheriting_ctors)
+ push_deferring_access_checks (dk_deferred);
+ }
rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
- if (inherited_base)
- argtype = NULL_TREE;
+ if (inherited_binfo)
+ {
+ if (flag_new_inheriting_ctors)
+ pop_deferring_access_checks ();
+ argtype = NULL_TREE;
+ }
process_subob_fn (rval, spec_p, trivial_p, deleted_p,
constexpr_p, diag, basetype);
@@ -1547,9 +1652,24 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
FOR_EACH_VEC_ELT (*vbases, i, base_binfo)
{
tree basetype = BINFO_TYPE (base_binfo);
+ bool inherited_binfo = false;
+
if (copy_arg_p)
argtype = build_stub_type (basetype, quals, move_p);
+ else if ((inherited_binfo
+ = binfo_inherited_from (binfo, base_binfo, inheriting_ctor)))
+ {
+ argtype = inherited_parms;
+ if (flag_new_inheriting_ctors)
+ push_deferring_access_checks (dk_deferred);
+ }
rval = locate_fn_flags (base_binfo, fnname, argtype, flags, complain);
+ if (inherited_binfo)
+ {
+ if (flag_new_inheriting_ctors)
+ pop_deferring_access_checks ();
+ argtype = NULL_TREE;
+ }
process_subob_fn (rval, spec_p, trivial_p, deleted_p,
constexpr_p, diag, basetype);
@@ -1598,7 +1718,7 @@ get_defaulted_eh_spec (tree decl)
bool const_p = CP_TYPE_CONST_P (non_reference (parm_type));
tree spec = empty_except_spec;
synthesized_method_walk (ctype, sfk, const_p, &spec, NULL, NULL,
- NULL, false, DECL_INHERITED_CTOR_BASE (decl),
+ NULL, false, DECL_INHERITED_CTOR (decl),
parms);
return spec;
}
@@ -1657,6 +1777,17 @@ maybe_explain_implicit_delete (tree decl)
decl, ctype);
informed = true;
}
+ else if (sfk == sfk_inheriting_constructor)
+ {
+ tree binfo = inherited_ctor_binfo (decl);
+ if (TREE_CODE (binfo) != TREE_BINFO)
+ {
+ inform (DECL_SOURCE_LOCATION (decl),
+ "%q#D inherits from multiple base subobjects",
+ decl);
+ informed = true;
+ }
+ }
if (!informed)
{
tree parms = FUNCTION_FIRST_USER_PARMTYPE (decl);
@@ -1668,7 +1799,7 @@ maybe_explain_implicit_delete (tree decl)
synthesized_method_walk (ctype, sfk, const_p,
&raises, NULL, &deleted_p, NULL, false,
- DECL_INHERITED_CTOR_BASE (decl), parms);
+ DECL_INHERITED_CTOR (decl), parms);
if (deleted_p)
{
inform (DECL_SOURCE_LOCATION (decl),
@@ -1676,7 +1807,7 @@ maybe_explain_implicit_delete (tree decl)
"definition would be ill-formed:", decl);
synthesized_method_walk (ctype, sfk, const_p,
NULL, NULL, NULL, NULL, true,
- DECL_INHERITED_CTOR_BASE (decl), parms);
+ DECL_INHERITED_CTOR (decl), parms);
}
else if (!comp_except_specs
(TYPE_RAISES_EXCEPTIONS (TREE_TYPE (decl)),
@@ -1709,7 +1840,7 @@ explain_implicit_non_constexpr (tree decl)
synthesized_method_walk (DECL_CLASS_CONTEXT (decl),
special_function_p (decl), const_p,
NULL, NULL, NULL, &dummy, true,
- DECL_INHERITED_CTOR_BASE (decl),
+ DECL_INHERITED_CTOR (decl),
FUNCTION_FIRST_USER_PARMTYPE (decl));
}
@@ -1720,14 +1851,17 @@ explain_implicit_non_constexpr (tree decl)
void
deduce_inheriting_ctor (tree decl)
{
- gcc_assert (DECL_INHERITED_CTOR_BASE (decl));
+ gcc_assert (DECL_INHERITED_CTOR (decl));
tree spec;
bool trivial, constexpr_, deleted;
synthesized_method_walk (DECL_CONTEXT (decl), sfk_inheriting_constructor,
false, &spec, &trivial, &deleted, &constexpr_,
/*diag*/false,
- DECL_INHERITED_CTOR_BASE (decl),
+ DECL_INHERITED_CTOR (decl),
FUNCTION_FIRST_USER_PARMTYPE (decl));
+ if (TREE_CODE (inherited_ctor_binfo (decl)) != TREE_BINFO)
+ /* Inherited the same constructor from different base subobjects. */
+ deleted = true;
DECL_DELETED_FN (decl) = deleted;
TREE_TYPE (decl) = build_exception_variant (TREE_TYPE (decl), spec);
}
@@ -1828,9 +1962,6 @@ implicitly_declare_fn (special_function_kind kind, tree type,
gcc_unreachable ();
}
- tree inherited_base = (inherited_ctor
- ? DECL_CONTEXT (inherited_ctor)
- : NULL_TREE);
bool trivial_p = false;
if (inherited_ctor && TREE_CODE (inherited_ctor) == TEMPLATE_DECL)
@@ -1846,12 +1977,12 @@ implicitly_declare_fn (special_function_kind kind, tree type,
raises = unevaluated_noexcept_spec ();
synthesized_method_walk (type, kind, const_p, NULL, &trivial_p,
&deleted_p, &constexpr_p, false,
- inherited_base, inherited_parms);
+ inherited_ctor, inherited_parms);
}
else
synthesized_method_walk (type, kind, const_p, &raises, &trivial_p,
&deleted_p, &constexpr_p, false,
- inherited_base, inherited_parms);
+ inherited_ctor, inherited_parms);
/* Don't bother marking a deleted constructor as constexpr. */
if (deleted_p)
constexpr_p = false;
@@ -1902,7 +2033,7 @@ implicitly_declare_fn (special_function_kind kind, tree type,
{
tree *p = &DECL_ARGUMENTS (fn);
int index = 1;
- for (tree parm = inherited_parms; parm != void_list_node;
+ for (tree parm = inherited_parms; parm && parm != void_list_node;
parm = TREE_CHAIN (parm))
{
*p = cp_build_parm_decl (NULL_TREE, TREE_VALUE (parm));
@@ -1912,7 +2043,7 @@ implicitly_declare_fn (special_function_kind kind, tree type,
DECL_CONTEXT (*p) = fn;
p = &DECL_CHAIN (*p);
}
- SET_DECL_INHERITED_CTOR_BASE (fn, inherited_base);
+ SET_DECL_INHERITED_CTOR (fn, inherited_ctor);
DECL_NONCONVERTING_P (fn) = DECL_NONCONVERTING_P (inherited_ctor);
/* A constructor so declared has the same access as the corresponding
constructor in X. */
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 9e84a1b1f2e..e574c271194 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1195,19 +1195,41 @@ pushdecl_maybe_friend_1 (tree x, bool is_friend)
nowarn = true;
}
- if (warn_shadow && !nowarn)
+ if ((warn_shadow
+ || warn_shadow_local
+ || warn_shadow_compatible_local)
+ && !nowarn)
{
bool warned;
+ enum opt_code warning_code;
+ /* If '-Wshadow=compatible-local' is specified without other
+ -Wshadow= flags, we will warn only when the type of the
+ shadowing variable (i.e. x) can be converted to that of
+ the shadowed parameter (oldlocal). The reason why we only
+ check if x's type can be converted to oldlocal's type
+ (but not the other way around) is because when users
+ accidentally shadow a parameter, more than often they
+ would use the variable thinking (mistakenly) it's still
+ the parameter. It would be rare that users would use the
+ variable in the place that expects the parameter but
+ thinking it's a new decl. */
+ if (warn_shadow)
+ warning_code = OPT_Wshadow;
+ else if (can_convert (TREE_TYPE (oldlocal), TREE_TYPE (x),
+ tf_none))
+ warning_code = OPT_Wshadow_compatible_local;
+ else
+ warning_code = OPT_Wshadow_local;
if (TREE_CODE (oldlocal) == PARM_DECL)
- warned = warning_at (input_location, OPT_Wshadow,
+ warned = warning_at (input_location, warning_code,
"declaration of %q#D shadows a parameter", x);
else if (is_capture_proxy (oldlocal))
- warned = warning_at (input_location, OPT_Wshadow,
+ warned = warning_at (input_location, warning_code,
"declaration of %qD shadows a lambda capture",
x);
else
- warned = warning_at (input_location, OPT_Wshadow,
+ warned = warning_at (input_location, warning_code,
"declaration of %qD shadows a previous local",
x);
@@ -3399,6 +3421,12 @@ do_class_using_decl (tree scope, tree name)
return NULL_TREE;
}
}
+ else if (name == ctor_identifier
+ && BINFO_INHERITANCE_CHAIN (BINFO_INHERITANCE_CHAIN (binfo)))
+ {
+ error ("cannot inherit constructors from indirect base %qT", scope);
+ return NULL_TREE;
+ }
else if (!name_dependent_p)
{
decl = lookup_member (binfo, name, 0, false, tf_warning_or_error);
diff --git a/gcc/cp/optimize.c b/gcc/cp/optimize.c
index e2032c1d90e..b926ef7ad6c 100644
--- a/gcc/cp/optimize.c
+++ b/gcc/cp/optimize.c
@@ -166,7 +166,8 @@ cdtor_comdat_group (tree complete, tree base)
{
gcc_assert (!diff_seen
&& idx > 0
- && (p[idx - 1] == 'C' || p[idx - 1] == 'D')
+ && (p[idx - 1] == 'C' || p[idx - 1] == 'D'
+ || p[idx - 1] == 'I')
&& p[idx] == '1'
&& q[idx] == '2');
grp_name[idx] = '5';
@@ -259,6 +260,11 @@ maybe_thunk_body (tree fn, bool force)
(for non-vague linkage ctors) or the COMDAT group (otherwise). */
populate_clone_array (fn, fns);
+
+ /* Don't use thunks if the base clone omits inherited parameters. */
+ if (ctor_omit_inherited_parms (fns[0]))
+ return 0;
+
DECL_ABSTRACT_P (fn) = false;
if (!DECL_WEAK (fn))
{
@@ -490,7 +496,7 @@ maybe_clone_body (tree fn)
parm = DECL_CHAIN (parm);
if (DECL_HAS_VTT_PARM_P (clone))
clone_parm = DECL_CHAIN (clone_parm);
- for (; parm;
+ for (; parm && clone_parm;
parm = DECL_CHAIN (parm), clone_parm = DECL_CHAIN (clone_parm))
/* Update this parameter. */
update_cloned_parm (parm, clone_parm, first);
@@ -616,7 +622,8 @@ maybe_clone_body (tree fn)
else
{
decl_map->put (parm, clone_parm);
- clone_parm = DECL_CHAIN (clone_parm);
+ if (clone_parm)
+ clone_parm = DECL_CHAIN (clone_parm);
}
}
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 53eafa7beeb..e4436485053 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -6441,7 +6441,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
can be used in constant-expressions. */
if (!cast_valid_in_integral_constant_expression_p (type)
&& cp_parser_non_integral_constant_expression (parser, NIC_CAST))
- return error_mark_node;
+ {
+ postfix_expression = error_mark_node;
+ break;
+ }
switch (keyword)
{
@@ -6521,7 +6524,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
parser->type_definition_forbidden_message = saved_message;
/* `typeid' may not appear in an integral constant expression. */
if (cp_parser_non_integral_constant_expression (parser, NIC_TYPEID))
- return error_mark_node;
+ postfix_expression = error_mark_node;
}
break;
@@ -6615,7 +6618,10 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
/*cast_p=*/false, /*allow_expansion_p=*/true,
/*non_constant_p=*/NULL);
if (vec == NULL)
- return error_mark_node;
+ {
+ postfix_expression = error_mark_node;
+ break;
+ }
FOR_EACH_VEC_ELT (*vec, i, p)
mark_exp_read (p);
@@ -6624,10 +6630,15 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
{
case RID_ADDRESSOF:
if (vec->length () == 1)
- return cp_build_addressof (loc, (*vec)[0], tf_warning_or_error);
- error_at (loc, "wrong number of arguments to "
- "%<__builtin_addressof%>");
- return error_mark_node;
+ postfix_expression
+ = cp_build_addressof (loc, (*vec)[0], tf_warning_or_error);
+ else
+ {
+ error_at (loc, "wrong number of arguments to "
+ "%<__builtin_addressof%>");
+ postfix_expression = error_mark_node;
+ }
+ break;
case RID_BUILTIN_LAUNDER:
if (vec->length () == 1)
@@ -6643,14 +6654,20 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
case RID_BUILTIN_SHUFFLE:
if (vec->length () == 2)
- return build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE,
- (*vec)[1], tf_warning_or_error);
+ postfix_expression
+ = build_x_vec_perm_expr (loc, (*vec)[0], NULL_TREE,
+ (*vec)[1], tf_warning_or_error);
else if (vec->length () == 3)
- return build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1],
- (*vec)[2], tf_warning_or_error);
- error_at (loc, "wrong number of arguments to "
- "%<__builtin_shuffle%>");
- return error_mark_node;
+ postfix_expression
+ = build_x_vec_perm_expr (loc, (*vec)[0], (*vec)[1],
+ (*vec)[2], tf_warning_or_error);
+ else
+ {
+ error_at (loc, "wrong number of arguments to "
+ "%<__builtin_shuffle%>");
+ postfix_expression = error_mark_node;
+ }
+ break;
default:
gcc_unreachable ();
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index c916e58482f..3df71dd97db 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -2216,7 +2216,7 @@ determine_specialization (tree template_id,
continue;
// Then, try to form the new function type.
- insttype = tsubst (TREE_TYPE (fn), targs, tf_none, NULL_TREE);
+ insttype = tsubst (TREE_TYPE (fn), targs, tf_fndecl_type, NULL_TREE);
if (insttype == error_mark_node)
continue;
fn_arg_types
@@ -5876,7 +5876,7 @@ get_underlying_template (tree tmpl)
}
/* Subroutine of convert_nontype_argument. Converts EXPR to TYPE, which
- must be a function or a pointer-to-function type, as specified
+ must be a reference-to-function or a pointer-to-function type, as specified
in [temp.arg.nontype]: disambiguate EXPR if it is an overload set,
and check that the resulting function has external linkage. */
@@ -5892,7 +5892,7 @@ convert_nontype_argument_function (tree type, tree expr,
if (fn == error_mark_node)
return error_mark_node;
- fn_no_ptr = fn;
+ fn_no_ptr = strip_fnptr_conv (fn);
if (TREE_CODE (fn_no_ptr) == ADDR_EXPR)
fn_no_ptr = TREE_OPERAND (fn_no_ptr, 0);
if (BASELINK_P (fn_no_ptr))
@@ -5913,11 +5913,11 @@ convert_nontype_argument_function (tree type, tree expr,
error ("%qE is not a valid template argument for type %qT",
expr, type);
if (TYPE_PTR_P (type))
- error ("it must be the address of a function with "
- "external linkage");
+ inform (input_location, "it must be the address of a function "
+ "with external linkage");
else
- error ("it must be the name of a function with "
- "external linkage");
+ inform (input_location, "it must be the name of a function with "
+ "external linkage");
}
return NULL_TREE;
}
@@ -5939,6 +5939,11 @@ convert_nontype_argument_function (tree type, tree expr,
return NULL_TREE;
}
+ if (TREE_CODE (type) == REFERENCE_TYPE)
+ fn = build_address (fn);
+ if (!same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (fn)))
+ fn = build_nop (type, fn);
+
return fn;
}
@@ -6648,8 +6653,6 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
expr = convert_nontype_argument_function (type, expr, complain);
if (!expr || expr == error_mark_node)
return expr;
-
- expr = build_nop (type, build_address (expr));
}
/* [temp.arg.nontype]/5, bullet 6
@@ -6669,6 +6672,11 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain)
&& !check_valid_ptrmem_cst_expr (type, expr, complain))
return error_mark_node;
+ /* Repeated conversion can't deal with a conversion that turns PTRMEM_CST
+ into a CONSTRUCTOR, so build up a new PTRMEM_CST instead. */
+ if (fnptr_conv_p (type, TREE_TYPE (expr)))
+ expr = make_ptrmem_cst (type, PTRMEM_CST_MEMBER (expr));
+
/* There is no way to disable standard conversions in
resolve_address_of_overloaded_function (called by
instantiate_type). It is possible that the call succeeded by
@@ -7325,7 +7333,8 @@ convert_template_argument (tree parm,
if (val == NULL_TREE)
val = error_mark_node;
else if (val == error_mark_node && (complain & tf_error))
- error ("could not convert template argument %qE to %qT", orig_arg, t);
+ error ("could not convert template argument %qE from %qT to %qT",
+ orig_arg, TREE_TYPE (orig_arg), t);
if (INDIRECT_REF_P (val))
{
@@ -8857,6 +8866,13 @@ for_each_template_parm_r (tree *tp, int *walk_subtrees, void *d)
want walk_tree walking into them itself. */
*walk_subtrees = 0;
}
+
+ if (flag_noexcept_type)
+ {
+ tree spec = TYPE_RAISES_EXCEPTIONS (t);
+ if (spec)
+ WALK_SUBTREE (TREE_PURPOSE (spec));
+ }
break;
case TYPEOF_TYPE:
@@ -9170,6 +9186,13 @@ push_tinst_level_loc (tree d, location_t loc)
if (limit_bad_template_recursion (d))
return false;
+ /* When not -quiet, dump template instantiations other than functions, since
+ announce_function will take care of those. */
+ if (!quiet_flag
+ && TREE_CODE (d) != TREE_LIST
+ && TREE_CODE (d) != FUNCTION_DECL)
+ fprintf (stderr, " %s", decl_as_string (d, TFF_DECL_SPECIFIERS));
+
new_level = ggc_alloc<tinst_level> ();
new_level->decl = d;
new_level->locus = loc;
@@ -11921,7 +11944,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
member = 0;
ctx = DECL_CONTEXT (t);
}
- type = tsubst (TREE_TYPE (t), args, complain, in_decl);
+ type = tsubst (TREE_TYPE (t), args, complain|tf_fndecl_type, in_decl);
if (type == error_mark_node)
RETURN (error_mark_node);
@@ -12056,7 +12079,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
maybe_retrofit_in_chrg (r);
if (DECL_CONSTRUCTOR_P (r))
grok_ctor_properties (ctx, r);
- if (DECL_INHERITED_CTOR_BASE (r))
+ if (DECL_INHERITED_CTOR (r))
deduce_inheriting_ctor (r);
/* If this is an instantiation of a member template, clone it.
If it isn't, that'll be handled by
@@ -13004,6 +13027,9 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
}
+ bool fndecl_type = (complain & tf_fndecl_type);
+ complain &= ~tf_fndecl_type;
+
if (type
&& code != TYPENAME_TYPE
&& code != TEMPLATE_TYPE_PARM
@@ -13501,8 +13527,8 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
return error_mark_node;
/* Substitute the exception specification. */
- specs = tsubst_exception_specification (t, args, complain,
- in_decl, /*defer_ok*/true);
+ specs = tsubst_exception_specification (t, args, complain, in_decl,
+ /*defer_ok*/fndecl_type);
if (specs == error_mark_node)
return error_mark_node;
if (specs)
@@ -15437,15 +15463,27 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
if (IF_STMT_CONSTEXPR_P (t) && integer_zerop (tmp))
/* Don't instantiate the THEN_CLAUSE. */;
else
- RECUR (THEN_CLAUSE (t));
+ {
+ bool inhibit = integer_zerop (fold_non_dependent_expr (tmp));
+ if (inhibit)
+ ++c_inhibit_evaluation_warnings;
+ RECUR (THEN_CLAUSE (t));
+ if (inhibit)
+ --c_inhibit_evaluation_warnings;
+ }
finish_then_clause (stmt);
if (IF_STMT_CONSTEXPR_P (t) && integer_nonzerop (tmp))
/* Don't instantiate the ELSE_CLAUSE. */;
else if (ELSE_CLAUSE (t))
{
+ bool inhibit = integer_nonzerop (fold_non_dependent_expr (tmp));
begin_else_clause (stmt);
+ if (inhibit)
+ ++c_inhibit_evaluation_warnings;
RECUR (ELSE_CLAUSE (t));
+ if (inhibit)
+ --c_inhibit_evaluation_warnings;
finish_else_clause (stmt);
}
@@ -15487,7 +15525,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
{
tree low = RECUR (CASE_LOW (t));
tree high = RECUR (CASE_HIGH (t));
- finish_case_label (EXPR_LOCATION (t), low, high);
+ tree l = finish_case_label (EXPR_LOCATION (t), low, high);
+ if (l && TREE_CODE (l) == CASE_LABEL_EXPR)
+ FALLTHROUGH_LABEL_P (CASE_LABEL (l))
+ = FALLTHROUGH_LABEL_P (CASE_LABEL (t));
}
break;
@@ -15497,6 +15538,8 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl,
tree label;
label = finish_label_stmt (DECL_NAME (decl));
+ if (TREE_CODE (label) == LABEL_DECL)
+ FALLTHROUGH_LABEL_P (label) = FALLTHROUGH_LABEL_P (decl);
if (DECL_ATTRIBUTES (decl) != NULL_TREE)
cplus_decl_attributes (&label, DECL_ATTRIBUTES (decl), 0);
}
@@ -17658,11 +17701,16 @@ instantiate_template_1 (tree tmpl, tree orig_args, tsubst_flags_t complain)
DECL_TI_ARGS (fndecl) = targ_ptr;
/* Now we know the specialization, compute access previously
- deferred. */
- push_access_scope (fndecl);
- if (!perform_deferred_access_checks (complain))
- access_ok = false;
- pop_access_scope (fndecl);
+ deferred. Do no access control for inheriting constructors,
+ as we already checked access for the inherited constructor. */
+ if (!(flag_new_inheriting_ctors
+ && DECL_INHERITED_CTOR (fndecl)))
+ {
+ push_access_scope (fndecl);
+ if (!perform_deferred_access_checks (complain))
+ access_ok = false;
+ pop_access_scope (fndecl);
+ }
pop_deferring_access_checks ();
/* If we've just instantiated the main entry point for a function,
@@ -17820,6 +17868,11 @@ fn_type_unification (tree fn,
static int deduction_depth;
struct pending_template *old_last_pend = last_pending_template;
struct tinst_level *old_error_tinst = last_error_tinst_level;
+
+ tree orig_fn = fn;
+ if (flag_new_inheriting_ctors)
+ fn = strip_inheriting_ctors (fn);
+
tree tparms = DECL_INNERMOST_TEMPLATE_PARMS (fn);
tree tinst;
tree r = error_mark_node;
@@ -17953,7 +18006,7 @@ fn_type_unification (tree fn,
access path at this point. */
push_deferring_access_checks (dk_deferred);
fntype = tsubst (TREE_TYPE (fn), explicit_targs,
- complain | tf_partial, NULL_TREE);
+ complain | tf_partial | tf_fndecl_type, NULL_TREE);
pop_deferring_access_checks ();
input_location = loc;
processing_template_decl -= incomplete;
@@ -18108,6 +18161,11 @@ fn_type_unification (tree fn,
}
}
+ /* After doing deduction with the inherited constructor, actually return an
+ instantiation of the inheriting constructor. */
+ if (orig_fn != fn)
+ decl = instantiate_template (orig_fn, targs, complain);
+
r = decl;
fail:
@@ -19315,7 +19373,7 @@ template_parm_level_and_index (tree parm, int* level, int* index)
do { \
if (unify (TP, TA, P, A, S, EP)) \
return 1; \
- } while (0);
+ } while (0)
/* Unifies the remaining arguments in PACKED_ARGS with the pack
expansion at the end of PACKED_PARMS. Returns 0 if the type
@@ -20273,6 +20331,11 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
class_of_this_parm (arg),
class_of_this_parm (parm))))
return unify_cv_qual_mismatch (explain_p, parm, arg);
+ if (TREE_CODE (arg) == FUNCTION_TYPE
+ && type_memfn_quals (parm) != type_memfn_quals (arg))
+ return unify_cv_qual_mismatch (explain_p, parm, arg);
+ if (type_memfn_rqual (parm) != type_memfn_rqual (arg))
+ return unify_type_mismatch (explain_p, parm, arg);
RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_TYPE (parm),
TREE_TYPE (arg), UNIFY_ALLOW_NONE, explain_p);
@@ -20285,9 +20348,27 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
args[i] = TREE_VALUE (a);
nargs = i;
- return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
- args, nargs, 1, DEDUCE_EXACT,
- LOOKUP_NORMAL, NULL, explain_p);
+ if (type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
+ args, nargs, 1, DEDUCE_EXACT,
+ LOOKUP_NORMAL, NULL, explain_p))
+ return 1;
+
+ if (flag_noexcept_type)
+ {
+ tree pspec = TYPE_RAISES_EXCEPTIONS (parm);
+ tree aspec = canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (arg));
+ if (pspec == NULL_TREE) pspec = noexcept_false_spec;
+ if (aspec == NULL_TREE) aspec = noexcept_false_spec;
+ if (TREE_PURPOSE (pspec) && TREE_PURPOSE (aspec)
+ && uses_template_parms (TREE_PURPOSE (pspec)))
+ RECUR_AND_CHECK_FAILURE (tparms, targs, TREE_PURPOSE (pspec),
+ TREE_PURPOSE (aspec),
+ UNIFY_ALLOW_NONE, explain_p);
+ else if (nothrow_spec_p (pspec) && !nothrow_spec_p (aspec))
+ return unify_type_mismatch (explain_p, parm, arg);
+ }
+
+ return 0;
}
case OFFSET_TYPE:
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index cfbc3d40680..247a98fc5e9 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -985,6 +985,14 @@ ptr_initializer (tinfo_s *ti, tree target)
flags |= 0x20;
to = tx_unsafe_fn_variant (to);
}
+ if (flag_noexcept_type
+ && (TREE_CODE (to) == FUNCTION_TYPE
+ || TREE_CODE (to) == METHOD_TYPE)
+ && TYPE_NOTHROW_P (to))
+ {
+ flags |= 0x40;
+ to = build_exception_variant (to, NULL_TREE);
+ }
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, init);
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE, build_int_cst (NULL_TREE, flags));
CONSTRUCTOR_APPEND_ELT (v, NULL_TREE,
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 03eef0030d0..7872dd29cf8 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1980,7 +1980,8 @@ static bool
cp_check_qualified_type (const_tree cand, const_tree base, int type_quals,
cp_ref_qualifier rqual, tree raises)
{
- return (check_qualified_type (cand, base, type_quals)
+ return (TYPE_QUALS (cand) == type_quals
+ && check_base_type (cand, base)
&& comp_except_specs (raises, TYPE_RAISES_EXCEPTIONS (cand),
ce_exact)
&& type_memfn_rqual (cand) == rqual);
@@ -2208,6 +2209,27 @@ cxx_printable_name_translate (tree decl, int v)
return cxx_printable_name_internal (decl, v, true);
}
+/* Return the canonical version of exception-specification RAISES for a C++17
+ function type, for use in type comparison and building TYPE_CANONICAL. */
+
+tree
+canonical_eh_spec (tree raises)
+{
+ if (raises == NULL_TREE)
+ return raises;
+ else if (DEFERRED_NOEXCEPT_SPEC_P (raises)
+ || uses_template_parms (raises)
+ || uses_template_parms (TREE_PURPOSE (raises)))
+ /* Keep a dependent or deferred exception specification. */
+ return raises;
+ else if (nothrow_spec_p (raises))
+ /* throw() -> noexcept. */
+ return noexcept_true_spec;
+ else
+ /* For C++17 type matching, anything else -> nothing. */
+ return NULL_TREE;
+}
+
/* Build the FUNCTION_TYPE or METHOD_TYPE which may throw exceptions
listed in RAISES. */
@@ -2229,6 +2251,25 @@ build_exception_variant (tree type, tree raises)
/* Need to build a new variant. */
v = build_variant_type_copy (type);
TYPE_RAISES_EXCEPTIONS (v) = raises;
+
+ if (!flag_noexcept_type)
+ /* The exception-specification is not part of the canonical type. */
+ return v;
+
+ /* Canonicalize the exception specification. */
+ tree cr = canonical_eh_spec (raises);
+
+ if (TYPE_STRUCTURAL_EQUALITY_P (type))
+ /* Propagate structural equality. */
+ SET_TYPE_STRUCTURAL_EQUALITY (v);
+ else if (TYPE_CANONICAL (type) != type || cr != raises)
+ /* Build the underlying canonical type, since it is different
+ from TYPE. */
+ TYPE_CANONICAL (v) = build_exception_variant (TYPE_CANONICAL (type), cr);
+ else
+ /* T is its own canonical type. */
+ TYPE_CANONICAL (v) = v;
+
return v;
}
@@ -4080,9 +4121,7 @@ cp_build_type_attribute_variant (tree type, tree attributes)
}
/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
- Called only after doing all language independent checks. Only
- to check TYPE_RAISES_EXCEPTIONS for FUNCTION_TYPE, the rest is already
- compared in type_hash_eq. */
+ Called only after doing all language independent checks. */
bool
cxx_type_hash_eq (const_tree typea, const_tree typeb)
@@ -4090,6 +4129,8 @@ cxx_type_hash_eq (const_tree typea, const_tree typeb)
gcc_assert (TREE_CODE (typea) == FUNCTION_TYPE
|| TREE_CODE (typea) == METHOD_TYPE);
+ if (type_memfn_rqual (typea) != type_memfn_rqual (typeb))
+ return false;
return comp_except_specs (TYPE_RAISES_EXCEPTIONS (typea),
TYPE_RAISES_EXCEPTIONS (typeb), ce_exact);
}
@@ -4282,7 +4323,7 @@ special_function_p (const_tree decl)
/* Rather than doing all this stuff with magic names, we should
probably have a field of type `special_function_kind' in
DECL_LANG_SPECIFIC. */
- if (DECL_INHERITED_CTOR_BASE (decl))
+ if (DECL_INHERITED_CTOR (decl))
return sfk_inheriting_constructor;
if (DECL_COPY_CONSTRUCTOR_P (decl))
return sfk_copy_constructor;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 569442f38ac..211696cf029 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -647,6 +647,14 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
return objc_common_type (t1, t2);
}
+ /* if T1 or T2 is "pointer to noexcept function" and the other type is
+ "pointer to function", where the function types are otherwise the same,
+ "pointer to function" */
+ if (fnptr_conv_p (t1, t2))
+ return t1;
+ if (fnptr_conv_p (t2, t1))
+ return t2;
+
/* [expr.eq] permits the application of a pointer conversion to
bring the pointers to a common type. */
if (TYPE_PTR_P (t1) && TYPE_PTR_P (t2)
@@ -710,22 +718,6 @@ composite_pointer_type (tree t1, tree t2, tree arg1, tree arg2,
return error_mark_node;
}
}
- else if (TYPE_PTR_P (t1) && TYPE_PTR_P (t2)
- && FUNC_OR_METHOD_TYPE_P (TREE_TYPE (t1))
- && TREE_CODE (TREE_TYPE (t2)) == TREE_CODE (TREE_TYPE (t1)))
- {
- /* ...if T1 is "pointer to transaction_safe function" and T2 is "pointer
- to function", where the function types are otherwise the same, T2, and
- vice versa.... */
- tree f1 = TREE_TYPE (t1);
- tree f2 = TREE_TYPE (t2);
- bool safe1 = tx_safe_fn_type_p (f1);
- bool safe2 = tx_safe_fn_type_p (f2);
- if (safe1 && !safe2)
- t1 = build_pointer_type (tx_unsafe_fn_variant (f1));
- else if (safe2 && !safe1)
- t2 = build_pointer_type (tx_unsafe_fn_variant (f2));
- }
return composite_pointer_type_r (t1, t2, operation, complain);
}
@@ -1020,6 +1012,7 @@ comp_except_types (tree a, tree b, bool exact)
/* Return true if TYPE1 and TYPE2 are equivalent exception specifiers.
If EXACT is ce_derived, T2 can be stricter than T1 (according to 15.4/5).
+ If EXACT is ce_type, the C++17 type compatibility rules apply.
If EXACT is ce_normal, the compatibility rules in 15.4/3 apply.
If EXACT is ce_exact, the specs must be exactly the same. Exception lists
are unordered, but we've already filtered out duplicates. Most lists will
@@ -1038,8 +1031,13 @@ comp_except_specs (const_tree t1, const_tree t2, int exact)
/* First handle noexcept. */
if (exact < ce_exact)
{
+ if (exact == ce_type
+ && (canonical_eh_spec (CONST_CAST_TREE (t1))
+ == canonical_eh_spec (CONST_CAST_TREE (t2))))
+ return true;
+
/* noexcept(false) is compatible with no exception-specification,
- and stricter than any spec. */
+ and less strict than any spec. */
if (t1 == noexcept_false_spec)
return t2 == NULL_TREE || exact == ce_derived;
/* Even a derived noexcept(false) is compatible with no
@@ -1222,10 +1220,17 @@ structural_comptypes (tree t1, tree t2, int strict)
return false;
/* Need to check this before TYPE_MAIN_VARIANT.
FIXME function qualifiers should really change the main variant. */
- if ((TREE_CODE (t1) == FUNCTION_TYPE
- || TREE_CODE (t1) == METHOD_TYPE)
- && type_memfn_rqual (t1) != type_memfn_rqual (t2))
- return false;
+ if (TREE_CODE (t1) == FUNCTION_TYPE
+ || TREE_CODE (t1) == METHOD_TYPE)
+ {
+ if (type_memfn_rqual (t1) != type_memfn_rqual (t2))
+ return false;
+ if (flag_noexcept_type
+ && !comp_except_specs (TYPE_RAISES_EXCEPTIONS (t1),
+ TYPE_RAISES_EXCEPTIONS (t2),
+ ce_type))
+ return false;
+ }
/* Allow for two different type nodes which have essentially the same
definition. Note that we already checked for equality of the type
@@ -1457,7 +1462,9 @@ same_type_ignoring_top_level_qualifiers_p (tree type1, tree type2)
if (type1 == error_mark_node || type2 == error_mark_node)
return false;
- return same_type_p (TYPE_MAIN_VARIANT (type1), TYPE_MAIN_VARIANT (type2));
+ type1 = cp_build_qualified_type (type1, TYPE_UNQUALIFIED);
+ type2 = cp_build_qualified_type (type2, TYPE_UNQUALIFIED);
+ return same_type_p (type1, type2);
}
/* Returns 1 if TYPE1 is at least as qualified as TYPE2. */
@@ -9227,13 +9234,6 @@ apply_memfn_quals (tree type, cp_cv_quals memfn_quals, cp_ref_qualifier rqual)
/* This should really have a different TYPE_MAIN_VARIANT, but that gets
complex. */
tree result = build_qualified_type (type, memfn_quals);
- if (tree canon = TYPE_CANONICAL (result))
- if (canon != result)
- /* check_qualified_type doesn't check the ref-qualifier, so make sure
- TYPE_CANONICAL is correct. */
- TYPE_CANONICAL (result)
- = build_ref_qualified_type (canon, type_memfn_rqual (result));
- result = build_exception_variant (result, TYPE_RAISES_EXCEPTIONS (type));
return build_ref_qualified_type (result, rqual);
}
diff --git a/gcc/cse.c b/gcc/cse.c
index 4b3cd2e1df4..11b8fbed06e 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -43,10 +43,6 @@ along with GCC; see the file COPYING3. If not see
#include "dbgcnt.h"
#include "rtl-iter.h"
-#ifndef LOAD_EXTEND_OP
-#define LOAD_EXTEND_OP(M) UNKNOWN
-#endif
-
/* The basic idea of common subexpression elimination is to go
through the code, keeping a record of expressions that would
have the same value at the current scan point, and replacing
diff --git a/gcc/dbgcnt.def b/gcc/dbgcnt.def
index 78ddcc2be8b..0a45bac279e 100644
--- a/gcc/dbgcnt.def
+++ b/gcc/dbgcnt.def
@@ -141,6 +141,7 @@ echo ubound: $ub
*/
/* Debug counter definitions. */
+DEBUG_COUNTER (asan_use_after_scope)
DEBUG_COUNTER (auto_inc_dec)
DEBUG_COUNTER (ccp)
DEBUG_COUNTER (cfg_cleanup)
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 74d41e72e0f..9c4000252a2 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -1259,6 +1259,10 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define WORD_REGISTER_OPERATIONS 0
#endif
+#ifndef LOAD_EXTEND_OP
+#define LOAD_EXTEND_OP(M) UNKNOWN
+#endif
+
#ifndef CONSTANT_ALIGNMENT
#define CONSTANT_ALIGNMENT(EXP, ALIGN) ALIGN
#endif
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 160bcb5177f..f06e2b8206d 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -199,6 +199,7 @@ in the following sections.
-fno-implicit-templates @gol
-fno-implicit-inline-templates @gol
-fno-implement-inlines -fms-extensions @gol
+-fnew-inheriting-ctors @gol
-fno-nonansi-builtins -fnothrow-opt -fno-operator-names @gol
-fno-optional-diags -fpermissive @gol
-fno-pretty-templates @gol
@@ -293,6 +294,7 @@ Objective-C and Objective-C++ Dialects}.
-Wpointer-arith -Wno-pointer-to-int-cast @gol
-Wno-pragmas -Wredundant-decls -Wno-return-local-addr @gol
-Wreturn-type -Wsequence-point -Wshadow -Wno-shadow-ivar @gol
+-Wshadow=global, -Wshadow=local, -Wshadow=compatible-local @gol
-Wshift-overflow -Wshift-overflow=@var{n} @gol
-Wshift-count-negative -Wshift-count-overflow -Wshift-negative-value @gol
-Wsign-compare -Wsign-conversion -Wfloat-conversion @gol
@@ -2219,6 +2221,10 @@ Version 10, which first appeared in G++ 6.1, adds mangling of
attributes that affect type identity, such as ia32 calling convention
attributes (e.g. @samp{stdcall}).
+Version 11, which first appeared in G++ 7, corrects the mangling of
+sizeof... expressions. It also implies
+@option{-fnew-inheriting-ctors}.
+
See also @option{-Wabi}.
@item -fabi-compat-version=@var{n}
@@ -2412,6 +2418,13 @@ errors if these functions are not inlined everywhere they are called.
Disable Wpedantic warnings about constructs used in MFC, such as implicit
int and getting a pointer to member function via non-standard syntax.
+@item -fnew-inheriting-ctors
+@opindex fnew-inheriting-ctors
+Enable the P0136 adjustment to the semantics of C++11 constructor
+inheritance. This is part of C++17 but also considered to be a Defect
+Report against C++11 and C++14. This flag is enabled by default
+unless @option{-fabi-version=10} or lower is specified.
+
@item -fno-nonansi-builtins
@opindex fno-nonansi-builtins
Disable built-in declarations of functions that are not mandated by
@@ -4984,8 +4997,10 @@ This option warns on all uses of @code{alloca} in the source.
@item -Walloca-larger-than=@var{n}
This option warns on calls to @code{alloca} that are not bounded by a
-controlling predicate limiting its size to @var{n} bytes, or calls to
-@code{alloca} where the bound is unknown.
+controlling predicate limiting its argument of integer type to at most
+@var{n} bytes, or calls to @code{alloca} where the bound is unknown.
+Arguments of non-integer types are considered unbounded even if they
+appear to be constrained to the expected range.
For example, a bounded case of @code{alloca} could be:
@@ -5001,13 +5016,13 @@ void func (size_t n)
@}
@end smallexample
-In the above example, passing @code{-Walloca=1000} would not issue a
-warning because the call to @code{alloca} is known to be at most 1000
-bytes. However, if @code{-Walloca=500} was passed, the compiler would
-have emitted a warning.
+In the above example, passing @code{-Walloca-larger-than=1000} would not
+issue a warning because the call to @code{alloca} is known to be at most
+1000 bytes. However, if @code{-Walloca-larger-than=500} were passed,
+the compiler would emit a warning.
Unbounded uses, on the other hand, are uses of @code{alloca} with no
-controlling predicate verifying its size. For example:
+controlling predicate constraining its integer argument. For example:
@smallexample
void func ()
@@ -5017,8 +5032,8 @@ void func ()
@}
@end smallexample
-If @code{-Walloca=500} was passed, the above would trigger a warning,
-but this time because of the lack of bounds checking.
+If @code{-Walloca-larger-than=500} were passed, the above would trigger
+a warning, but this time because of the lack of bounds checking.
Note, that even seemingly correct code involving signed integers could
cause a warning:
@@ -5035,7 +5050,7 @@ void func (signed int n)
@end smallexample
In the above example, @var{n} could be negative, causing a larger than
-expected argument to be implicitly casted into the @code{alloca} call.
+expected argument to be implicitly cast into the @code{alloca} call.
This option also warns when @code{alloca} is used in a loop.
@@ -5321,6 +5336,7 @@ variable, parameter, type, class member (in C++), or instance variable
(in Objective-C) or whenever a built-in function is shadowed. Note
that in C++, the compiler warns if a local variable shadows an
explicit typedef, but not if it shadows a struct/class/enum.
+Same as @option{-Wshadow=global}.
@item -Wno-shadow-ivar @r{(Objective-C only)}
@opindex Wno-shadow-ivar
@@ -5328,6 +5344,48 @@ explicit typedef, but not if it shadows a struct/class/enum.
Do not warn whenever a local variable shadows an instance variable in an
Objective-C method.
+@item -Wshadow=global
+@opindex Wshadow=local
+The default for @option{-Wshadow}. Warns for any (global) shadowing.
+
+@item -Wshadow=local
+@opindex Wshadow=local
+Warn when a local variable shadows another local variable or parameter.
+This warning is enabled by @option{-Wshadow=global}.
+
+@item -Wshadow=compatible-local
+@opindex Wshadow=compatible-local
+Warn when a local variable shadows another local variable or parameter
+whose type is compatible with that of the shadowing variable. In C++,
+type compatibility here means the type of the shadowing variable can be
+converted to that of the shadowed variable. The creation of this flag
+(in addition to @option{-Wshadow=local}) is based on the idea that when
+a local variable shadows another one of incompatible type, it is most
+likely intentional, not a bug or typo, as shown in the following example:
+
+@smallexample
+@group
+for (SomeIterator i = SomeObj.begin(); i != SomeObj.end(); ++i)
+@{
+ for (int i = 0; i < N; ++i)
+ @{
+ ...
+ @}
+ ...
+@}
+@end group
+@end smallexample
+
+Since the two variable @code{i} in the example above have incompatible types,
+enabling only @option{-Wshadow=compatible-local} will not emit a warning.
+Because their types are incompatible, if a programmer accidentally uses one
+in place of the other, type checking will catch that and emit an error or
+warning. So not warning (about shadowing) in this case will not lead to
+undetected bugs. Use of this flag instead of @option{-Wshadow=local} can
+possibly reduce the number of warnings triggered by intentional shadowing.
+
+This warning is enabled by @option{-Wshadow=local}.
+
@item -Wlarger-than=@var{len}
@opindex Wlarger-than=@var{len}
@opindex Wlarger-than-@var{len}
@@ -5516,6 +5574,11 @@ enabled by @option{-Wall}.
Warn about C++ constructs whose meaning differs between ISO C++ 2011
and ISO C++ 2014. This warning is enabled by @option{-Wall}.
+@item -Wc++1z-compat @r{(C++ and Objective-C++ only)}
+@opindex Wc++1z-compat
+Warn about C++ constructs whose meaning differs between ISO C++ 2014
+and the forthoming ISO C++ 2017(?). This warning is enabled by @option{-Wall}.
+
@item -Wcast-qual
@opindex Wcast-qual
@opindex Wno-cast-qual
@@ -10232,6 +10295,10 @@ is greater or equal to this number, use callbacks instead of inline checks.
E.g. to disable inline code use
@option{--param asan-instrumentation-with-call-threshold=0}.
+@item use-after-scope-direct-emission-threshold
+If size of a local variables in bytes is smaller of equal to this number,
+direct instruction emission is utilized to poison and unpoison local variables.
+
@item chkp-max-ctor-size
Static constructors generated by Pointer Bounds Checker may become very
large and significantly increase compile time at optimization level
@@ -10442,6 +10509,7 @@ thread-safe code.
Enable AddressSanitizer, a fast memory error detector.
Memory access instructions are instrumented to detect
out-of-bounds and use-after-free bugs.
+The option enables @option{-fsanitize-address-use-after-scope}.
See @uref{https://github.com/google/sanitizers/wiki/AddressSanitizer} for
more details. The run-time behavior can be influenced using the
@env{ASAN_OPTIONS} environment variable. When set to @code{help=1},
@@ -10453,6 +10521,7 @@ The option can't be combined with @option{-fsanitize=thread}.
@item -fsanitize=kernel-address
@opindex fsanitize=kernel-address
Enable AddressSanitizer for Linux kernel.
+The option enables @option{-fsanitize-address-use-after-scope}.
See @uref{https://github.com/google/kasan/wiki} for more details.
@item -fsanitize=thread
@@ -10652,8 +10721,8 @@ except for @option{-fsanitize=unreachable} and @option{-fsanitize=return}),
@option{-fsanitize=float-cast-overflow}, @option{-fsanitize=float-divide-by-zero},
@option{-fsanitize=bounds-strict},
@option{-fsanitize=kernel-address} and @option{-fsanitize=address}.
-For these sanitizers error recovery is turned on by default, except @option{-fsanitize=address},
-for which this feature is experimental.
+For these sanitizers error recovery is turned on by default,
+except @option{-fsanitize=address}, for which this feature is experimental.
@option{-fsanitize-recover=all} and @option{-fno-sanitize-recover=all} is also
accepted, the former enables recovery for all sanitizers that support it,
the latter disables recovery for all sanitizers that support it.
@@ -10675,6 +10744,11 @@ Similarly @option{-fno-sanitize-recover} is equivalent to
-fno-sanitize-recover=undefined,float-cast-overflow,float-divide-by-zero,bounds-strict
@end smallexample
+@item -fsanitize-address-use-after-scope
+@opindex fsanitize-address-use-after-scope
+Enable sanitization of local variables to detect use-after-scope bugs.
+The option sets @option{-fstack-reuse} to @samp{none}.
+
@item -fsanitize-undefined-trap-on-error
@opindex fsanitize-undefined-trap-on-error
The @option{-fsanitize-undefined-trap-on-error} option instructs the compiler to
@@ -14869,6 +14943,8 @@ Permissible names are: @samp{arm2}, @samp{arm250},
@samp{cortex-a32}, @samp{cortex-a35}, @samp{cortex-a53}, @samp{cortex-a57},
@samp{cortex-a72}, @samp{cortex-a73}, @samp{cortex-r4},
@samp{cortex-r4f}, @samp{cortex-r5}, @samp{cortex-r7}, @samp{cortex-r8},
+@samp{cortex-m33},
+@samp{cortex-m23},
@samp{cortex-m7},
@samp{cortex-m4},
@samp{cortex-m3},
diff --git a/gcc/doc/sourcebuild.texi b/gcc/doc/sourcebuild.texi
index 07c75e2847a..fb5dbb590c5 100644
--- a/gcc/doc/sourcebuild.texi
+++ b/gcc/doc/sourcebuild.texi
@@ -1675,6 +1675,10 @@ and @code{MOVT} instructions available.
ARM target generates Thumb-1 code for @code{-mthumb} with
@code{CBZ} and @code{CBNZ} instructions available.
+@item arm_divmod_simode
+ARM target for which divmod transform is disabled, if it supports hardware
+div instruction.
+
@end table
@subsubsection AArch64-specific attributes
@@ -1848,6 +1852,13 @@ Target requires a command line argument to enable a SIMD instruction set.
@item pie_copyreloc
The x86-64 target linker supports PIE with copy reloc.
+
+@item divmod
+Target supporting hardware divmod insn or divmod libcall.
+
+@item divmod_simode
+Target supporting hardware divmod insn or divmod libcall for SImode.
+
@end table
@subsubsection Environment attributes
@@ -2479,10 +2490,6 @@ The tests are organized by directory, each directory corresponding to
a chapter of the Ada Reference Manual. So for example, @file{c9} corresponds
to chapter 9, which deals with tasking features of the language.
-There is also an extra chapter called @file{gcc} containing a template for
-creating new executable tests, although this is deprecated in favor of
-the @file{gnat.dg} testsuite.
-
The tests are run using two @command{sh} scripts: @file{run_acats} and
@file{run_all.sh}. To run the tests using a simulator or a cross
target, see the small
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 6d0cbc3c40e..10122439c30 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -2903,6 +2903,10 @@ This hook defines a class of registers which could be used for spilling pseudos
This hook defines the machine mode to use for the boolean result of conditional store patterns. The ICODE argument is the instruction code for the cstore being performed. Not definiting this hook is the same as accepting the mode encoded into operand 0 of the cstore expander patterns.
@end deftypefn
+@deftypefn {Target Hook} int TARGET_COMPUTE_PRESSURE_CLASSES (enum reg_class *@var{pressure_classes})
+A target hook which lets a backend compute the set of pressure classes to be used by those optimization passes which take register pressure into account, as opposed to letting IRA compute them. It returns the number of register classes stored in the array @var{pressure_classes}.
+@end deftypefn
+
@node Stack and Calling
@section Stack Layout and Calling Conventions
@cindex calling conventions
@@ -7100,6 +7104,11 @@ This is firstly introduced on ARM/AArch64 targets, please refer to
the hook implementation for how different fusion types are supported.
@end deftypefn
+@deftypefn {Target Hook} void TARGET_EXPAND_DIVMOD_LIBFUNC (rtx @var{libfunc}, machine_mode @var{mode}, rtx @var{op0}, rtx @var{op1}, rtx *@var{quot}, rtx *@var{rem})
+Define this hook for enabling divmod transform if the port does not have
+hardware divmod insn but defines target-specific divmod libfuncs.
+@end deftypefn
+
@node Sections
@section Dividing the Output into Sections (Texts, Data, @dots{})
@c the above section title is WAY too long. maybe cut the part between
@@ -10622,6 +10631,23 @@ smaller than a word are always performed on the entire register.
Most RISC machines have this property and most CISC machines do not.
@end defmac
+@deftypefn {Target Hook} {unsigned int} TARGET_MIN_ARITHMETIC_PRECISION (void)
+On some RISC architectures with 64-bit registers, the processor also
+maintains 32-bit condition codes that make it possible to do real 32-bit
+arithmetic, although the operations are performed on the full registers.
+
+On such architectures, defining this hook to 32 tells the compiler to try
+using 32-bit arithmetical operations setting the condition codes instead
+of doing full 64-bit arithmetic.
+
+More generally, define this hook on RISC architectures if you want the
+compiler to try using arithmetical operations setting the condition codes
+with a precision lower than the word precision.
+
+You need not define this hook if @code{WORD_REGISTER_OPERATIONS} is not
+defined to 1.
+@end deftypefn
+
@defmac LOAD_EXTEND_OP (@var{mem_mode})
Define this macro to be a C expression indicating when insns that read
memory in @var{mem_mode}, an integral mode narrower than a word, set the
@@ -11532,7 +11558,7 @@ This target hook is required only when the target has several different
modes and they have different conditional execution capability, such as ARM.
@end deftypefn
-@deftypefn {Target Hook} rtx TARGET_GEN_CCMP_FIRST (rtx *@var{prep_seq}, rtx *@var{gen_seq}, int @var{code}, tree @var{op0}, tree @var{op1})
+@deftypefn {Target Hook} rtx TARGET_GEN_CCMP_FIRST (rtx_insn **@var{prep_seq}, rtx_insn **@var{gen_seq}, int @var{code}, tree @var{op0}, tree @var{op1})
This function prepares to emit a comparison insn for the first compare in a
sequence of conditional comparisions. It returns an appropriate comparison
with @code{CC} for passing to @code{gen_ccmp_next} or @code{cbranch_optab}.
@@ -11542,7 +11568,7 @@ This function prepares to emit a comparison insn for the first compare in a
@var{code} is the @code{rtx_code} of the compare for @var{op0} and @var{op1}.
@end deftypefn
-@deftypefn {Target Hook} rtx TARGET_GEN_CCMP_NEXT (rtx *@var{prep_seq}, rtx *@var{gen_seq}, rtx @var{prev}, int @var{cmp_code}, tree @var{op0}, tree @var{op1}, int @var{bit_code})
+@deftypefn {Target Hook} rtx TARGET_GEN_CCMP_NEXT (rtx_insn **@var{prep_seq}, rtx_insn **@var{gen_seq}, rtx @var{prev}, int @var{cmp_code}, tree @var{op0}, tree @var{op1}, int @var{bit_code})
This function prepares to emit a conditional comparison within a sequence
of conditional comparisons. It returns an appropriate comparison with
@code{CC} for passing to @code{gen_ccmp_next} or @code{cbranch_optab}.
@@ -11821,3 +11847,7 @@ All and all it does not take long to convert ports that the
maintainer is familiar with.
@end defmac
+
+@deftypefn {Target Hook} void TARGET_RUN_TARGET_SELFTESTS (void)
+If selftests are enabled, run any selftests for this target.
+@end deftypefn
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index b1fd50097bc..0a7eca32639 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -2509,6 +2509,8 @@ value that the middle-end intended.
@hook TARGET_CSTORE_MODE
+@hook TARGET_COMPUTE_PRESSURE_CLASSES
+
@node Stack and Calling
@section Stack Layout and Calling Conventions
@cindex calling conventions
@@ -4894,6 +4896,8 @@ them: try the first ones in this list first.
@hook TARGET_SCHED_FUSION_PRIORITY
+@hook TARGET_EXPAND_DIVMOD_LIBFUNC
+
@node Sections
@section Dividing the Output into Sections (Texts, Data, @dots{})
@c the above section title is WAY too long. maybe cut the part between
@@ -7577,6 +7581,8 @@ smaller than a word are always performed on the entire register.
Most RISC machines have this property and most CISC machines do not.
@end defmac
+@hook TARGET_MIN_ARITHMETIC_PRECISION
+
@defmac LOAD_EXTEND_OP (@var{mem_mode})
Define this macro to be a C expression indicating when insns that read
memory in @var{mem_mode}, an integral mode narrower than a word, set the
@@ -8307,3 +8313,5 @@ All and all it does not take long to convert ports that the
maintainer is familiar with.
@end defmac
+
+@hook TARGET_RUN_TARGET_SELFTESTS
diff --git a/gcc/dojump.c b/gcc/dojump.c
index 5a32c34aee6..e6ddf78898d 100644
--- a/gcc/dojump.c
+++ b/gcc/dojump.c
@@ -703,6 +703,7 @@ do_jump_by_parts_greater_rtx (machine_mode mode, int unsignedp, rtx op0,
if_false_label = drop_through_label;
drop_through_if_true = false;
drop_through_if_false = true;
+ prob = inv (prob);
}
/* Compare a word at a time, high order first. */
diff --git a/gcc/dse.c b/gcc/dse.c
index 95d5757140e..a7ae02200eb 100644
--- a/gcc/dse.c
+++ b/gcc/dse.c
@@ -3298,12 +3298,19 @@ dse_step5 (void)
bitmap_clear (v);
}
else if (insn_info->read_rec
- || insn_info->non_frame_wild_read)
+ || insn_info->non_frame_wild_read
+ || insn_info->frame_read)
{
- if (dump_file && !insn_info->non_frame_wild_read)
- fprintf (dump_file, "regular read\n");
- else if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "non-frame wild read\n");
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ if (!insn_info->non_frame_wild_read
+ && !insn_info->frame_read)
+ fprintf (dump_file, "regular read\n");
+ if (insn_info->non_frame_wild_read)
+ fprintf (dump_file, "non-frame wild read\n");
+ if (insn_info->frame_read)
+ fprintf (dump_file, "frame read\n");
+ }
scan_reads (insn_info, v, NULL);
}
}
diff --git a/gcc/dwarf2asm.c b/gcc/dwarf2asm.c
index 47335388500..2e0aae40827 100644
--- a/gcc/dwarf2asm.c
+++ b/gcc/dwarf2asm.c
@@ -825,7 +825,7 @@ static GTY(()) hash_map<const char *, tree> *indirect_pool;
static GTY(()) int dw2_const_labelno;
#if defined(HAVE_GAS_HIDDEN)
-# define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY)
+# define USE_LINKONCE_INDIRECT (SUPPORTS_ONE_ONLY && !XCOFF_DEBUGGING_INFO)
#else
# define USE_LINKONCE_INDIRECT 0
#endif
diff --git a/gcc/dwarf2cfi.c b/gcc/dwarf2cfi.c
index da9da52353e..b6e8b4b6c61 100644
--- a/gcc/dwarf2cfi.c
+++ b/gcc/dwarf2cfi.c
@@ -1236,7 +1236,7 @@ dwarf2out_frame_debug_cfa_register (rtx set)
reg_save (sregno, dregno, 0);
}
-/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_EXPRESSION note. */
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_EXPRESSION note. */
static void
dwarf2out_frame_debug_cfa_expression (rtx set)
@@ -1268,6 +1268,29 @@ dwarf2out_frame_debug_cfa_expression (rtx set)
update_row_reg_save (cur_row, regno, cfi);
}
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_VAL_EXPRESSION
+ note. */
+
+static void
+dwarf2out_frame_debug_cfa_val_expression (rtx set)
+{
+ rtx dest = SET_DEST (set);
+ gcc_assert (REG_P (dest));
+
+ rtx span = targetm.dwarf_register_span (dest);
+ gcc_assert (!span);
+
+ rtx src = SET_SRC (set);
+ dw_cfi_ref cfi = new_cfi ();
+ cfi->dw_cfi_opc = DW_CFA_val_expression;
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = dwf_regno (dest);
+ cfi->dw_cfi_oprnd2.dw_cfi_loc
+ = mem_loc_descriptor (src, GET_MODE (src),
+ GET_MODE (dest), VAR_INIT_STATUS_INITIALIZED);
+ add_cfi (cfi);
+ update_row_reg_save (cur_row, dwf_regno (dest), cfi);
+}
+
/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note. */
static void
@@ -2034,10 +2057,16 @@ dwarf2out_frame_debug (rtx_insn *insn)
break;
case REG_CFA_EXPRESSION:
+ case REG_CFA_VAL_EXPRESSION:
n = XEXP (note, 0);
if (n == NULL)
n = single_set (insn);
- dwarf2out_frame_debug_cfa_expression (n);
+
+ if (REG_NOTE_KIND (note) == REG_CFA_EXPRESSION)
+ dwarf2out_frame_debug_cfa_expression (n);
+ else
+ dwarf2out_frame_debug_cfa_val_expression (n);
+
handled_one = true;
break;
@@ -3016,7 +3045,8 @@ output_cfa_loc (dw_cfi_ref cfi, int for_eh)
dw_loc_descr_ref loc;
unsigned long size;
- if (cfi->dw_cfi_opc == DW_CFA_expression)
+ if (cfi->dw_cfi_opc == DW_CFA_expression
+ || cfi->dw_cfi_opc == DW_CFA_val_expression)
{
unsigned r =
DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, for_eh);
@@ -3042,7 +3072,8 @@ output_cfa_loc_raw (dw_cfi_ref cfi)
dw_loc_descr_ref loc;
unsigned long size;
- if (cfi->dw_cfi_opc == DW_CFA_expression)
+ if (cfi->dw_cfi_opc == DW_CFA_expression
+ || cfi->dw_cfi_opc == DW_CFA_val_expression)
{
unsigned r =
DWARF2_FRAME_REG_OUT (cfi->dw_cfi_oprnd1.dw_cfi_reg_num, 1);
@@ -3189,6 +3220,7 @@ output_cfi (dw_cfi_ref cfi, dw_fde_ref fde, int for_eh)
case DW_CFA_def_cfa_expression:
case DW_CFA_expression:
+ case DW_CFA_val_expression:
output_cfa_loc (cfi, for_eh);
break;
@@ -3303,16 +3335,13 @@ output_cfi_directive (FILE *f, dw_cfi_ref cfi)
break;
case DW_CFA_def_cfa_expression:
- if (f != asm_out_file)
- {
- fprintf (f, "\t.cfi_def_cfa_expression ...\n");
- break;
- }
- /* FALLTHRU */
case DW_CFA_expression:
+ case DW_CFA_val_expression:
if (f != asm_out_file)
{
- fprintf (f, "\t.cfi_cfa_expression ...\n");
+ fprintf (f, "\t.cfi_%scfa_%sexpression ...\n",
+ cfi->dw_cfi_opc == DW_CFA_def_cfa_expression ? "def_" : "",
+ cfi->dw_cfi_opc == DW_CFA_val_expression ? "val_" : "");
break;
}
fprintf (f, "\t.cfi_escape %#x,", cfi->dw_cfi_opc);
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 78a29799564..1dfff38a862 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -167,6 +167,7 @@ static GTY(()) section *debug_loc_section;
static GTY(()) section *debug_pubnames_section;
static GTY(()) section *debug_pubtypes_section;
static GTY(()) section *debug_str_section;
+static GTY(()) section *debug_line_str_section;
static GTY(()) section *debug_str_dwo_section;
static GTY(()) section *debug_str_offsets_section;
static GTY(()) section *debug_ranges_section;
@@ -225,6 +226,8 @@ struct indirect_string_hasher : ggc_ptr_hash<indirect_string_node>
static GTY (()) hash_table<indirect_string_hasher> *debug_str_hash;
+static GTY (()) hash_table<indirect_string_hasher> *debug_line_str_hash;
+
/* With split_debug_info, both the comp_dir and dwo_name go in the
main object file, rather than the dwo, similar to the force_direct
parameter elsewhere but with additional complications:
@@ -232,8 +235,8 @@ static GTY (()) hash_table<indirect_string_hasher> *debug_str_hash;
1) The string is needed in both the main object file and the dwo.
That is, the comp_dir and dwo_name will appear in both places.
- 2) Strings can use three forms: DW_FORM_string, DW_FORM_strp or
- DW_FORM_GNU_str_index.
+ 2) Strings can use four forms: DW_FORM_string, DW_FORM_strp,
+ DW_FORM_line_strp or DW_FORM_GNU_str_index.
3) GCC chooses the form to use late, depending on the size and
reference count.
@@ -274,6 +277,9 @@ static void dwarf2out_note_section_used (void);
personality CFI. */
static GTY(()) rtx current_unit_personality;
+/* .debug_rnglists next index. */
+static unsigned int rnglist_idx;
+
/* Data and reference forms for relocatable data. */
#define DW_FORM_data (DWARF_OFFSET_SIZE == 8 ? DW_FORM_data8 : DW_FORM_data4)
#define DW_FORM_ref (DWARF_OFFSET_SIZE == 8 ? DW_FORM_ref8 : DW_FORM_ref4)
@@ -519,6 +525,7 @@ dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi)
case DW_CFA_def_cfa_register:
case DW_CFA_register:
case DW_CFA_expression:
+ case DW_CFA_val_expression:
return dw_cfi_oprnd_reg_num;
case DW_CFA_def_cfa_offset:
@@ -552,6 +559,7 @@ dw_cfi_oprnd2_desc (enum dwarf_call_frame_info cfi)
return dw_cfi_oprnd_reg_num;
case DW_CFA_expression:
+ case DW_CFA_val_expression:
return dw_cfi_oprnd_loc;
default:
@@ -1276,7 +1284,13 @@ typedef struct GTY(()) dw_loc_list_struct {
bool resolved_addr;
/* True if this list has been replaced by dw_loc_next. */
bool replaced;
- bool emitted;
+ /* True if it has been emitted into .debug_loc* / .debug_loclists*
+ section. */
+ unsigned char emitted : 1;
+ /* True if hash field is index rather than hash value. */
+ unsigned char num_assigned : 1;
+ /* True if .debug_loclists.dwo offset has been emitted for it already. */
+ unsigned char offset_emitted : 1;
/* True if the range should be emitted even if begin and end
are the same. */
bool force;
@@ -1363,9 +1377,9 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b)
case dw_val_class_offset:
case dw_val_class_unsigned_const:
case dw_val_class_const:
+ case dw_val_class_unsigned_const_implicit:
+ case dw_val_class_const_implicit:
case dw_val_class_range_list:
- case dw_val_class_lineptr:
- case dw_val_class_macptr:
/* These are all HOST_WIDE_INT, signed or unsigned. */
return a->v.val_unsigned == b->v.val_unsigned;
@@ -1378,6 +1392,9 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b)
case dw_val_class_fde_ref:
return a->v.val_fde_index == b->v.val_fde_index;
case dw_val_class_lbl_id:
+ case dw_val_class_lineptr:
+ case dw_val_class_macptr:
+ case dw_val_class_loclistsptr:
case dw_val_class_high_pc:
return strcmp (a->v.val_lbl_id, b->v.val_lbl_id) == 0;
case dw_val_class_str:
@@ -1385,6 +1402,7 @@ dw_val_equal_p (dw_val_node *a, dw_val_node *b)
case dw_val_class_flag:
return a->v.val_flag == b->v.val_flag;
case dw_val_class_file:
+ case dw_val_class_file_implicit:
return a->v.val_file == b->v.val_file;
case dw_val_class_decl_ref:
return a->v.val_decl_ref == b->v.val_decl_ref;
@@ -1514,6 +1532,149 @@ loc_list_plus_const (dw_loc_list_ref list_head, HOST_WIDE_INT offset)
#define DWARF_REF_SIZE \
(dwarf_version == 2 ? DWARF2_ADDR_SIZE : DWARF_OFFSET_SIZE)
+/* The number of bits that can be encoded by largest DW_FORM_dataN.
+ In DWARF4 and earlier it is DW_FORM_data8 with 64 bits, in DWARF5
+ DW_FORM_data16 with 128 bits. */
+#define DWARF_LARGEST_DATA_FORM_BITS \
+ (dwarf_version >= 5 ? 128 : 64)
+
+/* Utility inline function for construction of ops that were GNU extension
+ before DWARF 5. */
+static inline enum dwarf_location_atom
+dwarf_OP (enum dwarf_location_atom op)
+{
+ switch (op)
+ {
+ case DW_OP_implicit_pointer:
+ if (dwarf_version < 5)
+ return DW_OP_GNU_implicit_pointer;
+ break;
+
+ case DW_OP_entry_value:
+ if (dwarf_version < 5)
+ return DW_OP_GNU_entry_value;
+ break;
+
+ case DW_OP_const_type:
+ if (dwarf_version < 5)
+ return DW_OP_GNU_const_type;
+ break;
+
+ case DW_OP_regval_type:
+ if (dwarf_version < 5)
+ return DW_OP_GNU_regval_type;
+ break;
+
+ case DW_OP_deref_type:
+ if (dwarf_version < 5)
+ return DW_OP_GNU_deref_type;
+ break;
+
+ case DW_OP_convert:
+ if (dwarf_version < 5)
+ return DW_OP_GNU_convert;
+ break;
+
+ case DW_OP_reinterpret:
+ if (dwarf_version < 5)
+ return DW_OP_GNU_reinterpret;
+ break;
+
+ default:
+ break;
+ }
+ return op;
+}
+
+/* Similarly for attributes. */
+static inline enum dwarf_attribute
+dwarf_AT (enum dwarf_attribute at)
+{
+ switch (at)
+ {
+ case DW_AT_call_return_pc:
+ if (dwarf_version < 5)
+ return DW_AT_low_pc;
+ break;
+
+ case DW_AT_call_tail_call:
+ if (dwarf_version < 5)
+ return DW_AT_GNU_tail_call;
+ break;
+
+ case DW_AT_call_origin:
+ if (dwarf_version < 5)
+ return DW_AT_abstract_origin;
+ break;
+
+ case DW_AT_call_target:
+ if (dwarf_version < 5)
+ return DW_AT_GNU_call_site_target;
+ break;
+
+ case DW_AT_call_target_clobbered:
+ if (dwarf_version < 5)
+ return DW_AT_GNU_call_site_target_clobbered;
+ break;
+
+ case DW_AT_call_parameter:
+ if (dwarf_version < 5)
+ return DW_AT_abstract_origin;
+ break;
+
+ case DW_AT_call_value:
+ if (dwarf_version < 5)
+ return DW_AT_GNU_call_site_value;
+ break;
+
+ case DW_AT_call_data_value:
+ if (dwarf_version < 5)
+ return DW_AT_GNU_call_site_data_value;
+ break;
+
+ case DW_AT_call_all_calls:
+ if (dwarf_version < 5)
+ return DW_AT_GNU_all_call_sites;
+ break;
+
+ case DW_AT_call_all_tail_calls:
+ if (dwarf_version < 5)
+ return DW_AT_GNU_all_tail_call_sites;
+ break;
+
+ case DW_AT_dwo_name:
+ if (dwarf_version < 5)
+ return DW_AT_GNU_dwo_name;
+ break;
+
+ default:
+ break;
+ }
+ return at;
+}
+
+/* And similarly for tags. */
+static inline enum dwarf_tag
+dwarf_TAG (enum dwarf_tag tag)
+{
+ switch (tag)
+ {
+ case DW_TAG_call_site:
+ if (dwarf_version < 5)
+ return DW_TAG_GNU_call_site;
+ break;
+
+ case DW_TAG_call_site_parameter:
+ if (dwarf_version < 5)
+ return DW_TAG_GNU_call_site_parameter;
+ break;
+
+ default:
+ break;
+ }
+ return tag;
+}
+
static unsigned long int get_base_type_offset (dw_die_ref);
/* Return the size of a location descriptor. */
@@ -1633,15 +1794,18 @@ size_of_loc_descr (dw_loc_descr_ref loc)
size += size_of_uleb128 (loc->dw_loc_oprnd1.v.val_unsigned)
+ loc->dw_loc_oprnd1.v.val_unsigned;
break;
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
size += DWARF_REF_SIZE + size_of_sleb128 (loc->dw_loc_oprnd2.v.val_int);
break;
+ case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
{
unsigned long op_size = size_of_locs (loc->dw_loc_oprnd1.v.val_loc);
size += size_of_uleb128 (op_size) + op_size;
break;
}
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
{
unsigned long o
@@ -1668,6 +1832,7 @@ size_of_loc_descr (dw_loc_descr_ref loc)
}
break;
}
+ case DW_OP_regval_type:
case DW_OP_GNU_regval_type:
{
unsigned long o
@@ -1676,6 +1841,7 @@ size_of_loc_descr (dw_loc_descr_ref loc)
+ size_of_uleb128 (o);
}
break;
+ case DW_OP_deref_type:
case DW_OP_GNU_deref_type:
{
unsigned long o
@@ -1683,6 +1849,8 @@ size_of_loc_descr (dw_loc_descr_ref loc)
size += 1 + size_of_uleb128 (o);
}
break;
+ case DW_OP_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_convert:
case DW_OP_GNU_reinterpret:
if (loc->dw_loc_oprnd1.val_class == dw_val_class_unsigned_const)
@@ -2043,6 +2211,7 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
}
break;
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
{
char label[MAX_ARTIFICIAL_LABEL_BYTES
@@ -2054,11 +2223,13 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
}
break;
+ case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
dw2_asm_output_data_uleb128 (size_of_locs (val1->v.val_loc), NULL);
output_loc_sequence (val1->v.val_loc, for_eh_or_skip);
break;
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
{
unsigned long o = get_base_type_offset (val1->v.val_die_ref.die), l;
@@ -2132,6 +2303,7 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
}
}
break;
+ case DW_OP_regval_type:
case DW_OP_GNU_regval_type:
{
unsigned r = val1->v.val_unsigned;
@@ -2147,6 +2319,7 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
dw2_asm_output_data_uleb128 (o, NULL);
}
break;
+ case DW_OP_deref_type:
case DW_OP_GNU_deref_type:
{
unsigned long o = get_base_type_offset (val2->v.val_die_ref.die);
@@ -2155,6 +2328,8 @@ output_loc_operands (dw_loc_descr_ref loc, int for_eh_or_skip)
dw2_asm_output_data_uleb128 (o, NULL);
}
break;
+ case DW_OP_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_convert:
case DW_OP_GNU_reinterpret:
if (loc->dw_loc_oprnd1.val_class == dw_val_class_unsigned_const)
@@ -2353,6 +2528,13 @@ output_loc_operands_raw (dw_loc_descr_ref loc)
}
break;
+ case DW_OP_implicit_pointer:
+ case DW_OP_entry_value:
+ case DW_OP_const_type:
+ case DW_OP_regval_type:
+ case DW_OP_deref_type:
+ case DW_OP_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_implicit_pointer:
case DW_OP_GNU_entry_value:
case DW_OP_GNU_const_type:
@@ -2589,7 +2771,8 @@ const struct gcc_debug_hooks dwarf2_lineno_debug_hooks =
-fno-debug-types-section. It is more efficient to put them in a
separate comdat sections since the linker will then be able to
remove duplicates. But not all tools support .debug_types sections
- yet. */
+ yet. For Dwarf V5 or higher .debug_types doesn't exist any more,
+ it is DW_UT_type unit type in .debug_info section. */
#define use_debug_types (dwarf_version >= 4 && flag_debug_types_section)
@@ -2729,9 +2912,15 @@ pubname_entry;
struct GTY(()) dw_ranges {
+ const char *label;
/* If this is positive, it's a block number, otherwise it's a
bitwise-negated index into dw_ranges_by_label. */
int num;
+ /* Index for the range list for DW_FORM_rnglistx. */
+ unsigned int idx : 31;
+ /* True if this range might be possibly in a different section
+ from previous entry. */
+ unsigned int maybe_new_sec : 1;
};
/* A structure to hold a macinfo entry. */
@@ -2805,12 +2994,15 @@ skeleton_chain_node;
/* Fixed size portion of the DWARF compilation unit header. */
#define DWARF_COMPILE_UNIT_HEADER_SIZE \
- (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE + 3)
+ (DWARF_INITIAL_LENGTH_SIZE + DWARF_OFFSET_SIZE \
+ + (dwarf_version >= 5 \
+ ? 4 + DWARF_TYPE_SIGNATURE_SIZE + DWARF_OFFSET_SIZE : 3))
/* Fixed size portion of the DWARF comdat type unit header. */
#define DWARF_COMDAT_TYPE_UNIT_HEADER_SIZE \
- (DWARF_COMPILE_UNIT_HEADER_SIZE + DWARF_TYPE_SIGNATURE_SIZE \
- + DWARF_OFFSET_SIZE)
+ (DWARF_COMPILE_UNIT_HEADER_SIZE \
+ + (dwarf_version >= 5 \
+ ? 0 : DWARF_TYPE_SIGNATURE_SIZE + DWARF_OFFSET_SIZE))
/* Fixed size portion of public names info. */
#define DWARF_PUBNAMES_HEADER_SIZE (2 * DWARF_OFFSET_SIZE + 2)
@@ -3006,17 +3198,9 @@ struct dw_loc_list_hasher : ggc_ptr_hash<cached_dw_loc_list>
/* Table of cached location lists. */
static GTY (()) hash_table<dw_loc_list_hasher> *cached_dw_loc_list_table;
-/* A pointer to the base of a list of references to DIE's that
- are uniquely identified by their tag, presence/absence of
- children DIE's, and list of attribute/value pairs. */
-static GTY((length ("abbrev_die_table_allocated")))
- dw_die_ref *abbrev_die_table;
-
-/* Number of elements currently allocated for abbrev_die_table. */
-static GTY(()) unsigned abbrev_die_table_allocated;
-
-/* Number of elements in abbrev_die_table currently in use. */
-static GTY(()) unsigned abbrev_die_table_in_use;
+/* A vector of references to DIE's that are uniquely identified by their tag,
+ presence/absence of children DIE's, and list of attribute/value pairs. */
+static GTY(()) vec<dw_die_ref, va_gc> *abbrev_die_table;
/* A hash map to remember the stack usage for DWARF procedures. The value
stored is the stack size difference between before the DWARF procedure
@@ -3024,10 +3208,6 @@ static GTY(()) unsigned abbrev_die_table_in_use;
that consumes N stack slots and that pushes M ones, this stores M - N. */
static hash_map<dw_die_ref, int> *dwarf_proc_stack_usage_map;
-/* Size (in elements) of increments by which we may expand the
- abbrev_die_table. */
-#define ABBREV_DIE_TABLE_INCREMENT 256
-
/* A global counter for generating labels for line number data. */
static unsigned int line_info_label_num;
@@ -3160,6 +3340,8 @@ static inline rtx AT_addr (dw_attr_node *);
static void add_AT_lbl_id (dw_die_ref, enum dwarf_attribute, const char *);
static void add_AT_lineptr (dw_die_ref, enum dwarf_attribute, const char *);
static void add_AT_macptr (dw_die_ref, enum dwarf_attribute, const char *);
+static void add_AT_loclistsptr (dw_die_ref, enum dwarf_attribute,
+ const char *);
static void add_AT_offset (dw_die_ref, enum dwarf_attribute,
unsigned HOST_WIDE_INT);
static void add_AT_range_list (dw_die_ref, enum dwarf_attribute,
@@ -3248,8 +3430,8 @@ static void output_abbrev_section (void);
static void output_die_abbrevs (unsigned long, dw_die_ref);
static void output_die_symbol (dw_die_ref);
static void output_die (dw_die_ref);
-static void output_compilation_unit_header (void);
-static void output_comp_unit (dw_die_ref, int);
+static void output_compilation_unit_header (enum dwarf_unit_type);
+static void output_comp_unit (dw_die_ref, int, const unsigned char *);
static void output_comdat_type_unit (comdat_type_node *);
static const char *dwarf2_name (tree, int);
static void add_pubname (tree, dw_die_ref);
@@ -3258,8 +3440,7 @@ static void add_pubname_string (const char *, dw_die_ref);
static void add_pubtype (tree, dw_die_ref);
static void output_pubnames (vec<pubname_entry, va_gc> *);
static void output_aranges (void);
-static unsigned int add_ranges_num (int);
-static unsigned int add_ranges (const_tree);
+static unsigned int add_ranges (const_tree, bool = false);
static void add_ranges_by_labels (dw_die_ref, const char *, const char *,
bool *, bool);
static void output_ranges (void);
@@ -3293,9 +3474,9 @@ struct loc_descr_context;
static void add_loc_descr_to_each (dw_loc_list_ref list, dw_loc_descr_ref ref);
static void add_loc_list (dw_loc_list_ref *ret, dw_loc_list_ref list);
static dw_loc_list_ref loc_list_from_tree (tree, int,
- const struct loc_descr_context *);
+ struct loc_descr_context *);
static dw_loc_descr_ref loc_descriptor_from_tree (tree, int,
- const struct loc_descr_context *);
+ struct loc_descr_context *);
static HOST_WIDE_INT ceiling (HOST_WIDE_INT, unsigned int);
static tree field_type (const_tree);
static unsigned int simple_type_align_in_bits (const_tree);
@@ -3320,9 +3501,9 @@ static void add_name_attribute (dw_die_ref, const char *);
static void add_gnat_descriptive_type_attribute (dw_die_ref, tree, dw_die_ref);
static void add_comp_dir_attribute (dw_die_ref);
static void add_scalar_info (dw_die_ref, enum dwarf_attribute, tree, int,
- const struct loc_descr_context *);
+ struct loc_descr_context *);
static void add_bound_info (dw_die_ref, enum dwarf_attribute, tree,
- const struct loc_descr_context *);
+ struct loc_descr_context *);
static void add_subscript_info (dw_die_ref, tree, bool);
static void add_byte_size_attribute (dw_die_ref, tree);
static inline void add_bit_offset_attribute (dw_die_ref, tree,
@@ -3332,7 +3513,7 @@ static void add_prototyped_attribute (dw_die_ref, tree);
static dw_die_ref add_abstract_origin_attribute (dw_die_ref, tree);
static void add_pure_or_virtual_attribute (dw_die_ref, tree);
static void add_src_coords_attributes (dw_die_ref, tree);
-static void add_name_and_src_coords_attributes (dw_die_ref, tree);
+static void add_name_and_src_coords_attributes (dw_die_ref, tree, bool = false);
static void add_discr_value (dw_die_ref, dw_discr_value *);
static void add_discr_list (dw_die_ref, dw_discr_list_ref);
static inline dw_discr_list_ref AT_discr_list (dw_attr_node *);
@@ -3460,8 +3641,8 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel)
ref->dtprel = dtprel;
if (dwarf_split_debug_info)
ref->dw_loc_oprnd1.val_entry
- = add_addr_table_entry (addr,
- dtprel ? ate_kind_rtx_dtprel : ate_kind_rtx);
+ = add_addr_table_entry (addr,
+ dtprel ? ate_kind_rtx_dtprel : ate_kind_rtx);
else
ref->dw_loc_oprnd1.val_entry = NULL;
@@ -3512,6 +3693,12 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel)
#ifndef DEBUG_DWO_LOC_SECTION
#define DEBUG_DWO_LOC_SECTION ".debug_loc.dwo"
#endif
+#ifndef DEBUG_LOCLISTS_SECTION
+#define DEBUG_LOCLISTS_SECTION ".debug_loclists"
+#endif
+#ifndef DEBUG_DWO_LOCLISTS_SECTION
+#define DEBUG_DWO_LOCLISTS_SECTION ".debug_loclists.dwo"
+#endif
#ifndef DEBUG_PUBNAMES_SECTION
#define DEBUG_PUBNAMES_SECTION \
((debug_generate_pub_sections == 2) \
@@ -3537,6 +3724,12 @@ new_addr_loc_descr (rtx addr, enum dtprel_bool dtprel)
#ifndef DEBUG_RANGES_SECTION
#define DEBUG_RANGES_SECTION ".debug_ranges"
#endif
+#ifndef DEBUG_RNGLISTS_SECTION
+#define DEBUG_RNGLISTS_SECTION ".debug_rnglists"
+#endif
+#ifndef DEBUG_LINE_STR_SECTION
+#define DEBUG_LINE_STR_SECTION ".debug_line_str"
+#endif
/* Standard ELF section names for compiled code and data. */
#ifndef TEXT_SECTION_NAME
@@ -3617,6 +3810,7 @@ static char debug_skeleton_line_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char macinfo_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char loc_section_label[MAX_ARTIFICIAL_LABEL_BYTES];
static char ranges_section_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
+static char ranges_base_label[2 * MAX_ARTIFICIAL_LABEL_BYTES];
#ifndef TEXT_END_LABEL
#define TEXT_END_LABEL "Letext"
@@ -3905,7 +4099,8 @@ add_AT_int (dw_die_ref die, enum dwarf_attribute attr_kind, HOST_WIDE_INT int_va
static inline HOST_WIDE_INT
AT_int (dw_attr_node *a)
{
- gcc_assert (a && AT_class (a) == dw_val_class_const);
+ gcc_assert (a && (AT_class (a) == dw_val_class_const
+ || AT_class (a) == dw_val_class_const_implicit));
return a->dw_attr_val.v.val_int;
}
@@ -3927,7 +4122,8 @@ add_AT_unsigned (dw_die_ref die, enum dwarf_attribute attr_kind,
static inline unsigned HOST_WIDE_INT
AT_unsigned (dw_attr_node *a)
{
- gcc_assert (a && AT_class (a) == dw_val_class_unsigned_const);
+ gcc_assert (a && (AT_class (a) == dw_val_class_unsigned_const
+ || AT_class (a) == dw_val_class_unsigned_const_implicit));
return a->dw_attr_val.v.val_unsigned;
}
@@ -4013,7 +4209,7 @@ add_AT_low_high_pc (dw_die_ref die, const char *lbl_low, const char *lbl_high,
attr.dw_attr_val.v.val_lbl_id = lbl_id;
if (dwarf_split_debug_info && !force_direct)
attr.dw_attr_val.val_entry
- = add_addr_table_entry (lbl_id, ate_kind_label);
+ = add_addr_table_entry (lbl_id, ate_kind_label);
else
attr.dw_attr_val.val_entry = NULL;
add_dwarf_attr (die, &attr);
@@ -4028,7 +4224,7 @@ add_AT_low_high_pc (dw_die_ref die, const char *lbl_low, const char *lbl_high,
if (attr.dw_attr_val.val_class == dw_val_class_lbl_id
&& dwarf_split_debug_info && !force_direct)
attr.dw_attr_val.val_entry
- = add_addr_table_entry (lbl_id, ate_kind_label);
+ = add_addr_table_entry (lbl_id, ate_kind_label);
else
attr.dw_attr_val.val_entry = NULL;
add_dwarf_attr (die, &attr);
@@ -4114,7 +4310,9 @@ set_indirect_string (struct indirect_string_node *node)
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
/* Already indirect is a no op. */
- if (node->form == DW_FORM_strp || node->form == DW_FORM_GNU_str_index)
+ if (node->form == DW_FORM_strp
+ || node->form == DW_FORM_line_strp
+ || node->form == DW_FORM_GNU_str_index)
{
gcc_assert (node->label);
return;
@@ -4158,7 +4356,7 @@ find_string_form (struct indirect_string_node *node)
single module. */
if (DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET
|| ((debug_str_section->common.flags & SECTION_MERGE) == 0
- && (len - DWARF_OFFSET_SIZE) * node->refcount <= len))
+ && (len - DWARF_OFFSET_SIZE) * node->refcount <= len))
return node->form = DW_FORM_string;
set_indirect_string (node);
@@ -4506,7 +4704,8 @@ add_AT_file (dw_die_ref die, enum dwarf_attribute attr_kind,
static inline struct dwarf_file_data *
AT_file (dw_attr_node *a)
{
- gcc_assert (a && AT_class (a) == dw_val_class_file);
+ gcc_assert (a && (AT_class (a) == dw_val_class_file
+ || AT_class (a) == dw_val_class_file_implicit));
return a->dw_attr_val.v.val_file;
}
@@ -4562,6 +4761,22 @@ add_AT_lineptr (dw_die_ref die, enum dwarf_attribute attr_kind,
}
/* Add a section offset attribute value to a DIE, an offset into the
+ debug_loclists section. */
+
+static inline void
+add_AT_loclistsptr (dw_die_ref die, enum dwarf_attribute attr_kind,
+ const char *label)
+{
+ dw_attr_node attr;
+
+ attr.dw_attr = attr_kind;
+ attr.dw_attr_val.val_class = dw_val_class_loclistsptr;
+ attr.dw_attr_val.val_entry = NULL;
+ attr.dw_attr_val.v.val_lbl_id = xstrdup (label);
+ add_dwarf_attr (die, &attr);
+}
+
+/* Add a section offset attribute value to a DIE, an offset into the
debug_macinfo section. */
static inline void
@@ -4643,6 +4858,7 @@ AT_lbl (dw_attr_node *a)
gcc_assert (a && (AT_class (a) == dw_val_class_lbl_id
|| AT_class (a) == dw_val_class_lineptr
|| AT_class (a) == dw_val_class_macptr
+ || AT_class (a) == dw_val_class_loclistsptr
|| AT_class (a) == dw_val_class_high_pc));
return a->dw_attr_val.v.val_lbl_id;
}
@@ -5020,6 +5236,7 @@ new_die (enum dwarf_tag tag_value, dw_die_ref parent_die, tree t)
/* These are allowed because they're generated while
breaking out COMDAT units late. */
&& tag_value != DW_TAG_type_unit
+ && tag_value != DW_TAG_skeleton_unit
&& !early_dwarf
/* Allow nested functions to live in limbo because they will
only temporarily live there, as decls_for_scope will fix
@@ -5581,9 +5798,11 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
fprintf (outfile, "range list");
break;
case dw_val_class_const:
+ case dw_val_class_const_implicit:
fprintf (outfile, HOST_WIDE_INT_PRINT_DEC, val->v.val_int);
break;
case dw_val_class_unsigned_const:
+ case dw_val_class_unsigned_const_implicit:
fprintf (outfile, HOST_WIDE_INT_PRINT_UNSIGNED, val->v.val_unsigned);
break;
case dw_val_class_const_double:
@@ -5640,6 +5859,7 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
case dw_val_class_lbl_id:
case dw_val_class_lineptr:
case dw_val_class_macptr:
+ case dw_val_class_loclistsptr:
case dw_val_class_high_pc:
fprintf (outfile, "label: %s", val->v.val_lbl_id);
break;
@@ -5650,6 +5870,7 @@ print_dw_val (dw_val_node *val, bool recurse, FILE *outfile)
fprintf (outfile, "<null>");
break;
case dw_val_class_file:
+ case dw_val_class_file_implicit:
fprintf (outfile, "\"%s\" (%d)", val->v.val_file->filename,
val->v.val_file->emitted_number);
break;
@@ -5912,6 +6133,7 @@ check_die (dw_die_ref die)
&& a->dw_attr != DW_AT_high_pc
&& a->dw_attr != DW_AT_location
&& a->dw_attr != DW_AT_frame_base
+ && a->dw_attr != DW_AT_call_all_calls
&& a->dw_attr != DW_AT_GNU_all_call_sites);
}
}
@@ -5979,9 +6201,11 @@ attr_checksum (dw_attr_node *at, struct md5_ctx *ctx, int *mark)
switch (AT_class (at))
{
case dw_val_class_const:
+ case dw_val_class_const_implicit:
CHECKSUM (at->dw_attr_val.v.val_int);
break;
case dw_val_class_unsigned_const:
+ case dw_val_class_unsigned_const_implicit:
CHECKSUM (at->dw_attr_val.v.val_unsigned);
break;
case dw_val_class_const_double:
@@ -6028,10 +6252,12 @@ attr_checksum (dw_attr_node *at, struct md5_ctx *ctx, int *mark)
case dw_val_class_lbl_id:
case dw_val_class_lineptr:
case dw_val_class_macptr:
+ case dw_val_class_loclistsptr:
case dw_val_class_high_pc:
break;
case dw_val_class_file:
+ case dw_val_class_file_implicit:
CHECKSUM_STRING (AT_file (at)->filename);
break;
@@ -6256,11 +6482,13 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_node *at,
switch (AT_class (at))
{
case dw_val_class_const:
+ case dw_val_class_const_implicit:
CHECKSUM_ULEB128 (DW_FORM_sdata);
CHECKSUM_SLEB128 (at->dw_attr_val.v.val_int);
break;
case dw_val_class_unsigned_const:
+ case dw_val_class_unsigned_const_implicit:
CHECKSUM_ULEB128 (DW_FORM_sdata);
CHECKSUM_SLEB128 ((int) at->dw_attr_val.v.val_unsigned);
break;
@@ -6320,10 +6548,12 @@ attr_checksum_ordered (enum dwarf_tag tag, dw_attr_node *at,
case dw_val_class_lbl_id:
case dw_val_class_lineptr:
case dw_val_class_macptr:
+ case dw_val_class_loclistsptr:
case dw_val_class_high_pc:
break;
case dw_val_class_file:
+ case dw_val_class_file_implicit:
CHECKSUM_ULEB128 (DW_FORM_string);
CHECKSUM_STRING (AT_file (at)->filename);
break;
@@ -6766,8 +6996,10 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
switch (v1->val_class)
{
case dw_val_class_const:
+ case dw_val_class_const_implicit:
return v1->v.val_int == v2->v.val_int;
case dw_val_class_unsigned_const:
+ case dw_val_class_unsigned_const_implicit:
return v1->v.val_unsigned == v2->v.val_unsigned;
case dw_val_class_const_double:
return v1->v.val_double.high == v2->v.val_double.high
@@ -6813,10 +7045,12 @@ same_dw_val_p (const dw_val_node *v1, const dw_val_node *v2, int *mark)
case dw_val_class_lbl_id:
case dw_val_class_lineptr:
case dw_val_class_macptr:
+ case dw_val_class_loclistsptr:
case dw_val_class_high_pc:
return 1;
case dw_val_class_file:
+ case dw_val_class_file_implicit:
return v1->v.val_file == v2->v.val_file;
case dw_val_class_data8:
@@ -7031,7 +7265,8 @@ is_symbol_die (dw_die_ref c)
static inline bool
is_cu_die (dw_die_ref c)
{
- return c && c->die_tag == DW_TAG_compile_unit;
+ return c && (c->die_tag == DW_TAG_compile_unit
+ || c->die_tag == DW_TAG_skeleton_unit);
}
/* Returns true iff C is a unit DIE of some sort. */
@@ -7041,7 +7276,8 @@ is_unit_die (dw_die_ref c)
{
return c && (c->die_tag == DW_TAG_compile_unit
|| c->die_tag == DW_TAG_partial_unit
- || c->die_tag == DW_TAG_type_unit);
+ || c->die_tag == DW_TAG_type_unit
+ || c->die_tag == DW_TAG_skeleton_unit);
}
/* Returns true iff C is a namespace DIE. */
@@ -7326,7 +7562,8 @@ contains_subprogram_definition (dw_die_ref die)
}
/* Return non-zero if this is a type DIE that should be moved to a
- COMDAT .debug_types section. */
+ COMDAT .debug_types section or .debug_info section with DW_UT_*type
+ unit type. */
static int
should_move_die_to_comdat (dw_die_ref die)
@@ -7843,8 +8080,9 @@ copy_dwarf_procs_ref_in_dies (dw_die_ref die,
copied_dwarf_procs));
}
-/* Traverse the DIE and set up additional .debug_types sections for each
- type worthy of being placed in a COMDAT section. */
+/* Traverse the DIE and set up additional .debug_types or .debug_info
+ DW_UT_*type sections for each type worthy of being placed in a COMDAT
+ section. */
static void
break_out_comdat_types (dw_die_ref die)
@@ -8093,6 +8331,59 @@ output_location_lists (dw_die_ref die)
FOR_EACH_CHILD (die, c, output_location_lists (c));
}
+/* During assign_location_list_indexes and output_loclists_offset the
+ current index, after it the number of assigned indexes (i.e. how
+ large the .debug_loclists* offset table should be). */
+static unsigned int loc_list_idx;
+
+/* Output all location list offsets for the DIE and its children. */
+
+static void
+output_loclists_offsets (dw_die_ref die)
+{
+ dw_die_ref c;
+ dw_attr_node *a;
+ unsigned ix;
+
+ FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+ if (AT_class (a) == dw_val_class_loc_list)
+ {
+ dw_loc_list_ref l = AT_loc_list (a);
+ if (l->offset_emitted)
+ continue;
+ dw2_asm_output_delta (DWARF_OFFSET_SIZE, l->ll_symbol,
+ loc_section_label, NULL);
+ gcc_assert (l->hash == loc_list_idx);
+ loc_list_idx++;
+ l->offset_emitted = true;
+ }
+
+ FOR_EACH_CHILD (die, c, output_loclists_offsets (c));
+}
+
+/* Recursively set indexes of location lists. */
+
+static void
+assign_location_list_indexes (dw_die_ref die)
+{
+ dw_die_ref c;
+ dw_attr_node *a;
+ unsigned ix;
+
+ FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+ if (AT_class (a) == dw_val_class_loc_list)
+ {
+ dw_loc_list_ref list = AT_loc_list (a);
+ if (!list->num_assigned)
+ {
+ list->num_assigned = true;
+ list->hash = loc_list_idx++;
+ }
+ }
+
+ FOR_EACH_CHILD (die, c, assign_location_list_indexes (c));
+}
+
/* We want to limit the number of external references, because they are
larger than local references: a relocation takes multiple words, and
even a sig8 reference is always eight bytes, whereas a local reference
@@ -8252,6 +8543,20 @@ optimize_external_refs (dw_die_ref die)
return map;
}
+/* The following 3 variables are temporaries that are computed only during the
+ build_abbrev_table call and used and released during the following
+ optimize_abbrev_table call. */
+
+/* First abbrev_id that can be optimized based on usage. */
+static unsigned int abbrev_opt_start;
+
+/* Vector of usage counts during build_abbrev_table. Indexed by
+ abbrev_id - abbrev_opt_start. */
+static vec<unsigned int> abbrev_usage_count;
+
+/* Vector of all DIEs added with die_abbrev >= abbrev_opt_start. */
+static vec<dw_die_ref> sorted_abbrev_dies;
+
/* The format of each DIE (and its attribute value pairs) is encoded in an
abbreviation table. This routine builds the abbreviation table and assigns
a unique abbreviation id for each abbreviation entry. The children of each
@@ -8260,11 +8565,11 @@ optimize_external_refs (dw_die_ref die)
static void
build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
{
- unsigned long abbrev_id;
- unsigned int n_alloc;
+ unsigned int abbrev_id = 0;
dw_die_ref c;
dw_attr_node *a;
unsigned ix;
+ dw_die_ref abbrev;
/* Scan the DIE references, and replace any that refer to
DIEs from other CUs (i.e. those which are not marked) with
@@ -8284,13 +8589,14 @@ build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
set_AT_ref_external (a, 1);
}
- for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
+ FOR_EACH_VEC_SAFE_ELT (abbrev_die_table, abbrev_id, abbrev)
{
- dw_die_ref abbrev = abbrev_die_table[abbrev_id];
dw_attr_node *die_a, *abbrev_a;
unsigned ix;
bool ok = true;
+ if (abbrev_id == 0)
+ continue;
if (abbrev->die_tag != die->die_tag)
continue;
if ((abbrev->die_child != NULL) != (die->die_child != NULL))
@@ -8313,25 +8619,179 @@ build_abbrev_table (dw_die_ref die, external_ref_hash_type *extern_map)
break;
}
- if (abbrev_id >= abbrev_die_table_in_use)
+ if (abbrev_id >= vec_safe_length (abbrev_die_table))
+ {
+ vec_safe_push (abbrev_die_table, die);
+ if (abbrev_opt_start)
+ abbrev_usage_count.safe_push (0);
+ }
+ if (abbrev_opt_start && abbrev_id >= abbrev_opt_start)
+ {
+ abbrev_usage_count[abbrev_id - abbrev_opt_start]++;
+ sorted_abbrev_dies.safe_push (die);
+ }
+
+ die->die_abbrev = abbrev_id;
+ FOR_EACH_CHILD (die, c, build_abbrev_table (c, extern_map));
+}
+
+/* Callback function for sorted_abbrev_dies vector sorting. We sort
+ by die_abbrev's usage count, from the most commonly used
+ abbreviation to the least. */
+
+static int
+die_abbrev_cmp (const void *p1, const void *p2)
+{
+ dw_die_ref die1 = *(const dw_die_ref *) p1;
+ dw_die_ref die2 = *(const dw_die_ref *) p2;
+
+ gcc_checking_assert (die1->die_abbrev >= abbrev_opt_start);
+ gcc_checking_assert (die2->die_abbrev >= abbrev_opt_start);
+
+ if (abbrev_usage_count[die1->die_abbrev - abbrev_opt_start]
+ > abbrev_usage_count[die2->die_abbrev - abbrev_opt_start])
+ return -1;
+ if (abbrev_usage_count[die1->die_abbrev - abbrev_opt_start]
+ < abbrev_usage_count[die2->die_abbrev - abbrev_opt_start])
+ return 1;
+
+ /* Stabilize the sort. */
+ if (die1->die_abbrev < die2->die_abbrev)
+ return -1;
+ if (die1->die_abbrev > die2->die_abbrev)
+ return 1;
+
+ return 0;
+}
+
+/* Convert dw_val_class_const and dw_val_class_unsigned_const class attributes
+ of DIEs in between sorted_abbrev_dies[first_id] and abbrev_dies[end_id - 1]
+ into dw_val_class_const_implicit or
+ dw_val_class_unsigned_const_implicit. */
+
+static void
+optimize_implicit_const (unsigned int first_id, unsigned int end,
+ vec<bool> &implicit_consts)
+{
+ /* It never makes sense if there is just one DIE using the abbreviation. */
+ if (end < first_id + 2)
+ return;
+
+ dw_attr_node *a;
+ unsigned ix, i;
+ dw_die_ref die = sorted_abbrev_dies[first_id];
+ FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+ if (implicit_consts[ix])
+ {
+ enum dw_val_class new_class = dw_val_class_none;
+ switch (AT_class (a))
+ {
+ case dw_val_class_unsigned_const:
+ if ((HOST_WIDE_INT) AT_unsigned (a) < 0)
+ continue;
+
+ /* The .debug_abbrev section will grow by
+ size_of_sleb128 (AT_unsigned (a)) and we avoid the constants
+ in all the DIEs using that abbreviation. */
+ if (constant_size (AT_unsigned (a)) * (end - first_id)
+ <= (unsigned) size_of_sleb128 (AT_unsigned (a)))
+ continue;
+
+ new_class = dw_val_class_unsigned_const_implicit;
+ break;
+
+ case dw_val_class_const:
+ new_class = dw_val_class_const_implicit;
+ break;
+
+ case dw_val_class_file:
+ new_class = dw_val_class_file_implicit;
+ break;
+
+ default:
+ continue;
+ }
+ for (i = first_id; i < end; i++)
+ (*sorted_abbrev_dies[i]->die_attr)[ix].dw_attr_val.val_class
+ = new_class;
+ }
+}
+
+/* Attempt to optimize abbreviation table from abbrev_opt_start
+ abbreviation above. */
+
+static void
+optimize_abbrev_table (void)
+{
+ if (abbrev_opt_start
+ && vec_safe_length (abbrev_die_table) > abbrev_opt_start
+ && (dwarf_version >= 5 || vec_safe_length (abbrev_die_table) > 127))
{
- if (abbrev_die_table_in_use >= abbrev_die_table_allocated)
+ auto_vec<bool, 32> implicit_consts;
+ sorted_abbrev_dies.qsort (die_abbrev_cmp);
+
+ unsigned int abbrev_id = abbrev_opt_start - 1;
+ unsigned int first_id = 0;
+ unsigned int last_abbrev_id = 0;
+ unsigned int i;
+ dw_die_ref die;
+ /* Reassign abbreviation ids from abbrev_opt_start above, so that
+ most commonly used abbreviations come first. */
+ FOR_EACH_VEC_ELT (sorted_abbrev_dies, i, die)
{
- n_alloc = abbrev_die_table_allocated + ABBREV_DIE_TABLE_INCREMENT;
- abbrev_die_table = GGC_RESIZEVEC (dw_die_ref, abbrev_die_table,
- n_alloc);
+ dw_attr_node *a;
+ unsigned ix;
- memset (&abbrev_die_table[abbrev_die_table_allocated], 0,
- (n_alloc - abbrev_die_table_allocated) * sizeof (dw_die_ref));
- abbrev_die_table_allocated = n_alloc;
- }
+ if (die->die_abbrev != last_abbrev_id)
+ {
+ last_abbrev_id = die->die_abbrev;
+ if (dwarf_version >= 5 && i)
+ optimize_implicit_const (first_id, i, implicit_consts);
+ abbrev_id++;
+ (*abbrev_die_table)[abbrev_id] = die;
+ if (dwarf_version >= 5)
+ {
+ first_id = i;
+ implicit_consts.truncate (0);
- ++abbrev_die_table_in_use;
- abbrev_die_table[abbrev_id] = die;
+ FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+ switch (AT_class (a))
+ {
+ case dw_val_class_const:
+ case dw_val_class_unsigned_const:
+ case dw_val_class_file:
+ implicit_consts.safe_push (true);
+ break;
+ default:
+ implicit_consts.safe_push (false);
+ break;
+ }
+ }
+ }
+ else if (dwarf_version >= 5)
+ {
+ FOR_EACH_VEC_SAFE_ELT (die->die_attr, ix, a)
+ if (!implicit_consts[ix])
+ continue;
+ else
+ {
+ dw_attr_node *other_a
+ = &(*(*abbrev_die_table)[abbrev_id]->die_attr)[ix];
+ if (!dw_val_equal_p (&a->dw_attr_val,
+ &other_a->dw_attr_val))
+ implicit_consts[ix] = false;
+ }
+ }
+ die->die_abbrev = abbrev_id;
+ }
+ gcc_assert (abbrev_id == vec_safe_length (abbrev_die_table) - 1);
+ if (dwarf_version >= 5)
+ optimize_implicit_const (first_id, i, implicit_consts);
}
- die->die_abbrev = abbrev_id;
- FOR_EACH_CHILD (die, c, build_abbrev_table (c, extern_map));
+ abbrev_opt_start = 0;
+ abbrev_usage_count.release ();
+ sorted_abbrev_dies.release ();
}
/* Return the power-of-two number of bytes necessary to represent VALUE. */
@@ -8393,16 +8853,23 @@ size_of_die (dw_die_ref die)
}
break;
case dw_val_class_loc_list:
- if (dwarf_split_debug_info && AT_index (a) != NOT_INDEXED)
- {
- gcc_assert (AT_index (a) != NO_INDEX_ASSIGNED);
- size += size_of_uleb128 (AT_index (a));
- }
+ if (dwarf_split_debug_info && dwarf_version >= 5)
+ {
+ gcc_assert (AT_loc_list (a)->num_assigned);
+ size += size_of_uleb128 (AT_loc_list (a)->hash);
+ }
else
size += DWARF_OFFSET_SIZE;
break;
case dw_val_class_range_list:
- size += DWARF_OFFSET_SIZE;
+ if (value_format (a) == DW_FORM_rnglistx)
+ {
+ gcc_assert (rnglist_idx);
+ dw_ranges *r = &(*ranges_table)[a->dw_attr_val.v.val_offset];
+ size += size_of_uleb128 (r->idx);
+ }
+ else
+ size += DWARF_OFFSET_SIZE;
break;
case dw_val_class_const:
size += size_of_sleb128 (AT_int (a));
@@ -8418,16 +8885,22 @@ size_of_die (dw_die_ref die)
size += csize;
}
break;
+ case dw_val_class_const_implicit:
+ case dw_val_class_unsigned_const_implicit:
+ case dw_val_class_file_implicit:
+ /* These occupy no size in the DIE, just an extra sleb128 in
+ .debug_abbrev. */
+ break;
case dw_val_class_const_double:
size += HOST_BITS_PER_DOUBLE_INT / HOST_BITS_PER_CHAR;
- if (HOST_BITS_PER_WIDE_INT >= 64)
+ if (HOST_BITS_PER_WIDE_INT >= DWARF_LARGEST_DATA_FORM_BITS)
size++; /* block */
break;
case dw_val_class_wide_int:
size += (get_full_len (*a->dw_attr_val.v.val_wide)
* HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR);
- if (get_full_len (*a->dw_attr_val.v.val_wide) * HOST_BITS_PER_WIDE_INT
- > 64)
+ if (get_full_len (*a->dw_attr_val.v.val_wide)
+ * HOST_BITS_PER_WIDE_INT > DWARF_LARGEST_DATA_FORM_BITS)
size++; /* block */
break;
case dw_val_class_vec:
@@ -8479,14 +8952,15 @@ size_of_die (dw_die_ref die)
break;
case dw_val_class_lineptr:
case dw_val_class_macptr:
- size += DWARF_OFFSET_SIZE;
+ case dw_val_class_loclistsptr:
+ size += DWARF_OFFSET_SIZE;
break;
case dw_val_class_str:
form = AT_string_form (a);
- if (form == DW_FORM_strp)
+ if (form == DW_FORM_strp || form == DW_FORM_line_strp)
size += DWARF_OFFSET_SIZE;
- else if (form == DW_FORM_GNU_str_index)
- size += size_of_uleb128 (AT_index (a));
+ else if (form == DW_FORM_GNU_str_index)
+ size += size_of_uleb128 (AT_index (a));
else
size += strlen (a->dw_attr_val.v.val_str->str) + 1;
break;
@@ -8744,8 +9218,25 @@ value_format (dw_attr_node *a)
default:
gcc_unreachable ();
}
- case dw_val_class_range_list:
case dw_val_class_loc_list:
+ if (dwarf_split_debug_info
+ && dwarf_version >= 5
+ && AT_loc_list (a)->num_assigned)
+ return DW_FORM_loclistx;
+ /* FALLTHRU */
+ case dw_val_class_range_list:
+ /* For range lists in DWARF 5, use DW_FORM_rnglistx from .debug_info.dwo
+ but in .debug_info use DW_FORM_sec_offset, which is shorter if we
+ care about sizes of .debug* sections in shared libraries and
+ executables and don't take into account relocations that affect just
+ relocatable objects - for DW_FORM_rnglistx we'd have to emit offset
+ table in the .debug_rnglists section. */
+ if (dwarf_split_debug_info
+ && dwarf_version >= 5
+ && AT_class (a) == dw_val_class_range_list
+ && rnglist_idx
+ && a->dw_attr_val.val_entry != RELOCATED_OFFSET)
+ return DW_FORM_rnglistx;
if (dwarf_version >= 4)
return DW_FORM_sec_offset;
/* FALLTHRU */
@@ -8798,6 +9289,10 @@ value_format (dw_attr_node *a)
default:
gcc_unreachable ();
}
+ case dw_val_class_const_implicit:
+ case dw_val_class_unsigned_const_implicit:
+ case dw_val_class_file_implicit:
+ return DW_FORM_implicit_const;
case dw_val_class_const_double:
switch (HOST_BITS_PER_WIDE_INT)
{
@@ -8808,6 +9303,9 @@ value_format (dw_attr_node *a)
case 32:
return DW_FORM_data8;
case 64:
+ if (dwarf_version >= 5)
+ return DW_FORM_data16;
+ /* FALLTHRU */
default:
return DW_FORM_block1;
}
@@ -8822,6 +9320,10 @@ value_format (dw_attr_node *a)
return DW_FORM_data4;
case 64:
return DW_FORM_data8;
+ case 128:
+ if (dwarf_version >= 5)
+ return DW_FORM_data16;
+ /* FALLTHRU */
default:
return DW_FORM_block1;
}
@@ -8863,6 +9365,7 @@ value_format (dw_attr_node *a)
? DW_FORM_addr : DW_FORM_GNU_addr_index);
case dw_val_class_lineptr:
case dw_val_class_macptr:
+ case dw_val_class_loclistsptr:
return dwarf_version >= 4 ? DW_FORM_sec_offset : DW_FORM_data;
case dw_val_class_str:
return AT_string_form (a);
@@ -8951,6 +9454,17 @@ output_die_abbrevs (unsigned long abbrev_id, dw_die_ref abbrev)
dw2_asm_output_data_uleb128 (a_attr->dw_attr, "(%s)",
dwarf_attr_name (a_attr->dw_attr));
output_value_format (a_attr);
+ if (value_format (a_attr) == DW_FORM_implicit_const)
+ {
+ if (AT_class (a_attr) == dw_val_class_file_implicit)
+ {
+ int f = maybe_emit_file (a_attr->dw_attr_val.v.val_file);
+ const char *filename = a_attr->dw_attr_val.v.val_file->filename;
+ dw2_asm_output_data_sleb128 (f, "(%s)", filename);
+ }
+ else
+ dw2_asm_output_data_sleb128 (a_attr->dw_attr_val.v.val_int, NULL);
+ }
}
dw2_asm_output_data (1, 0, NULL);
@@ -8964,10 +9478,12 @@ output_die_abbrevs (unsigned long abbrev_id, dw_die_ref abbrev)
static void
output_abbrev_section (void)
{
- unsigned long abbrev_id;
+ unsigned int abbrev_id;
+ dw_die_ref abbrev;
- for (abbrev_id = 1; abbrev_id < abbrev_die_table_in_use; ++abbrev_id)
- output_die_abbrevs (abbrev_id, abbrev_die_table[abbrev_id]);
+ FOR_EACH_VEC_SAFE_ELT (abbrev_die_table, abbrev_id, abbrev)
+ if (abbrev_id != 0)
+ output_die_abbrevs (abbrev_id, abbrev);
/* Terminate the table. */
dw2_asm_output_data (1, 0, NULL);
@@ -9027,14 +9543,18 @@ gen_llsym (dw_loc_list_ref list)
static void
output_loc_list (dw_loc_list_ref list_head)
{
- dw_loc_list_ref curr = list_head;
-
if (list_head->emitted)
return;
list_head->emitted = true;
ASM_OUTPUT_LABEL (asm_out_file, list_head->ll_symbol);
+ dw_loc_list_ref curr = list_head;
+#ifdef HAVE_AS_LEB128
+ const char *last_section = NULL;
+ const char *base_label = NULL;
+#endif
+
/* Walk the location list, and output each range + expression. */
for (curr = list_head; curr != NULL; curr = curr->dw_loc_next)
{
@@ -9049,23 +9569,142 @@ output_loc_list (dw_loc_list_ref list_head)
in a single range are unlikely very useful. */
if (size > 0xffff)
continue;
- if (dwarf_split_debug_info)
- {
- dw2_asm_output_data (1, DW_LLE_GNU_start_length_entry,
- "Location list start/length entry (%s)",
- list_head->ll_symbol);
- dw2_asm_output_data_uleb128 (curr->begin_entry->index,
- "Location list range start index (%s)",
- curr->begin);
- /* The length field is 4 bytes. If we ever need to support
- an 8-byte length, we can add a new DW_LLE code or fall back
- to DW_LLE_GNU_start_end_entry. */
- dw2_asm_output_delta (4, curr->end, curr->begin,
- "Location list range length (%s)",
- list_head->ll_symbol);
- }
+ if (dwarf_version >= 5)
+ {
+ if (dwarf_split_debug_info)
+ {
+ /* For -gsplit-dwarf, emit DW_LLE_starx_length, which has
+ uleb128 index into .debug_addr and uleb128 length. */
+ dw2_asm_output_data (1, DW_LLE_startx_length,
+ "DW_LLE_startx_length (%s)",
+ list_head->ll_symbol);
+ dw2_asm_output_data_uleb128 (curr->begin_entry->index,
+ "Location list range start index "
+ "(%s)", curr->begin);
+ /* FIXME: This will ICE ifndef HAVE_AS_LEB128.
+ For that case we probably need to emit DW_LLE_startx_endx,
+ but we'd need 2 .debug_addr entries rather than just one. */
+ dw2_asm_output_delta_uleb128 (curr->end, curr->begin,
+ "Location list length (%s)",
+ list_head->ll_symbol);
+ }
+#ifdef HAVE_AS_LEB128
+ else if (!have_multiple_function_sections)
+ {
+ /* If all code is in .text section, the base address is
+ already provided by the CU attributes. Use
+ DW_LLE_offset_pair where both addresses are uleb128 encoded
+ offsets against that base. */
+ dw2_asm_output_data (1, DW_LLE_offset_pair,
+ "DW_LLE_offset_pair (%s)",
+ list_head->ll_symbol);
+ dw2_asm_output_delta_uleb128 (curr->begin, curr->section,
+ "Location list begin address (%s)",
+ list_head->ll_symbol);
+ dw2_asm_output_delta_uleb128 (curr->end, curr->section,
+ "Location list end address (%s)",
+ list_head->ll_symbol);
+ }
+ else
+ {
+ /* Otherwise, find out how many consecutive entries could share
+ the same base entry. If just one, emit DW_LLE_start_length,
+ otherwise emit DW_LLE_base_address for the base address
+ followed by a series of DW_LLE_offset_pair. */
+ if (last_section == NULL || curr->section != last_section)
+ {
+ dw_loc_list_ref curr2;
+ for (curr2 = curr->dw_loc_next; curr2 != NULL;
+ curr2 = curr2->dw_loc_next)
+ {
+ if (strcmp (curr2->begin, curr2->end) == 0
+ && !curr2->force)
+ continue;
+ if ((unsigned long) size_of_locs (curr2->expr) > 0xffff)
+ continue;
+ break;
+ }
+ if (curr2 == NULL || curr->section != curr2->section)
+ last_section = NULL;
+ else
+ {
+ last_section = curr->section;
+ base_label = curr->begin;
+ dw2_asm_output_data (1, DW_LLE_base_address,
+ "DW_LLE_base_address (%s)",
+ list_head->ll_symbol);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, base_label,
+ "Base address (%s)",
+ list_head->ll_symbol);
+ }
+ }
+ /* Only one entry with the same base address. Use
+ DW_LLE_start_length with absolute address and uleb128
+ length. */
+ if (last_section == NULL)
+ {
+ dw2_asm_output_data (1, DW_LLE_start_length,
+ "DW_LLE_start_length (%s)",
+ list_head->ll_symbol);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->begin,
+ "Location list begin address (%s)",
+ list_head->ll_symbol);
+ dw2_asm_output_delta_uleb128 (curr->end, curr->begin,
+ "Location list length "
+ "(%s)", list_head->ll_symbol);
+ }
+ /* Otherwise emit DW_LLE_offset_pair, relative to above emitted
+ DW_LLE_base_address. */
+ else
+ {
+ dw2_asm_output_data (1, DW_LLE_offset_pair,
+ "DW_LLE_offset_pair (%s)",
+ list_head->ll_symbol);
+ dw2_asm_output_delta_uleb128 (curr->begin, base_label,
+ "Location list begin address "
+ "(%s)", list_head->ll_symbol);
+ dw2_asm_output_delta_uleb128 (curr->end, base_label,
+ "Location list end address "
+ "(%s)", list_head->ll_symbol);
+ }
+ }
+#else
+ /* The assembler does not support .uleb128 directive. Emit
+ DW_LLE_start_end with a pair of absolute addresses. */
+ else
+ {
+ dw2_asm_output_data (1, DW_LLE_start_end,
+ "DW_LLE_start_end (%s)",
+ list_head->ll_symbol);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->begin,
+ "Location list begin address (%s)",
+ list_head->ll_symbol);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->end,
+ "Location list end address (%s)",
+ list_head->ll_symbol);
+ }
+#endif
+ }
+ else if (dwarf_split_debug_info)
+ {
+ /* For -gsplit-dwarf -gdwarf-{2,3,4} emit index into .debug_addr
+ and 4 byte length. */
+ dw2_asm_output_data (1, DW_LLE_GNU_start_length_entry,
+ "Location list start/length entry (%s)",
+ list_head->ll_symbol);
+ dw2_asm_output_data_uleb128 (curr->begin_entry->index,
+ "Location list range start index (%s)",
+ curr->begin);
+ /* The length field is 4 bytes. If we ever need to support
+ an 8-byte length, we can add a new DW_LLE code or fall back
+ to DW_LLE_GNU_start_end_entry. */
+ dw2_asm_output_delta (4, curr->end, curr->begin,
+ "Location list range length (%s)",
+ list_head->ll_symbol);
+ }
else if (!have_multiple_function_sections)
{
+ /* Pair of relative addresses against start of text section. */
dw2_asm_output_delta (DWARF2_ADDR_SIZE, curr->begin, curr->section,
"Location list begin address (%s)",
list_head->ll_symbol);
@@ -9075,6 +9714,7 @@ output_loc_list (dw_loc_list_ref list_head)
}
else
{
+ /* Pair of absolute addresses. */
dw2_asm_output_addr (DWARF2_ADDR_SIZE, curr->begin,
"Location list begin address (%s)",
list_head->ll_symbol);
@@ -9090,24 +9730,28 @@ output_loc_list (dw_loc_list_ref list_head)
output_loc_sequence (curr->expr, -1);
}
- if (dwarf_split_debug_info)
+ /* And finally list termination. */
+ if (dwarf_version >= 5)
+ dw2_asm_output_data (1, DW_LLE_end_of_list,
+ "DW_LLE_end_of_list (%s)", list_head->ll_symbol);
+ else if (dwarf_split_debug_info)
dw2_asm_output_data (1, DW_LLE_GNU_end_of_list_entry,
- "Location list terminator (%s)",
- list_head->ll_symbol);
+ "Location list terminator (%s)",
+ list_head->ll_symbol);
else
{
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
- "Location list terminator begin (%s)",
- list_head->ll_symbol);
+ "Location list terminator begin (%s)",
+ list_head->ll_symbol);
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0,
- "Location list terminator end (%s)",
- list_head->ll_symbol);
+ "Location list terminator end (%s)",
+ list_head->ll_symbol);
}
}
-/* Output a range_list offset into the debug_range section. Emit a
- relocated reference if val_entry is NULL, otherwise, emit an
- indirect reference. */
+/* Output a range_list offset into the .debug_ranges or .debug_rnglists
+ section. Emit a relocated reference if val_entry is NULL, otherwise,
+ emit an indirect reference. */
static void
output_range_list_offset (dw_attr_node *a)
@@ -9116,14 +9760,31 @@ output_range_list_offset (dw_attr_node *a)
if (a->dw_attr_val.val_entry == RELOCATED_OFFSET)
{
- char *p = strchr (ranges_section_label, '\0');
- sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX, a->dw_attr_val.v.val_offset);
- dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label,
- debug_ranges_section, "%s", name);
- *p = '\0';
+ if (dwarf_version >= 5)
+ {
+ dw_ranges *r = &(*ranges_table)[a->dw_attr_val.v.val_offset];
+ dw2_asm_output_offset (DWARF_OFFSET_SIZE, r->label,
+ debug_ranges_section, "%s", name);
+ }
+ else
+ {
+ char *p = strchr (ranges_section_label, '\0');
+ sprintf (p, "+" HOST_WIDE_INT_PRINT_HEX,
+ a->dw_attr_val.v.val_offset * 2 * DWARF2_ADDR_SIZE);
+ dw2_asm_output_offset (DWARF_OFFSET_SIZE, ranges_section_label,
+ debug_ranges_section, "%s", name);
+ *p = '\0';
+ }
+ }
+ else if (dwarf_version >= 5)
+ {
+ dw_ranges *r = &(*ranges_table)[a->dw_attr_val.v.val_offset];
+ gcc_assert (rnglist_idx);
+ dw2_asm_output_data_uleb128 (r->idx, "%s", name);
}
else
- dw2_asm_output_data (DWARF_OFFSET_SIZE, a->dw_attr_val.v.val_offset,
+ dw2_asm_output_data (DWARF_OFFSET_SIZE,
+ a->dw_attr_val.v.val_offset * 2 * DWARF2_ADDR_SIZE,
"%s (offset from %s)", name, ranges_section_label);
}
@@ -9135,12 +9796,19 @@ output_loc_list_offset (dw_attr_node *a)
char *sym = AT_loc_list (a)->ll_symbol;
gcc_assert (sym);
- if (dwarf_split_debug_info)
- dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label,
- "%s", dwarf_attr_name (a->dw_attr));
- else
+ if (!dwarf_split_debug_info)
dw2_asm_output_offset (DWARF_OFFSET_SIZE, sym, debug_loc_section,
"%s", dwarf_attr_name (a->dw_attr));
+ else if (dwarf_version >= 5)
+ {
+ gcc_assert (AT_loc_list (a)->num_assigned);
+ dw2_asm_output_data_uleb128 (AT_loc_list (a)->hash, "%s (%s)",
+ dwarf_attr_name (a->dw_attr),
+ sym);
+ }
+ else
+ dw2_asm_output_delta (DWARF_OFFSET_SIZE, sym, loc_section_label,
+ "%s", dwarf_attr_name (a->dw_attr));
}
/* Output an attribute's index or value appropriately. */
@@ -9157,18 +9825,15 @@ output_attr_index_or_value (dw_attr_node *a)
}
switch (AT_class (a))
{
- case dw_val_class_addr:
- dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name);
- break;
- case dw_val_class_high_pc:
- case dw_val_class_lbl_id:
- dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name);
- break;
- case dw_val_class_loc_list:
- output_loc_list_offset (a);
- break;
- default:
- gcc_unreachable ();
+ case dw_val_class_addr:
+ dw2_asm_output_addr_rtx (DWARF2_ADDR_SIZE, AT_addr (a), "%s", name);
+ break;
+ case dw_val_class_high_pc:
+ case dw_val_class_lbl_id:
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, AT_lbl (a), "%s", name);
+ break;
+ default:
+ gcc_unreachable ();
}
}
@@ -9264,11 +9929,25 @@ output_die (dw_die_ref die)
}
break;
+ case dw_val_class_const_implicit:
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t\t\t%s %s ("
+ HOST_WIDE_INT_PRINT_DEC ")\n",
+ ASM_COMMENT_START, name, AT_int (a));
+ break;
+
+ case dw_val_class_unsigned_const_implicit:
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t\t\t%s %s ("
+ HOST_WIDE_INT_PRINT_HEX ")\n",
+ ASM_COMMENT_START, name, AT_unsigned (a));
+ break;
+
case dw_val_class_const_double:
{
unsigned HOST_WIDE_INT first, second;
- if (HOST_BITS_PER_WIDE_INT >= 64)
+ if (HOST_BITS_PER_WIDE_INT >= DWARF_LARGEST_DATA_FORM_BITS)
dw2_asm_output_data (1,
HOST_BITS_PER_DOUBLE_INT
/ HOST_BITS_PER_CHAR,
@@ -9297,9 +9976,9 @@ output_die (dw_die_ref die)
int i;
int len = get_full_len (*a->dw_attr_val.v.val_wide);
int l = HOST_BITS_PER_WIDE_INT / HOST_BITS_PER_CHAR;
- if (len * HOST_BITS_PER_WIDE_INT > 64)
- dw2_asm_output_data (1, get_full_len (*a->dw_attr_val.v.val_wide) * l,
- NULL);
+ if (len * HOST_BITS_PER_WIDE_INT > DWARF_LARGEST_DATA_FORM_BITS)
+ dw2_asm_output_data (1, get_full_len (*a->dw_attr_val.v.val_wide)
+ * l, NULL);
if (WORDS_BIG_ENDIAN)
for (i = len - 1; i >= 0; --i)
@@ -9359,7 +10038,7 @@ output_die (dw_die_ref die)
break;
case dw_val_class_loc_list:
- output_attr_index_or_value (a);
+ output_loc_list_offset (a);
break;
case dw_val_class_die_ref:
@@ -9367,8 +10046,8 @@ output_die (dw_die_ref die)
{
if (AT_ref (a)->comdat_type_p)
{
- comdat_type_node *type_node =
- AT_ref (a)->die_id.die_type_node;
+ comdat_type_node *type_node
+ = AT_ref (a)->die_id.die_type_node;
gcc_assert (type_node);
output_signature (type_node->signature, name);
@@ -9422,7 +10101,7 @@ output_die (dw_die_ref die)
break;
case dw_val_class_lbl_id:
- output_attr_index_or_value (a);
+ output_attr_index_or_value (a);
break;
case dw_val_class_lineptr:
@@ -9435,12 +10114,22 @@ output_die (dw_die_ref die)
debug_macinfo_section, "%s", name);
break;
+ case dw_val_class_loclistsptr:
+ dw2_asm_output_offset (DWARF_OFFSET_SIZE, AT_lbl (a),
+ debug_loc_section, "%s", name);
+ break;
+
case dw_val_class_str:
if (a->dw_attr_val.v.val_str->form == DW_FORM_strp)
dw2_asm_output_offset (DWARF_OFFSET_SIZE,
a->dw_attr_val.v.val_str->label,
debug_str_section,
"%s: \"%s\"", name, AT_string (a));
+ else if (a->dw_attr_val.v.val_str->form == DW_FORM_line_strp)
+ dw2_asm_output_offset (DWARF_OFFSET_SIZE,
+ a->dw_attr_val.v.val_str->label,
+ debug_line_str_section,
+ "%s: \"%s\"", name, AT_string (a));
else if (a->dw_attr_val.v.val_str->form == DW_FORM_GNU_str_index)
dw2_asm_output_data_uleb128 (AT_index (a),
"%s: \"%s\"", name, AT_string (a));
@@ -9457,6 +10146,14 @@ output_die (dw_die_ref die)
break;
}
+ case dw_val_class_file_implicit:
+ if (flag_debug_asm)
+ fprintf (asm_out_file, "\t\t\t%s %s (%d, %s)\n",
+ ASM_COMMENT_START, name,
+ maybe_emit_file (a->dw_attr_val.v.val_file),
+ a->dw_attr_val.v.val_file->filename);
+ break;
+
case dw_val_class_data8:
{
int i;
@@ -9520,12 +10217,8 @@ output_die (dw_die_ref die)
.debug_info section, and precedes the DIE descriptions. */
static void
-output_compilation_unit_header (void)
+output_compilation_unit_header (enum dwarf_unit_type ut)
{
- /* We don't support actual DWARFv5 units yet, we just use some
- DWARFv5 draft DIE tags in DWARFv4 format. */
- int ver = dwarf_version < 5 ? dwarf_version : 4;
-
if (!XCOFF_DEBUGGING_INFO)
{
if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
@@ -9536,17 +10229,33 @@ output_compilation_unit_header (void)
"Length of Compilation Unit Info");
}
- dw2_asm_output_data (2, ver, "DWARF version number");
+ dw2_asm_output_data (2, dwarf_version, "DWARF version number");
+ if (dwarf_version >= 5)
+ {
+ const char *name;
+ switch (ut)
+ {
+ case DW_UT_compile: name = "DW_UT_compile"; break;
+ case DW_UT_type: name = "DW_UT_type"; break;
+ case DW_UT_split_compile: name = "DW_UT_split_compile"; break;
+ case DW_UT_split_type: name = "DW_UT_split_type"; break;
+ default: gcc_unreachable ();
+ }
+ dw2_asm_output_data (1, ut, name);
+ dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
+ }
dw2_asm_output_offset (DWARF_OFFSET_SIZE, abbrev_section_label,
debug_abbrev_section,
"Offset Into Abbrev. Section");
- dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
+ if (dwarf_version < 5)
+ dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
}
/* Output the compilation unit DIE and its children. */
static void
-output_comp_unit (dw_die_ref die, int output_if_empty)
+output_comp_unit (dw_die_ref die, int output_if_empty,
+ const unsigned char *dwo_id)
{
const char *secname, *oldsym;
char *tmp;
@@ -9564,8 +10273,16 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
external_ref_hash_type *extern_map = optimize_external_refs (die);
+ /* For now, optimize only the main CU, in order to optimize the rest
+ we'd need to see all of them earlier. Leave the rest for post-linking
+ tools like DWZ. */
+ if (die == comp_unit_die ())
+ abbrev_opt_start = vec_safe_length (abbrev_die_table);
+
build_abbrev_table (die, extern_map);
+ optimize_abbrev_table ();
+
delete extern_map;
/* Initialize the beginning DIE offset - and calculate sizes/offsets. */
@@ -9590,7 +10307,20 @@ output_comp_unit (dw_die_ref die, int output_if_empty)
}
/* Output debugging information. */
- output_compilation_unit_header ();
+ output_compilation_unit_header (dwo_id
+ ? DW_UT_split_compile : DW_UT_compile);
+ if (dwarf_version >= 5)
+ {
+ if (dwo_id != NULL)
+ for (int i = 0; i < 8; i++)
+ dw2_asm_output_data (1, dwo_id[i], i == 0 ? "DWO id" : NULL);
+ else
+ /* Hope all the padding will be removed for DWARF 5 final for
+ DW_AT_compile and DW_AT_partial. */
+ dw2_asm_output_data (8, 0, "Padding 1");
+
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, "Padding 2");
+ }
output_die (die);
/* Leave the marks on the main CU, so we can check them in
@@ -9659,7 +10389,7 @@ add_top_level_skeleton_die_attrs (dw_die_ref die)
const char *dwo_file_name = concat (aux_base_name, ".dwo", NULL);
const char *comp_dir = comp_dir_string ();
- add_skeleton_AT_string (die, DW_AT_GNU_dwo_name, dwo_file_name);
+ add_skeleton_AT_string (die, dwarf_AT (DW_AT_dwo_name), dwo_file_name);
if (comp_dir != NULL)
add_skeleton_AT_string (die, DW_AT_comp_dir, comp_dir);
add_AT_pubnames (die);
@@ -9669,12 +10399,9 @@ add_top_level_skeleton_die_attrs (dw_die_ref die)
/* Output skeleton debug sections that point to the dwo file. */
static void
-output_skeleton_debug_sections (dw_die_ref comp_unit)
+output_skeleton_debug_sections (dw_die_ref comp_unit,
+ const unsigned char *dwo_id)
{
- /* We don't support actual DWARFv5 units yet, we just use some
- DWARFv5 draft DIE tags in DWARFv4 format. */
- int ver = dwarf_version < 5 ? dwarf_version : 4;
-
/* These attributes will be found in the full debug_info section. */
remove_AT (comp_unit, DW_AT_producer);
remove_AT (comp_unit, DW_AT_language);
@@ -9694,11 +10421,24 @@ output_skeleton_debug_sections (dw_die_ref comp_unit)
- DWARF_INITIAL_LENGTH_SIZE
+ size_of_die (comp_unit),
"Length of Compilation Unit Info");
- dw2_asm_output_data (2, ver, "DWARF version number");
+ dw2_asm_output_data (2, dwarf_version, "DWARF version number");
+ if (dwarf_version >= 5)
+ {
+ dw2_asm_output_data (1, DW_UT_skeleton, "DW_UT_skeleton");
+ dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
+ }
dw2_asm_output_offset (DWARF_OFFSET_SIZE, debug_skeleton_abbrev_section_label,
- debug_abbrev_section,
+ debug_skeleton_abbrev_section,
"Offset Into Abbrev. Section");
- dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
+ if (dwarf_version < 5)
+ dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Pointer Size (in bytes)");
+ else
+ {
+ for (int i = 0; i < 8; i++)
+ dw2_asm_output_data (1, dwo_id[i], i == 0 ? "DWO id" : NULL);
+
+ dw2_asm_output_data (DWARF_OFFSET_SIZE, 0, "Padding 2");
+ }
comp_unit->die_abbrev = SKELETON_COMP_DIE_ABBREV;
output_die (comp_unit);
@@ -9739,13 +10479,20 @@ output_comdat_type_unit (comdat_type_node *node)
calc_die_sizes (node->root_die);
#if defined (OBJECT_FORMAT_ELF)
- if (!dwarf_split_debug_info)
+ if (dwarf_version >= 5)
+ {
+ if (!dwarf_split_debug_info)
+ secname = ".debug_info";
+ else
+ secname = ".debug_info.dwo";
+ }
+ else if (!dwarf_split_debug_info)
secname = ".debug_types";
else
secname = ".debug_types.dwo";
tmp = XALLOCAVEC (char, 4 + DWARF_TYPE_SIGNATURE_SIZE * 2);
- sprintf (tmp, "wt.");
+ sprintf (tmp, dwarf_version >= 5 ? "wi." : "wt.");
for (i = 0; i < DWARF_TYPE_SIGNATURE_SIZE; i++)
sprintf (tmp + 3 + i * 2, "%02x", node->signature[i] & 0xff);
comdat_key = get_identifier (tmp);
@@ -9754,7 +10501,8 @@ output_comdat_type_unit (comdat_type_node *node)
comdat_key);
#else
tmp = XALLOCAVEC (char, 18 + DWARF_TYPE_SIGNATURE_SIZE * 2);
- sprintf (tmp, ".gnu.linkonce.wt.");
+ sprintf (tmp, (dwarf_version >= 5
+ ? ".gnu.linkonce.wi." : ".gnu.linkonce.wt."));
for (i = 0; i < DWARF_TYPE_SIGNATURE_SIZE; i++)
sprintf (tmp + 17 + i * 2, "%02x", node->signature[i] & 0xff);
secname = tmp;
@@ -9762,7 +10510,8 @@ output_comdat_type_unit (comdat_type_node *node)
#endif
/* Output debugging information. */
- output_compilation_unit_header ();
+ output_compilation_unit_header (dwarf_split_debug_info
+ ? DW_UT_split_type : DW_UT_type);
output_signature (node->signature, "Type Signature");
dw2_asm_output_data (DWARF_OFFSET_SIZE, node->type_die->die_offset,
"Offset to Type DIE");
@@ -10130,24 +10879,36 @@ output_aranges (void)
dw2_asm_output_data (DWARF2_ADDR_SIZE, 0, NULL);
}
-/* Add a new entry to .debug_ranges. Return the offset at which it
- was placed. */
+/* Add a new entry to .debug_ranges. Return its index into
+ ranges_table vector. */
static unsigned int
-add_ranges_num (int num)
+add_ranges_num (int num, bool maybe_new_sec)
{
- dw_ranges r = { num };
+ dw_ranges r = { NULL, num, 0, maybe_new_sec };
vec_safe_push (ranges_table, r);
- return (vec_safe_length (ranges_table) - 1) * 2 * DWARF2_ADDR_SIZE;
+ return vec_safe_length (ranges_table) - 1;
}
/* Add a new entry to .debug_ranges corresponding to a block, or a
- range terminator if BLOCK is NULL. */
+ range terminator if BLOCK is NULL. MAYBE_NEW_SEC is true if
+ this entry might be in a different section from previous range. */
static unsigned int
-add_ranges (const_tree block)
+add_ranges (const_tree block, bool maybe_new_sec)
+{
+ return add_ranges_num (block ? BLOCK_NUMBER (block) : 0, maybe_new_sec);
+}
+
+/* Note that (*rnglist_table)[offset] is either a head of a rnglist
+ chain, or middle entry of a chain that will be directly referred to. */
+
+static void
+note_rnglist_head (unsigned int offset)
{
- return add_ranges_num (block ? BLOCK_NUMBER (block) : 0);
+ if (dwarf_version < 5 || (*ranges_table)[offset].label)
+ return;
+ (*ranges_table)[offset].label = gen_internal_sym ("LLRL");
}
/* Add a new entry to .debug_ranges corresponding to a pair of labels.
@@ -10163,14 +10924,17 @@ add_ranges_by_labels (dw_die_ref die, const char *begin, const char *end,
unsigned int offset;
dw_ranges_by_label rbl = { begin, end };
vec_safe_push (ranges_by_label, rbl);
- offset = add_ranges_num (-(int)in_use - 1);
+ offset = add_ranges_num (-(int)in_use - 1, true);
if (!*added)
{
add_AT_range_list (die, DW_AT_ranges, offset, force_direct);
*added = true;
+ note_rnglist_head (offset);
}
}
+/* Emit .debug_ranges section. */
+
static void
output_ranges (void)
{
@@ -10179,6 +10943,8 @@ output_ranges (void)
const char *fmt = start_fmt;
dw_ranges *r;
+ switch_to_section (debug_ranges_section);
+ ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label);
FOR_EACH_VEC_SAFE_ELT (ranges_table, i, r)
{
int block_num = r->num;
@@ -10257,6 +11023,188 @@ output_ranges (void)
}
}
+/* Non-zero if .debug_line_str should be used for .debug_line section
+ strings or strings that are likely shareable with those. */
+#define DWARF5_USE_DEBUG_LINE_STR \
+ (!DWARF2_INDIRECT_STRING_SUPPORT_MISSING_ON_TARGET \
+ && (DEBUG_STR_SECTION_FLAGS & SECTION_MERGE) != 0 \
+ /* FIXME: there is no .debug_line_str.dwo section, \
+ for -gsplit-dwarf we should use DW_FORM_strx instead. */ \
+ && !dwarf_split_debug_info)
+
+/* Assign .debug_rnglists indexes. */
+
+static void
+index_rnglists (void)
+{
+ unsigned i;
+ dw_ranges *r;
+
+ FOR_EACH_VEC_SAFE_ELT (ranges_table, i, r)
+ if (r->label)
+ r->idx = rnglist_idx++;
+}
+
+/* Emit .debug_rnglists section. */
+
+static void
+output_rnglists (void)
+{
+ unsigned i;
+ dw_ranges *r;
+ char l1[MAX_ARTIFICIAL_LABEL_BYTES];
+ char l2[MAX_ARTIFICIAL_LABEL_BYTES];
+#ifdef HAVE_AS_LEB128
+ char basebuf[MAX_ARTIFICIAL_LABEL_BYTES];
+#endif
+
+ switch_to_section (debug_ranges_section);
+ ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label);
+ ASM_GENERATE_INTERNAL_LABEL (l1, DEBUG_RANGES_SECTION_LABEL, 2);
+ ASM_GENERATE_INTERNAL_LABEL (l2, DEBUG_RANGES_SECTION_LABEL, 3);
+ if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ dw2_asm_output_data (4, 0xffffffff,
+ "Initial length escape value indicating "
+ "64-bit DWARF extension");
+ dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+ "Length of Range Lists");
+ ASM_OUTPUT_LABEL (asm_out_file, l1);
+ dw2_asm_output_data (2, dwarf_version, "DWARF Version");
+ dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size");
+ dw2_asm_output_data (1, 0, "Segment Size");
+ /* Emit the offset table only for -gsplit-dwarf. If we don't care
+ about relocation sizes and primarily care about the size of .debug*
+ sections in linked shared libraries and executables, then
+ the offset table plus corresponding DW_FORM_rnglistx uleb128 indexes
+ into it are usually larger than just DW_FORM_sec_offset offsets
+ into the .debug_rnglists section. */
+ dw2_asm_output_data (4, dwarf_split_debug_info ? rnglist_idx : 0,
+ "Offset Entry Count");
+ if (dwarf_split_debug_info)
+ {
+ ASM_OUTPUT_LABEL (asm_out_file, ranges_base_label);
+ FOR_EACH_VEC_SAFE_ELT (ranges_table, i, r)
+ if (r->label)
+ dw2_asm_output_delta (DWARF_OFFSET_SIZE, r->label,
+ ranges_base_label, NULL);
+ }
+
+ const char *lab = "";
+#ifdef HAVE_AS_LEB128
+ unsigned int len = vec_safe_length (ranges_table);
+ const char *base = NULL;
+#endif
+ FOR_EACH_VEC_SAFE_ELT (ranges_table, i, r)
+ {
+ int block_num = r->num;
+
+ if (r->label)
+ {
+ ASM_OUTPUT_LABEL (asm_out_file, r->label);
+ lab = r->label;
+ }
+#ifdef HAVE_AS_LEB128
+ if (r->label || r->maybe_new_sec)
+ base = NULL;
+#endif
+ if (block_num > 0)
+ {
+ char blabel[MAX_ARTIFICIAL_LABEL_BYTES];
+ char elabel[MAX_ARTIFICIAL_LABEL_BYTES];
+
+ ASM_GENERATE_INTERNAL_LABEL (blabel, BLOCK_BEGIN_LABEL, block_num);
+ ASM_GENERATE_INTERNAL_LABEL (elabel, BLOCK_END_LABEL, block_num);
+
+#ifdef HAVE_AS_LEB128
+ /* If all code is in the text section, then the compilation
+ unit base address defaults to DW_AT_low_pc, which is the
+ base of the text section. */
+ if (!have_multiple_function_sections)
+ {
+ dw2_asm_output_data (1, DW_RLE_offset_pair,
+ "DW_RLE_offset_pair (%s)", lab);
+ dw2_asm_output_delta_uleb128 (blabel, text_section_label,
+ "Range begin address (%s)", lab);
+ dw2_asm_output_delta_uleb128 (elabel, text_section_label,
+ "Range end address (%s)", lab);
+ continue;
+ }
+ if (base == NULL)
+ {
+ dw_ranges *r2 = NULL;
+ if (i < len - 1)
+ r2 = &(*ranges_table)[i + 1];
+ if (r2
+ && r2->num != 0
+ && r2->label == NULL
+ && !r2->maybe_new_sec)
+ {
+ dw2_asm_output_data (1, DW_RLE_base_address,
+ "DW_RLE_base_address (%s)", lab);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+ "Base address (%s)", lab);
+ strcpy (basebuf, blabel);
+ base = basebuf;
+ }
+ }
+ if (base)
+ {
+ dw2_asm_output_data (1, DW_RLE_offset_pair,
+ "DW_RLE_offset_pair (%s)", lab);
+ dw2_asm_output_delta_uleb128 (blabel, base,
+ "Range begin address (%s)", lab);
+ dw2_asm_output_delta_uleb128 (elabel, base,
+ "Range end address (%s)", lab);
+ continue;
+ }
+ dw2_asm_output_data (1, DW_RLE_start_length,
+ "DW_RLE_start_length (%s)", lab);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+ "Range begin address (%s)", lab);
+ dw2_asm_output_delta_uleb128 (elabel, blabel,
+ "Range length (%s)", lab);
+#else
+ dw2_asm_output_data (1, DW_RLE_start_end,
+ "DW_RLE_start_end (%s)", lab);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+ "Range begin address (%s)", lab);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, elabel,
+ "Range end address (%s)", lab);
+#endif
+ }
+
+ /* Negative block_num stands for an index into ranges_by_label. */
+ else if (block_num < 0)
+ {
+ int lab_idx = - block_num - 1;
+ const char *blabel = (*ranges_by_label)[lab_idx].begin;
+ const char *elabel = (*ranges_by_label)[lab_idx].end;
+
+ if (!have_multiple_function_sections)
+ gcc_unreachable ();
+#ifdef HAVE_AS_LEB128
+ dw2_asm_output_data (1, DW_RLE_start_length,
+ "DW_RLE_start_length (%s)", lab);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+ "Range begin address (%s)", lab);
+ dw2_asm_output_delta_uleb128 (elabel, blabel,
+ "Range length (%s)", lab);
+#else
+ dw2_asm_output_data (1, DW_RLE_start_end,
+ "DW_RLE_start_end (%s)", lab);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, blabel,
+ "Range begin address (%s)", lab);
+ dw2_asm_output_addr (DWARF2_ADDR_SIZE, elabel,
+ "Range end address (%s)", lab);
+#endif
+ }
+ else
+ dw2_asm_output_data (1, DW_RLE_end_of_list,
+ "DW_RLE_end_of_list (%s)", lab);
+ }
+ ASM_OUTPUT_LABEL (asm_out_file, l2);
+}
+
/* Data structure containing information about input files. */
struct file_info
{
@@ -10369,6 +11317,37 @@ file_name_acquire (dwarf_file_data **slot, file_name_acquire_data *fnad)
return 1;
}
+/* Helper function for output_file_names. Emit a FORM encoded
+ string STR, with assembly comment start ENTRY_KIND and
+ index IDX */
+
+static void
+output_line_string (enum dwarf_form form, const char *str,
+ const char *entry_kind, unsigned int idx)
+{
+ switch (form)
+ {
+ case DW_FORM_string:
+ dw2_asm_output_nstring (str, -1, "%s: %#x", entry_kind, idx);
+ break;
+ case DW_FORM_line_strp:
+ if (!debug_line_str_hash)
+ debug_line_str_hash
+ = hash_table<indirect_string_hasher>::create_ggc (10);
+
+ struct indirect_string_node *node;
+ node = find_AT_string_in_table (str, debug_line_str_hash);
+ set_indirect_string (node);
+ node->form = form;
+ dw2_asm_output_offset (DWARF_OFFSET_SIZE, node->label,
+ debug_line_str_section, "%s: %#x: \"%s\"",
+ entry_kind, 0, node->str);
+ break;
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* Output the directory table and the file name table. We try to minimize
the total amount of memory needed. A heuristic is used to avoid large
slowdowns with many input files. */
@@ -10389,8 +11368,18 @@ output_file_names (void)
if (!last_emitted_file)
{
- dw2_asm_output_data (1, 0, "End directory table");
- dw2_asm_output_data (1, 0, "End file name table");
+ if (dwarf_version >= 5)
+ {
+ dw2_asm_output_data (1, 0, "Directory entry format count");
+ dw2_asm_output_data_uleb128 (0, "Directories count");
+ dw2_asm_output_data (1, 0, "File name entry format count");
+ dw2_asm_output_data_uleb128 (0, "File names count");
+ }
+ else
+ {
+ dw2_asm_output_data (1, 0, "End directory table");
+ dw2_asm_output_data (1, 0, "End file name table");
+ }
return;
}
@@ -10513,13 +11502,52 @@ output_file_names (void)
/* Emit the directory name table. */
idx_offset = dirs[0].length > 0 ? 1 : 0;
- for (i = 1 - idx_offset; i < ndirs; i++)
- dw2_asm_output_nstring (dirs[i].path,
- dirs[i].length
- - !DWARF2_DIR_SHOULD_END_WITH_SEPARATOR,
- "Directory Entry: %#x", i + idx_offset);
+ enum dwarf_form str_form = DW_FORM_string;
+ enum dwarf_form idx_form = DW_FORM_udata;
+ if (dwarf_version >= 5)
+ {
+ const char *comp_dir = comp_dir_string ();
+ if (comp_dir == NULL)
+ comp_dir = "";
+ dw2_asm_output_data (1, 1, "Directory entry format count");
+ if (DWARF5_USE_DEBUG_LINE_STR)
+ str_form = DW_FORM_line_strp;
+ dw2_asm_output_data_uleb128 (DW_LNCT_path, "DW_LNCT_path");
+ dw2_asm_output_data_uleb128 (str_form, get_DW_FORM_name (str_form));
+ dw2_asm_output_data_uleb128 (ndirs + idx_offset, "Directories count");
+ if (str_form == DW_FORM_string)
+ {
+ dw2_asm_output_nstring (comp_dir, -1, "Directory Entry: %#x", 0);
+ for (i = 1 - idx_offset; i < ndirs; i++)
+ dw2_asm_output_nstring (dirs[i].path,
+ dirs[i].length
+ - !DWARF2_DIR_SHOULD_END_WITH_SEPARATOR,
+ "Directory Entry: %#x", i + idx_offset);
+ }
+ else
+ {
+ output_line_string (str_form, comp_dir, "Directory Entry", 0);
+ for (i = 1 - idx_offset; i < ndirs; i++)
+ {
+ const char *str
+ = ggc_alloc_string (dirs[i].path,
+ dirs[i].length
+ - !DWARF2_DIR_SHOULD_END_WITH_SEPARATOR);
+ output_line_string (str_form, str, "Directory Entry",
+ (unsigned) i + idx_offset);
+ }
+ }
+ }
+ else
+ {
+ for (i = 1 - idx_offset; i < ndirs; i++)
+ dw2_asm_output_nstring (dirs[i].path,
+ dirs[i].length
+ - !DWARF2_DIR_SHOULD_END_WITH_SEPARATOR,
+ "Directory Entry: %#x", i + idx_offset);
- dw2_asm_output_data (1, 0, "End directory table");
+ dw2_asm_output_data (1, 0, "End directory table");
+ }
/* We have to emit them in the order of emitted_number since that's
used in the debug info generation. To do this efficiently we
@@ -10528,6 +11556,70 @@ output_file_names (void)
for (i = 0; i < numfiles; i++)
backmap[files[i].file_idx->emitted_number - 1] = i;
+ if (dwarf_version >= 5)
+ {
+ const char *filename0 = get_AT_string (comp_unit_die (), DW_AT_name);
+ if (filename0 == NULL)
+ filename0 = "";
+ /* DW_LNCT_directory_index can use DW_FORM_udata, DW_FORM_data1 and
+ DW_FORM_data2. Choose one based on the number of directories
+ and how much space would they occupy in each encoding.
+ If we have at most 256 directories, all indexes fit into
+ a single byte, so DW_FORM_data1 is most compact (if there
+ are at most 128 directories, DW_FORM_udata would be as
+ compact as that, but not shorter and slower to decode). */
+ if (ndirs + idx_offset <= 256)
+ idx_form = DW_FORM_data1;
+ /* If there are more than 65536 directories, we have to use
+ DW_FORM_udata, DW_FORM_data2 can't refer to them.
+ Otherwise, compute what space would occupy if all the indexes
+ used DW_FORM_udata - sum - and compare that to how large would
+ be DW_FORM_data2 encoding, and pick the more efficient one. */
+ else if (ndirs + idx_offset <= 65536)
+ {
+ unsigned HOST_WIDE_INT sum = 1;
+ for (i = 0; i < numfiles; i++)
+ {
+ int file_idx = backmap[i];
+ int dir_idx = dirs[files[file_idx].dir_idx].dir_idx;
+ sum += size_of_uleb128 (dir_idx);
+ }
+ if (sum >= HOST_WIDE_INT_UC (2) * (numfiles + 1))
+ idx_form = DW_FORM_data2;
+ }
+#ifdef VMS_DEBUGGING_INFO
+ dw2_asm_output_data (1, 4, "File name entry format count");
+#else
+ dw2_asm_output_data (1, 2, "File name entry format count");
+#endif
+ dw2_asm_output_data_uleb128 (DW_LNCT_path, "DW_LNCT_path");
+ dw2_asm_output_data_uleb128 (str_form, get_DW_FORM_name (str_form));
+ dw2_asm_output_data_uleb128 (DW_LNCT_directory_index,
+ "DW_LNCT_directory_index");
+ dw2_asm_output_data_uleb128 (idx_form, get_DW_FORM_name (idx_form));
+#ifdef VMS_DEBUGGING_INFO
+ dw2_asm_output_data_uleb128 (DW_LNCT_timestamp, "DW_LNCT_timestamp");
+ dw2_asm_output_data_uleb128 (DW_FORM_udata, "DW_FORM_udata");
+ dw2_asm_output_data_uleb128 (DW_LNCT_size, "DW_LNCT_size");
+ dw2_asm_output_data_uleb128 (DW_FORM_udata, "DW_FORM_udata");
+#endif
+ dw2_asm_output_data_uleb128 (numfiles + 1, "File names count");
+
+ output_line_string (str_form, filename0, "File Entry", 0);
+
+ /* Include directory index. */
+ if (dwarf_version >= 5 && idx_form != DW_FORM_udata)
+ dw2_asm_output_data (idx_form == DW_FORM_data1 ? 1 : 2,
+ 0, NULL);
+ else
+ dw2_asm_output_data_uleb128 (0, NULL);
+
+#ifdef VMS_DEBUGGING_INFO
+ dw2_asm_output_data_uleb128 (0, NULL);
+ dw2_asm_output_data_uleb128 (0, NULL);
+#endif
+ }
+
/* Now write all the file names. */
for (i = 0; i < numfiles; i++)
{
@@ -10543,38 +11635,47 @@ output_file_names (void)
int ver;
long long cdt;
long siz;
- int maxfilelen = strlen (files[file_idx].path)
- + dirs[dir_idx].length
- + MAX_VMS_VERSION_LEN + 1;
+ int maxfilelen = (strlen (files[file_idx].path)
+ + dirs[dir_idx].length
+ + MAX_VMS_VERSION_LEN + 1);
char *filebuf = XALLOCAVEC (char, maxfilelen);
vms_file_stats_name (files[file_idx].path, 0, 0, 0, &ver);
snprintf (filebuf, maxfilelen, "%s;%d",
files[file_idx].path + dirs[dir_idx].length, ver);
- dw2_asm_output_nstring
- (filebuf, -1, "File Entry: %#x", (unsigned) i + 1);
+ output_line_string (str_form, filebuf, "File Entry", (unsigned) i + 1);
/* Include directory index. */
- dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL);
+ if (dwarf_version >= 5 && idx_form != DW_FORM_udata)
+ dw2_asm_output_data (idx_form == DW_FORM_data1 ? 1 : 2,
+ dir_idx + idx_offset, NULL);
+ else
+ dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL);
/* Modification time. */
- dw2_asm_output_data_uleb128
- ((vms_file_stats_name (files[file_idx].path, &cdt, 0, 0, 0) == 0)
- ? cdt : 0,
- NULL);
+ dw2_asm_output_data_uleb128 ((vms_file_stats_name (files[file_idx].path,
+ &cdt, 0, 0, 0) == 0)
+ ? cdt : 0, NULL);
/* File length in bytes. */
- dw2_asm_output_data_uleb128
- ((vms_file_stats_name (files[file_idx].path, 0, &siz, 0, 0) == 0)
- ? siz : 0,
- NULL);
+ dw2_asm_output_data_uleb128 ((vms_file_stats_name (files[file_idx].path,
+ 0, &siz, 0, 0) == 0)
+ ? siz : 0, NULL);
#else
- dw2_asm_output_nstring (files[file_idx].path + dirs[dir_idx].length, -1,
- "File Entry: %#x", (unsigned) i + 1);
+ output_line_string (str_form,
+ files[file_idx].path + dirs[dir_idx].length,
+ "File Entry", (unsigned) i + 1);
/* Include directory index. */
- dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL);
+ if (dwarf_version >= 5 && idx_form != DW_FORM_udata)
+ dw2_asm_output_data (idx_form == DW_FORM_data1 ? 1 : 2,
+ dir_idx + idx_offset, NULL);
+ else
+ dw2_asm_output_data_uleb128 (dir_idx + idx_offset, NULL);
+
+ if (dwarf_version >= 5)
+ continue;
/* Modification time. */
dw2_asm_output_data_uleb128 (0, NULL);
@@ -10584,7 +11685,8 @@ output_file_names (void)
#endif /* VMS_DEBUGGING_INFO */
}
- dw2_asm_output_data (1, 0, "End file name table");
+ if (dwarf_version < 5)
+ dw2_asm_output_data (1, 0, "End file name table");
}
@@ -10708,8 +11810,6 @@ output_line_info (bool prologue_only)
static unsigned int generation;
char l1[MAX_ARTIFICIAL_LABEL_BYTES], l2[MAX_ARTIFICIAL_LABEL_BYTES];
char p1[MAX_ARTIFICIAL_LABEL_BYTES], p2[MAX_ARTIFICIAL_LABEL_BYTES];
- /* We don't support DWARFv5 line tables yet. */
- int ver = dwarf_version < 5 ? dwarf_version : 4;
bool saw_one = false;
int opc;
@@ -10729,7 +11829,12 @@ output_line_info (bool prologue_only)
ASM_OUTPUT_LABEL (asm_out_file, l1);
- dw2_asm_output_data (2, ver, "DWARF Version");
+ dw2_asm_output_data (2, dwarf_version, "DWARF Version");
+ if (dwarf_version >= 5)
+ {
+ dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size");
+ dw2_asm_output_data (1, 0, "Segment Size");
+ }
dw2_asm_output_delta (DWARF_OFFSET_SIZE, p2, p1, "Prolog Length");
ASM_OUTPUT_LABEL (asm_out_file, p1);
@@ -10743,7 +11848,7 @@ output_line_info (bool prologue_only)
and don't let the target override. */
dw2_asm_output_data (1, 1, "Minimum Instruction Length");
- if (ver >= 4)
+ if (dwarf_version >= 4)
dw2_asm_output_data (1, DWARF_LINE_DEFAULT_MAX_OPS_PER_INSN,
"Maximum Operations Per Instruction");
dw2_asm_output_data (1, DWARF_LINE_DEFAULT_IS_STMT_START,
@@ -11468,8 +12573,20 @@ modified_type_die (tree type, int cv_quals, bool reverse,
copy was created to help us keep track of typedef names) and
that copy might have a different TYPE_UID from the original
..._TYPE node. */
- if (TREE_CODE (type) != VECTOR_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ /* For function/method types, can't just use type_main_variant here,
+ because that can have different ref-qualifiers for C++,
+ but try to canonicalize. */
+ tree main = TYPE_MAIN_VARIANT (type);
+ for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
+ if (check_base_type (t, main) && check_lang_type (t, type))
+ return lookup_type_die (t);
+ return lookup_type_die (type);
+ }
+ else if (TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE)
return lookup_type_die (type_main_variant (type));
else
/* Vectors have the debugging information in the type,
@@ -12587,13 +13704,13 @@ convert_descriptor_to_mode (machine_mode mode, dw_loc_descr_ref op)
if (GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE)
{
- add_loc_descr (&op, new_loc_descr (DW_OP_GNU_convert, 0, 0));
+ add_loc_descr (&op, new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0));
return op;
}
type_die = base_type_for_mode (outer_mode, 1);
if (type_die == NULL)
return NULL;
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -12634,6 +13751,7 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
return NULL;
if (dwarf_strict
+ && dwarf_version < 5
&& (!SCALAR_INT_MODE_P (op_mode)
|| GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE))
return NULL;
@@ -12657,12 +13775,12 @@ scompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
if (type_die == NULL)
return NULL;
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
add_loc_descr (&op0, cvt);
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -12744,7 +13862,9 @@ ucompare_loc_descriptor (enum dwarf_location_atom op, rtx rtl,
if (!SCALAR_INT_MODE_P (op_mode))
return NULL;
- if (dwarf_strict && GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE)
+ if (dwarf_strict
+ && dwarf_version < 5
+ && GET_MODE_SIZE (op_mode) > DWARF2_ADDR_SIZE)
return NULL;
op0 = mem_loc_descriptor (XEXP (rtl, 0), op_mode, mem_mode,
@@ -12808,6 +13928,7 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
dw_loc_descr_ref bra_node, drop_node;
if (dwarf_strict
+ && dwarf_version < 5
&& (!SCALAR_INT_MODE_P (mode)
|| GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE))
return NULL;
@@ -12857,12 +13978,12 @@ minmax_loc_descriptor (rtx rtl, machine_mode mode,
dw_loc_descr_ref cvt;
if (type_die == NULL)
return NULL;
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
add_loc_descr (&op0, cvt);
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -12908,12 +14029,12 @@ typed_binop (enum dwarf_location_atom op, rtx rtl, dw_die_ref type_die,
VAR_INIT_STATUS_INITIALIZED);
if (op0 == NULL || op1 == NULL)
return NULL;
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
add_loc_descr (&op0, cvt);
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -13381,7 +14502,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
mem_mode, initialized);
break;
}
- if (dwarf_strict)
+ if (dwarf_strict && dwarf_version < 5)
break;
if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (inner)))
break;
@@ -13407,9 +14528,9 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
}
if (GET_MODE_SIZE (mode)
!= GET_MODE_SIZE (GET_MODE (inner)))
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
else
- cvt = new_loc_descr (DW_OP_GNU_reinterpret, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_reinterpret), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -13418,7 +14539,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
&& GET_MODE_SIZE (mode) <= DWARF2_ADDR_SIZE)
{
/* Convert it to untyped afterwards. */
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
add_loc_descr (&mem_loc_result, cvt);
}
}
@@ -13437,7 +14558,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
dw_die_ref type_die;
unsigned int dbx_regnum;
- if (dwarf_strict)
+ if (dwarf_strict && dwarf_version < 5)
break;
if (REGNO (rtl) > FIRST_PSEUDO_REGISTER)
break;
@@ -13448,7 +14569,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
dbx_regnum = dbx_reg_number (rtl);
if (dbx_regnum == IGNORED_DWARF_REGNUM)
break;
- mem_loc_result = new_loc_descr (DW_OP_GNU_regval_type,
+ mem_loc_result = new_loc_descr (dwarf_OP (DW_OP_regval_type),
dbx_regnum, 0);
mem_loc_result->dw_loc_oprnd2.val_class = dw_val_class_die_ref;
mem_loc_result->dw_loc_oprnd2.v.val_die_ref.die = type_die;
@@ -13520,7 +14641,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
add_loc_descr (&mem_loc_result, int_loc_descriptor (shift));
add_loc_descr (&mem_loc_result, new_loc_descr (op, 0, 0));
}
- else if (!dwarf_strict)
+ else if (!dwarf_strict || dwarf_version >= 5)
{
dw_die_ref type_die1, type_die2;
dw_loc_descr_ref cvt;
@@ -13533,12 +14654,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
if (type_die2 == NULL)
break;
mem_loc_result = op0;
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die1;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
add_loc_descr (&mem_loc_result, cvt);
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die2;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -13570,13 +14691,13 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
dw_die_ref type_die;
dw_loc_descr_ref deref;
- if (dwarf_strict)
+ if (dwarf_strict && dwarf_version < 5)
return NULL;
type_die
= base_type_for_mode (mode, SCALAR_INT_MODE_P (mode));
if (type_die == NULL)
return NULL;
- deref = new_loc_descr (DW_OP_GNU_deref_type,
+ deref = new_loc_descr (dwarf_OP (DW_OP_deref_type),
GET_MODE_SIZE (mode), 0);
deref->dw_loc_oprnd2.val_class = dw_val_class_die_ref;
deref->dw_loc_oprnd2.v.val_die_ref.die = type_die;
@@ -13619,7 +14740,12 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
temp = new_addr_loc_descr (rtl, dtprel_true);
- mem_loc_result = new_loc_descr (DW_OP_GNU_push_tls_address, 0, 0);
+ /* We check for DWARF 5 here because gdb did not implement
+ DW_OP_form_tls_address until after 7.12. */
+ mem_loc_result = new_loc_descr ((dwarf_version >= 5
+ ? DW_OP_form_tls_address
+ : DW_OP_GNU_push_tls_address),
+ 0, 0);
add_loc_descr (&mem_loc_result, temp);
break;
@@ -13647,7 +14773,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
return 0;
case ENTRY_VALUE:
- if (dwarf_strict)
+ if (dwarf_strict && dwarf_version < 5)
return NULL;
if (REG_P (ENTRY_VALUE_EXP (rtl)))
{
@@ -13676,7 +14802,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
gcc_unreachable ();
if (op0 == NULL)
return NULL;
- mem_loc_result = new_loc_descr (DW_OP_GNU_entry_value, 0, 0);
+ mem_loc_result = new_loc_descr (dwarf_OP (DW_OP_entry_value), 0, 0);
mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_loc;
mem_loc_result->dw_loc_oprnd1.v.val_loc = op0;
break;
@@ -13747,7 +14873,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
goto do_binop;
case DIV:
- if (!dwarf_strict
+ if ((!dwarf_strict || dwarf_version >= 5)
&& SCALAR_INT_MODE_P (mode)
&& GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE)
{
@@ -13825,7 +14951,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
break;
case MOD:
- if (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE && !dwarf_strict)
+ if (GET_MODE_SIZE (mode) > DWARF2_ADDR_SIZE
+ && (!dwarf_strict || dwarf_version >= 5))
{
mem_loc_result = typed_binop (DW_OP_mod, rtl,
base_type_for_mode (mode, 0),
@@ -13851,7 +14978,8 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
break;
case UDIV:
- if (!dwarf_strict && SCALAR_INT_MODE_P (mode))
+ if ((!dwarf_strict || dwarf_version >= 5)
+ && SCALAR_INT_MODE_P (mode))
{
if (GET_MODE_CLASS (mode) > DWARF2_ADDR_SIZE)
{
@@ -13899,7 +15027,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
mem_loc_result = int_loc_descriptor (INTVAL (rtl));
break;
}
- if (!dwarf_strict
+ if ((!dwarf_strict || dwarf_version >= 5)
&& (GET_MODE_BITSIZE (mode) == HOST_BITS_PER_WIDE_INT
|| GET_MODE_BITSIZE (mode) == HOST_BITS_PER_DOUBLE_INT))
{
@@ -13912,20 +15040,20 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
if (INTVAL (rtl) >= 0
&& amode != BLKmode
&& trunc_int_for_mode (INTVAL (rtl), amode) == INTVAL (rtl)
- /* const DW_OP_GNU_convert <XXX> vs.
- DW_OP_GNU_const_type <XXX, 1, const>. */
+ /* const DW_OP_convert <XXX> vs.
+ DW_OP_const_type <XXX, 1, const>. */
&& size_of_int_loc_descriptor (INTVAL (rtl)) + 1 + 1
< (unsigned long) 1 + 1 + 1 + GET_MODE_SIZE (mode))
{
mem_loc_result = int_loc_descriptor (INTVAL (rtl));
- op0 = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ op0 = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
op0->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
op0->dw_loc_oprnd1.v.val_die_ref.die = type_die;
op0->dw_loc_oprnd1.v.val_die_ref.external = 0;
add_loc_descr (&mem_loc_result, op0);
return mem_loc_result;
}
- mem_loc_result = new_loc_descr (DW_OP_GNU_const_type, 0,
+ mem_loc_result = new_loc_descr (dwarf_OP (DW_OP_const_type), 0,
INTVAL (rtl));
mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
mem_loc_result->dw_loc_oprnd1.v.val_die_ref.die = type_die;
@@ -13943,7 +15071,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
break;
case CONST_DOUBLE:
- if (!dwarf_strict)
+ if (!dwarf_strict || dwarf_version >= 5)
{
dw_die_ref type_die;
@@ -13962,7 +15090,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
type_die = base_type_for_mode (mode, SCALAR_INT_MODE_P (mode));
if (type_die == NULL)
return NULL;
- mem_loc_result = new_loc_descr (DW_OP_GNU_const_type, 0, 0);
+ mem_loc_result = new_loc_descr (dwarf_OP (DW_OP_const_type), 0, 0);
mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
mem_loc_result->dw_loc_oprnd1.v.val_die_ref.die = type_die;
mem_loc_result->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -13990,14 +15118,14 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
break;
case CONST_WIDE_INT:
- if (!dwarf_strict)
+ if (!dwarf_strict || dwarf_version >= 5)
{
dw_die_ref type_die;
type_die = base_type_for_mode (mode, SCALAR_INT_MODE_P (mode));
if (type_die == NULL)
return NULL;
- mem_loc_result = new_loc_descr (DW_OP_GNU_const_type, 0, 0);
+ mem_loc_result = new_loc_descr (dwarf_OP (DW_OP_const_type), 0, 0);
mem_loc_result->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
mem_loc_result->dw_loc_oprnd1.v.val_die_ref.die = type_die;
mem_loc_result->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -14133,7 +15261,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
case UNSIGNED_FLOAT:
case FIX:
case UNSIGNED_FIX:
- if (!dwarf_strict)
+ if (!dwarf_strict || dwarf_version >= 5)
{
dw_die_ref type_die;
dw_loc_descr_ref cvt;
@@ -14151,7 +15279,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
GET_CODE (rtl) == UNSIGNED_FLOAT);
if (type_die == NULL)
break;
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -14160,7 +15288,7 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
type_die = base_type_for_mode (mode, GET_CODE (rtl) == UNSIGNED_FIX);
if (type_die == NULL)
break;
- cvt = new_loc_descr (DW_OP_GNU_convert, 0, 0);
+ cvt = new_loc_descr (dwarf_OP (DW_OP_convert), 0, 0);
cvt->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
cvt->dw_loc_oprnd1.v.val_die_ref.die = type_die;
cvt->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -14251,6 +15379,46 @@ mem_loc_descriptor (rtx rtl, machine_mode mode,
resolve_one_addr (&rtl);
goto symref;
+ /* RTL sequences inside PARALLEL record a series of DWARF operations for
+ the expression. An UNSPEC rtx represents a raw DWARF operation,
+ new_loc_descr is called for it to build the operation directly.
+ Otherwise mem_loc_descriptor is called recursively. */
+ case PARALLEL:
+ {
+ int index = 0;
+ dw_loc_descr_ref exp_result = NULL;
+
+ for (; index < XVECLEN (rtl, 0); index++)
+ {
+ rtx elem = XVECEXP (rtl, 0, index);
+ if (GET_CODE (elem) == UNSPEC)
+ {
+ /* Each DWARF operation UNSPEC contain two operands, if
+ one operand is not used for the operation, const0_rtx is
+ passed. */
+ gcc_assert (XVECLEN (elem, 0) == 2);
+
+ HOST_WIDE_INT dw_op = XINT (elem, 1);
+ HOST_WIDE_INT oprnd1 = INTVAL (XVECEXP (elem, 0, 0));
+ HOST_WIDE_INT oprnd2 = INTVAL (XVECEXP (elem, 0, 1));
+ exp_result
+ = new_loc_descr ((enum dwarf_location_atom) dw_op, oprnd1,
+ oprnd2);
+ }
+ else
+ exp_result
+ = mem_loc_descriptor (elem, mode, mem_mode,
+ VAR_INIT_STATUS_INITIALIZED);
+
+ if (!mem_loc_result)
+ mem_loc_result = exp_result;
+ else
+ add_loc_descr (&mem_loc_result, exp_result);
+ }
+
+ break;
+ }
+
default:
if (flag_checking)
{
@@ -14322,7 +15490,7 @@ concatn_loc_descriptor (rtx concatn, enum var_init_status initialized)
return cc_loc_result;
}
-/* Helper function for loc_descriptor. Return DW_OP_GNU_implicit_pointer
+/* Helper function for loc_descriptor. Return DW_OP_implicit_pointer
for DEBUG_IMPLICIT_PTR RTL. */
static dw_loc_descr_ref
@@ -14331,13 +15499,13 @@ implicit_ptr_descriptor (rtx rtl, HOST_WIDE_INT offset)
dw_loc_descr_ref ret;
dw_die_ref ref;
- if (dwarf_strict)
+ if (dwarf_strict && dwarf_version < 5)
return NULL;
gcc_assert (TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == VAR_DECL
|| TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == PARM_DECL
|| TREE_CODE (DEBUG_IMPLICIT_PTR_DECL (rtl)) == RESULT_DECL);
ref = lookup_decl_die (DEBUG_IMPLICIT_PTR_DECL (rtl));
- ret = new_loc_descr (DW_OP_GNU_implicit_pointer, 0, offset);
+ ret = new_loc_descr (dwarf_OP (DW_OP_implicit_pointer), 0, offset);
ret->dw_loc_oprnd2.val_class = dw_val_class_const;
if (ref)
{
@@ -15157,7 +16325,7 @@ cst_pool_loc_descr (tree loc)
static dw_loc_list_ref
loc_list_for_address_of_addr_expr_of_indirect_ref (tree loc, bool toplev,
- const loc_descr_context *context)
+ loc_descr_context *context)
{
tree obj, offset;
HOST_WIDE_INT bitsize, bitpos, bytepos;
@@ -15291,6 +16459,11 @@ struct loc_descr_context
/* Information about the DWARF procedure we are currently generating. NULL if
we are not generating a DWARF procedure. */
struct dwarf_procedure_info *dpi;
+ /* True if integral PLACEHOLDER_EXPR stands for the first argument passed
+ by consumer. Used for DW_TAG_generic_subrange attributes. */
+ bool placeholder_arg;
+ /* True if PLACEHOLDER_EXPR has been seen. */
+ bool placeholder_seen;
};
/* DWARF procedures generation
@@ -15400,8 +16573,23 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset,
/* If needed, relocate the picking offset with respect to the frame
offset. */
- if (l->dw_loc_opc == DW_OP_pick && l->frame_offset_rel)
+ if (l->frame_offset_rel)
{
+ unsigned HOST_WIDE_INT off;
+ switch (l->dw_loc_opc)
+ {
+ case DW_OP_pick:
+ off = l->dw_loc_oprnd1.v.val_unsigned;
+ break;
+ case DW_OP_dup:
+ off = 0;
+ break;
+ case DW_OP_over:
+ off = 1;
+ break;
+ default:
+ gcc_unreachable ();
+ }
/* frame_offset_ is the size of the current stack frame, including
incoming arguments. Besides, the arguments are pushed
right-to-left. Thus, in order to access the Nth argument from
@@ -15412,11 +16600,27 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset,
The targetted argument number (N) is already set as the operand,
and the number of temporaries can be computed with:
frame_offsets_ - dpi->args_count */
- l->dw_loc_oprnd1.v.val_unsigned += frame_offset_ - dpi->args_count;
+ off += frame_offset_ - dpi->args_count;
/* DW_OP_pick handles only offsets from 0 to 255 (inclusive)... */
- if (l->dw_loc_oprnd1.v.val_unsigned > 255)
+ if (off > 255)
return false;
+
+ if (off == 0)
+ {
+ l->dw_loc_opc = DW_OP_dup;
+ l->dw_loc_oprnd1.v.val_unsigned = 0;
+ }
+ else if (off == 1)
+ {
+ l->dw_loc_opc = DW_OP_over;
+ l->dw_loc_oprnd1.v.val_unsigned = 0;
+ }
+ else
+ {
+ l->dw_loc_opc = DW_OP_pick;
+ l->dw_loc_oprnd1.v.val_unsigned = off;
+ }
}
/* Update frame_offset according to the effect the current operation has
@@ -15467,7 +16671,6 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset,
case DW_OP_piece:
case DW_OP_deref_size:
case DW_OP_nop:
- case DW_OP_form_tls_address:
case DW_OP_bit_piece:
case DW_OP_implicit_value:
case DW_OP_stack_value:
@@ -15595,6 +16798,14 @@ resolve_args_picking_1 (dw_loc_descr_ref loc, unsigned initial_frame_offset,
break;
}
+ case DW_OP_implicit_pointer:
+ case DW_OP_entry_value:
+ case DW_OP_const_type:
+ case DW_OP_regval_type:
+ case DW_OP_deref_type:
+ case DW_OP_convert:
+ case DW_OP_reinterpret:
+ case DW_OP_form_tls_address:
case DW_OP_GNU_push_tls_address:
case DW_OP_GNU_uninit:
case DW_OP_GNU_encoded_addr:
@@ -15712,6 +16923,8 @@ function_to_dwarf_procedure (tree fndecl)
ctx.context_type = NULL_TREE;
ctx.base_decl = NULL_TREE;
ctx.dpi = &dpi;
+ ctx.placeholder_arg = false;
+ ctx.placeholder_seen = false;
dpi.fndecl = fndecl;
dpi.args_count = list_length (DECL_ARGUMENTS (fndecl));
loc_body = loc_descriptor_from_tree (tree_body, 0, &ctx);
@@ -15774,7 +16987,7 @@ function_to_dwarf_procedure (tree fndecl)
static dw_loc_list_ref
loc_list_from_tree_1 (tree loc, int want_address,
- const struct loc_descr_context *context)
+ struct loc_descr_context *context)
{
dw_loc_descr_ref ret = NULL, ret1 = NULL;
dw_loc_list_ref list_ret = NULL, list_ret1 = NULL;
@@ -15820,6 +17033,18 @@ loc_list_from_tree_1 (tree loc, int want_address,
else
return NULL;
}
+ /* For DW_TAG_generic_subrange attributes, PLACEHOLDER_EXPR stands for
+ the single argument passed by consumer. */
+ else if (context != NULL
+ && context->placeholder_arg
+ && INTEGRAL_TYPE_P (TREE_TYPE (loc))
+ && want_address == 0)
+ {
+ ret = new_loc_descr (DW_OP_pick, 0, 0);
+ ret->frame_offset_rel = 1;
+ context->placeholder_seen = true;
+ break;
+ }
else
expansion_failed (loc, NULL_RTX,
"PLACEHOLDER_EXPR for an unexpected type");
@@ -15924,8 +17149,11 @@ loc_list_from_tree_1 (tree loc, int want_address,
operand shouldn't be. */
if (DECL_EXTERNAL (loc) && !targetm.binds_local_p (loc))
return 0;
- dtprel = dtprel_true;
- tls_op = DW_OP_GNU_push_tls_address;
+ dtprel = dtprel_true;
+ /* We check for DWARF 5 here because gdb did not implement
+ DW_OP_form_tls_address until after 7.12. */
+ tls_op = (dwarf_version >= 5 ? DW_OP_form_tls_address
+ : DW_OP_GNU_push_tls_address);
}
else
{
@@ -16573,7 +17801,7 @@ loc_list_from_tree_1 (tree loc, int want_address,
static dw_loc_list_ref
loc_list_from_tree (tree loc, int want_address,
- const struct loc_descr_context *context)
+ struct loc_descr_context *context)
{
dw_loc_list_ref result = loc_list_from_tree_1 (loc, want_address, context);
@@ -16587,7 +17815,7 @@ loc_list_from_tree (tree loc, int want_address,
/* Same as above but return only single location expression. */
static dw_loc_descr_ref
loc_descriptor_from_tree (tree loc, int want_address,
- const struct loc_descr_context *context)
+ struct loc_descr_context *context)
{
dw_loc_list_ref ret = loc_list_from_tree (loc, want_address, context);
if (!ret)
@@ -16673,6 +17901,8 @@ type_byte_size (const_tree type, HOST_WIDE_INT *cst_size)
ctx.context_type = const_cast<tree> (type);
ctx.base_decl = NULL_TREE;
ctx.dpi = NULL;
+ ctx.placeholder_arg = false;
+ ctx.placeholder_seen = false;
type = TYPE_MAIN_VARIANT (type);
tree_size = TYPE_SIZE_UNIT (type);
@@ -16852,7 +18082,9 @@ field_byte_offset (const_tree decl, struct vlr_context *ctx,
struct loc_descr_context loc_ctx = {
ctx->struct_type, /* context_type */
NULL_TREE, /* base_decl */
- NULL /* dpi */
+ NULL, /* dpi */
+ false, /* placeholder_arg */
+ false /* placeholder_seen */
};
loc_result = loc_list_from_tree (tree_result, 0, &loc_ctx);
@@ -18245,12 +19477,12 @@ add_comp_dir_attribute (dw_die_ref die)
static void
add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
- int forms, const struct loc_descr_context *context)
+ int forms, struct loc_descr_context *context)
{
dw_die_ref context_die, decl_die;
dw_loc_list_ref list;
-
bool strip_conversions = true;
+ bool placeholder_seen = false;
while (strip_conversions)
switch (TREE_CODE (value))
@@ -18345,6 +19577,11 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
return;
list = loc_list_from_tree (value, 2, context);
+ if (context && context->placeholder_arg)
+ {
+ placeholder_seen = context->placeholder_seen;
+ context->placeholder_seen = false;
+ }
if (list == NULL || single_element_loc_list_p (list))
{
/* If this attribute is not a reference nor constant, it is
@@ -18353,6 +19590,14 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
dw_loc_list_ref list2 = loc_list_from_tree (value, 0, context);
if (list2 && single_element_loc_list_p (list2))
{
+ if (placeholder_seen)
+ {
+ struct dwarf_procedure_info dpi;
+ dpi.fndecl = NULL_TREE;
+ dpi.args_count = 1;
+ if (!resolve_args_picking (list2->expr, 1, &dpi))
+ return;
+ }
add_AT_loc (die, attr, list2->expr);
return;
}
@@ -18360,7 +19605,9 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
/* If that failed to give a single element location list, fall back to
outputting this as a reference... still if permitted. */
- if (list == NULL || (forms & dw_scalar_form_reference) == 0)
+ if (list == NULL
+ || (forms & dw_scalar_form_reference) == 0
+ || placeholder_seen)
return;
if (current_function_decl == 0)
@@ -18423,7 +19670,7 @@ lower_bound_default (void)
static void
add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
- tree bound, const struct loc_descr_context *context)
+ tree bound, struct loc_descr_context *context)
{
int dflt;
@@ -18454,7 +19701,8 @@ add_bound_info (dw_die_ref subrange_die, enum dwarf_attribute bound_attr,
encodings, GDB isn't ready yet to handle proper DWARF description
for self-referencial subrange bounds: let GNAT encodings do the
magic in such a case. */
- if (gnat_encodings != DWARF_GNAT_ENCODINGS_MINIMAL
+ if (is_ada ()
+ && gnat_encodings != DWARF_GNAT_ENCODINGS_MINIMAL
&& contains_placeholder_p (bound))
return;
@@ -18864,7 +20112,8 @@ add_linkage_name (dw_die_ref die, tree decl)
given decl, but only if it actually has a name. */
static void
-add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
+add_name_and_src_coords_attributes (dw_die_ref die, tree decl,
+ bool no_linkage_name)
{
tree decl_name;
@@ -18877,7 +20126,8 @@ add_name_and_src_coords_attributes (dw_die_ref die, tree decl)
if (! DECL_ARTIFICIAL (decl))
add_src_coords_attributes (die, decl);
- add_linkage_name (die, decl);
+ if (!no_linkage_name)
+ add_linkage_name (die, decl);
}
#ifdef VMS_DEBUGGING_INFO
@@ -19480,7 +20730,9 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
{
const dw_die_ref scope_die = scope_die_for (type, context_die);
const dw_die_ref array_die = new_die (DW_TAG_array_type, scope_die, type);
- const struct loc_descr_context context = { type, info->base_decl, NULL };
+ struct loc_descr_context context = { type, info->base_decl, NULL,
+ false, false };
+ enum dwarf_tag subrange_tag = DW_TAG_subrange_type;
int dim;
add_name_attribute (array_die, type_tag (type));
@@ -19528,13 +20780,23 @@ gen_descr_array_type_die (tree type, struct array_descr_info *info,
add_scalar_info (array_die, attr, info->stride, forms, &context);
}
}
+ if (dwarf_version >= 5)
+ {
+ if (info->rank)
+ {
+ add_scalar_info (array_die, DW_AT_rank, info->rank,
+ dw_scalar_form_constant
+ | dw_scalar_form_exprloc, &context);
+ subrange_tag = DW_TAG_generic_subrange;
+ context.placeholder_arg = true;
+ }
+ }
add_gnat_descriptive_type_attribute (array_die, type, context_die);
for (dim = 0; dim < info->ndimensions; dim++)
{
- dw_die_ref subrange_die
- = new_die (DW_TAG_subrange_type, array_die, NULL);
+ dw_die_ref subrange_die = new_die (subrange_tag, array_die, NULL);
if (info->dimen[dim].bounds_type)
add_type_attribute (subrange_die,
@@ -20325,7 +21587,7 @@ premark_types_used_by_global_vars (void)
->traverse<void *, premark_types_used_by_global_vars_helper> (NULL);
}
-/* Generate a DW_TAG_GNU_call_site DIE in function DECL under SUBR_DIE
+/* Generate a DW_TAG_call_site DIE in function DECL under SUBR_DIE
for CA_LOC call arg loc node. */
static dw_die_ref
@@ -20346,17 +21608,18 @@ gen_call_site_die (tree decl, dw_die_ref subr_die,
}
if (stmt_die == NULL)
stmt_die = subr_die;
- die = new_die (DW_TAG_GNU_call_site, stmt_die, NULL_TREE);
- add_AT_lbl_id (die, DW_AT_low_pc, ca_loc->label);
+ die = new_die (dwarf_TAG (DW_TAG_call_site), stmt_die, NULL_TREE);
+ add_AT_lbl_id (die, dwarf_AT (DW_AT_call_return_pc), ca_loc->label);
if (ca_loc->tail_call_p)
- add_AT_flag (die, DW_AT_GNU_tail_call, 1);
+ add_AT_flag (die, dwarf_AT (DW_AT_call_tail_call), 1);
if (ca_loc->symbol_ref)
{
dw_die_ref tdie = lookup_decl_die (SYMBOL_REF_DECL (ca_loc->symbol_ref));
if (tdie)
- add_AT_die_ref (die, DW_AT_abstract_origin, tdie);
+ add_AT_die_ref (die, dwarf_AT (DW_AT_call_origin), tdie);
else
- add_AT_addr (die, DW_AT_abstract_origin, ca_loc->symbol_ref, false);
+ add_AT_addr (die, dwarf_AT (DW_AT_call_origin), ca_loc->symbol_ref,
+ false);
}
return die;
}
@@ -20653,7 +21916,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
add_AT_flag (subr_die, DW_AT_deleted, 1);
/* If this is a C++11 defaulted special function member then
- generate a DW_AT_GNU_defaulted attribute. */
+ generate a DW_AT_defaulted attribute. */
if (dwarf_version >= 5 || !dwarf_strict)
{
int defaulted
@@ -20771,11 +22034,11 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
alignment offset. */
bool range_list_added = false;
add_ranges_by_labels (subr_die, fde->dw_fde_begin,
- fde->dw_fde_end, &range_list_added,
- false);
+ fde->dw_fde_end, &range_list_added,
+ false);
add_ranges_by_labels (subr_die, fde->dw_fde_second_begin,
fde->dw_fde_second_end,
- &range_list_added, false);
+ &range_list_added, false);
if (range_list_added)
add_ranges (NULL);
}
@@ -21022,7 +22285,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
location info. */
decls_for_scope (outer_scope, subr_die);
- if (call_arg_locations && !dwarf_strict)
+ if (call_arg_locations && (!dwarf_strict || dwarf_version >= 5))
{
struct call_arg_loc_node *ca_loc;
for (ca_loc = call_arg_locations; ca_loc; ca_loc = ca_loc->next)
@@ -21058,7 +22321,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
continue;
/* Get dynamic information about call target only if we
have no static information: we cannot generate both
- DW_AT_abstract_origin and DW_AT_GNU_call_site_target
+ DW_AT_call_origin and DW_AT_call_target
attributes. */
if (ca_loc->symbol_ref == NULL_RTX)
{
@@ -21108,13 +22371,14 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
continue;
if (die == NULL)
die = gen_call_site_die (decl, subr_die, ca_loc);
- cdie = new_die (DW_TAG_GNU_call_site_parameter, die,
+ cdie = new_die (dwarf_TAG (DW_TAG_call_site_parameter), die,
NULL_TREE);
if (reg != NULL)
add_AT_loc (cdie, DW_AT_location, reg);
else if (tdie != NULL)
- add_AT_die_ref (cdie, DW_AT_abstract_origin, tdie);
- add_AT_loc (cdie, DW_AT_GNU_call_site_value, val);
+ add_AT_die_ref (cdie, dwarf_AT (DW_AT_call_parameter),
+ tdie);
+ add_AT_loc (cdie, dwarf_AT (DW_AT_call_value), val);
if (next_arg != XEXP (arg, 1))
{
mode = GET_MODE (XEXP (XEXP (XEXP (arg, 1), 0), 1));
@@ -21125,7 +22389,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
mode, VOIDmode,
VAR_INIT_STATUS_INITIALIZED);
if (val != NULL)
- add_AT_loc (cdie, DW_AT_GNU_call_site_data_value, val);
+ add_AT_loc (cdie, dwarf_AT (DW_AT_call_data_value),
+ val);
}
}
if (die == NULL
@@ -21142,7 +22407,7 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
VOIDmode,
VAR_INIT_STATUS_INITIALIZED);
if (tval)
- add_AT_loc (die, DW_AT_GNU_call_site_target, tval);
+ add_AT_loc (die, dwarf_AT (DW_AT_call_target), tval);
else if (tlocc != NULL_RTX)
{
tval = mem_loc_descriptor (tlocc,
@@ -21151,7 +22416,8 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
VOIDmode,
VAR_INIT_STATUS_INITIALIZED);
if (tval)
- add_AT_loc (die, DW_AT_GNU_call_site_target_clobbered,
+ add_AT_loc (die,
+ dwarf_AT (DW_AT_call_target_clobbered),
tval);
}
}
@@ -21167,13 +22433,13 @@ gen_subprogram_die (tree decl, dw_die_ref context_die)
call_arg_loc_last = NULL;
if (tail_call_site_count >= 0
&& tail_call_site_count == tail_call_site_note_count
- && !dwarf_strict)
+ && (!dwarf_strict || dwarf_version >= 5))
{
if (call_site_count >= 0
&& call_site_count == call_site_note_count)
- add_AT_flag (subr_die, DW_AT_GNU_all_call_sites, 1);
+ add_AT_flag (subr_die, dwarf_AT (DW_AT_call_all_calls), 1);
else
- add_AT_flag (subr_die, DW_AT_GNU_all_tail_call_sites, 1);
+ add_AT_flag (subr_die, dwarf_AT (DW_AT_call_all_tail_calls), 1);
}
call_site_count = -1;
tail_call_site_count = -1;
@@ -21239,10 +22505,25 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
tree ultimate_origin;
dw_die_ref var_die;
dw_die_ref old_die = decl ? lookup_decl_die (decl) : NULL;
- dw_die_ref origin_die = NULL;
bool declaration = (DECL_EXTERNAL (decl_or_origin)
|| class_or_namespace_scope_p (context_die));
bool specialization_p = false;
+ bool no_linkage_name = false;
+
+ /* While C++ inline static data members have definitions inside of the
+ class, force the first DIE to be a declaration, then let gen_member_die
+ reparent it to the class context and call gen_variable_die again
+ to create the outside of the class DIE for the definition. */
+ if (!declaration
+ && old_die == NULL
+ && decl
+ && DECL_CONTEXT (decl)
+ && TYPE_P (DECL_CONTEXT (decl))
+ && lang_hooks.decls.decl_dwarf_attribute (decl, DW_AT_inline) != -1)
+ {
+ declaration = true;
+ no_linkage_name = true;
+ }
ultimate_origin = decl_ultimate_origin (decl_or_origin);
if (decl || ultimate_origin)
@@ -21399,7 +22680,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
var_die = new_die (DW_TAG_variable, context_die, decl);
if (origin != NULL)
- origin_die = add_abstract_origin_attribute (var_die, origin);
+ add_abstract_origin_attribute (var_die, origin);
/* Loop unrolling can create multiple blocks that refer to the same
static variable, so we must test for the DW_AT_declaration flag.
@@ -21430,7 +22711,7 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
}
}
else
- add_name_and_src_coords_attributes (var_die, decl);
+ add_name_and_src_coords_attributes (var_die, decl, no_linkage_name);
if ((origin == NULL && !specialization_p)
|| (origin != NULL
@@ -21490,9 +22771,18 @@ gen_variable_die (tree decl, tree origin, dw_die_ref context_die)
&& lang_hooks.decls.decl_dwarf_attribute (decl_or_origin,
DW_AT_const_expr) == 1
&& !get_AT (var_die, DW_AT_const_expr)
- && (origin_die == NULL || get_AT (origin_die, DW_AT_const_expr) == NULL)
&& !specialization_p)
add_AT_flag (var_die, DW_AT_const_expr, 1);
+
+ if (!dwarf_strict)
+ {
+ int inl = lang_hooks.decls.decl_dwarf_attribute (decl_or_origin,
+ DW_AT_inline);
+ if (inl != -1
+ && !get_AT (var_die, DW_AT_inline)
+ && !specialization_p)
+ add_AT_unsigned (var_die, DW_AT_inline, inl);
+ }
}
/* Generate a DIE to represent a named constant. */
@@ -21637,13 +22927,11 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
superblock = BLOCK_SUPERCONTEXT (chain);
}
if (attr != NULL
- && ((*ranges_table)[attr->dw_attr_val.v.val_offset
- / 2 / DWARF2_ADDR_SIZE].num
+ && ((*ranges_table)[attr->dw_attr_val.v.val_offset].num
== BLOCK_NUMBER (superblock))
&& BLOCK_FRAGMENT_CHAIN (superblock))
{
- unsigned long off = attr->dw_attr_val.v.val_offset
- / 2 / DWARF2_ADDR_SIZE;
+ unsigned long off = attr->dw_attr_val.v.val_offset;
unsigned long supercnt = 0, thiscnt = 0;
for (chain = BLOCK_FRAGMENT_CHAIN (superblock);
chain; chain = BLOCK_FRAGMENT_CHAIN (chain))
@@ -21657,19 +22945,22 @@ add_high_low_attributes (tree stmt, dw_die_ref die)
chain; chain = BLOCK_FRAGMENT_CHAIN (chain))
++thiscnt;
gcc_assert (supercnt >= thiscnt);
- add_AT_range_list (die, DW_AT_ranges,
- ((off + supercnt - thiscnt)
- * 2 * DWARF2_ADDR_SIZE),
- false);
+ add_AT_range_list (die, DW_AT_ranges, off + supercnt - thiscnt,
+ false);
+ note_rnglist_head (off + supercnt - thiscnt);
return;
}
- add_AT_range_list (die, DW_AT_ranges, add_ranges (stmt), false);
+ unsigned int offset = add_ranges (stmt, true);
+ add_AT_range_list (die, DW_AT_ranges, offset, false);
+ note_rnglist_head (offset);
+ bool prev_in_cold = BLOCK_IN_COLD_SECTION_P (stmt);
chain = BLOCK_FRAGMENT_CHAIN (stmt);
do
{
- add_ranges (chain);
+ add_ranges (chain, prev_in_cold != BLOCK_IN_COLD_SECTION_P (chain));
+ prev_in_cold = BLOCK_IN_COLD_SECTION_P (chain);
chain = BLOCK_FRAGMENT_CHAIN (chain);
}
while (chain);
@@ -21868,20 +23159,31 @@ gen_reference_type_die (tree type, dw_die_ref context_die)
}
#endif
-/* Generate a DIE for a pointer to a member type. */
+/* Generate a DIE for a pointer to a member type. TYPE can be an
+ OFFSET_TYPE, for a pointer to data member, or a RECORD_TYPE, for a
+ pointer to member function. */
static void
gen_ptr_to_mbr_type_die (tree type, dw_die_ref context_die)
{
- dw_die_ref ptr_die
- = new_die (DW_TAG_ptr_to_member_type,
- scope_die_for (type, context_die), type);
+ if (lookup_type_die (type))
+ return;
+
+ dw_die_ref ptr_die = new_die (DW_TAG_ptr_to_member_type,
+ scope_die_for (type, context_die), type);
equate_type_number_to_die (type, ptr_die);
add_AT_die_ref (ptr_die, DW_AT_containing_type,
lookup_type_die (TYPE_OFFSET_BASETYPE (type)));
add_type_attribute (ptr_die, TREE_TYPE (type), TYPE_UNQUALIFIED, false,
context_die);
+
+ if (TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE
+ && TREE_CODE (TREE_TYPE (type)) != METHOD_TYPE)
+ {
+ dw_loc_descr_ref op = new_loc_descr (DW_OP_plus, 0, 0);
+ add_AT_loc (ptr_die, DW_AT_use_location, op);
+ }
}
static char *producer_string;
@@ -22459,7 +23761,9 @@ gen_variant_part (tree variant_part_decl, struct vlr_context *vlr_ctx,
struct loc_descr_context ctx = {
vlr_ctx->struct_type, /* context_type */
NULL_TREE, /* base_decl */
- NULL /* dpi */
+ NULL, /* dpi */
+ false, /* placeholder_arg */
+ false /* placeholder_seen */
};
/* The FIELD_DECL node in STRUCT_TYPE that acts as the discriminant, or
@@ -22648,6 +23952,19 @@ gen_member_die (tree type, dw_die_ref context_die)
vlr_ctx.variant_part_offset = NULL_TREE;
gen_decl_die (member, NULL, &vlr_ctx, context_die);
}
+
+ /* For C++ inline static data members emit immediately a DW_TAG_variable
+ DIE that will refer to that DW_TAG_member through
+ DW_AT_specification. */
+ if (TREE_STATIC (member)
+ && (lang_hooks.decls.decl_dwarf_attribute (member, DW_AT_inline)
+ != -1))
+ {
+ int old_extern = DECL_EXTERNAL (member);
+ DECL_EXTERNAL (member) = 0;
+ gen_decl_die (member, NULL, NULL, comp_unit_die ());
+ DECL_EXTERNAL (member) = old_extern;
+ }
}
/* We do not keep type methods in type variants. */
@@ -22801,6 +24118,13 @@ gen_subroutine_type_die (tree type, dw_die_ref context_die)
if (get_AT (subr_die, DW_AT_name))
add_pubtype (type, subr_die);
+ if ((dwarf_version >= 5 || !dwarf_strict)
+ && lang_hooks.types.type_dwarf_attribute (type, DW_AT_reference) != -1)
+ add_AT_flag (subr_die, DW_AT_reference, 1);
+ if ((dwarf_version >= 5 || !dwarf_strict)
+ && lang_hooks.types.type_dwarf_attribute (type,
+ DW_AT_rvalue_reference) != -1)
+ add_AT_flag (subr_die, DW_AT_rvalue_reference, 1);
}
/* Generate a DIE for a type definition. */
@@ -23022,13 +24346,36 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
return;
}
+ if (lang_hooks.types.get_debug_type)
+ {
+ tree debug_type = lang_hooks.types.get_debug_type (type);
+
+ if (debug_type != NULL_TREE && debug_type != type)
+ {
+ gen_type_die_with_usage (debug_type, context_die, usage);
+ return;
+ }
+ }
+
/* We are going to output a DIE to represent the unqualified version
of this type (i.e. without any const or volatile qualifiers) so
get the main variant (i.e. the unqualified version) of this type
now. (Vectors and arrays are special because the debugging info is in the
- cloned type itself). */
- if (TREE_CODE (type) != VECTOR_TYPE
- && TREE_CODE (type) != ARRAY_TYPE)
+ cloned type itself. Similarly function/method types can contain extra
+ ref-qualification). */
+ if (TREE_CODE (type) == FUNCTION_TYPE
+ || TREE_CODE (type) == METHOD_TYPE)
+ {
+ /* For function/method types, can't use type_main_variant here,
+ because that can have different ref-qualifiers for C++,
+ but try to canonicalize. */
+ tree main = TYPE_MAIN_VARIANT (type);
+ for (tree t = main; t; t = TYPE_NEXT_VARIANT (t))
+ if (check_base_type (t, main) && check_lang_type (t, type))
+ type = t;
+ }
+ else if (TREE_CODE (type) != VECTOR_TYPE
+ && TREE_CODE (type) != ARRAY_TYPE)
type = type_main_variant (type);
/* If this is an array type with hidden descriptor, handle it first. */
@@ -23079,18 +24426,18 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
/* For these types, all that is required is that we output a DIE (or a
set of DIEs) to represent the "basis" type. */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_IND_USE);
+ DINFO_USAGE_IND_USE);
break;
case OFFSET_TYPE:
/* This code is used for C++ pointer-to-data-member types.
Output a description of the relevant class type. */
gen_type_die_with_usage (TYPE_OFFSET_BASETYPE (type), context_die,
- DINFO_USAGE_IND_USE);
+ DINFO_USAGE_IND_USE);
/* Output a description of the type of the object pointed to. */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_IND_USE);
+ DINFO_USAGE_IND_USE);
/* Now output a DIE to represent this pointer-to-data-member type
itself. */
@@ -23100,14 +24447,14 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
case FUNCTION_TYPE:
/* Force out return type (in case it wasn't forced out already). */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_DIR_USE);
+ DINFO_USAGE_DIR_USE);
gen_subroutine_type_die (type, context_die);
break;
case METHOD_TYPE:
/* Force out return type (in case it wasn't forced out already). */
gen_type_die_with_usage (TREE_TYPE (type), context_die,
- DINFO_USAGE_DIR_USE);
+ DINFO_USAGE_DIR_USE);
gen_subroutine_type_die (type, context_die);
break;
@@ -25165,7 +26512,7 @@ dwarf2out_define (unsigned int lineno ATTRIBUTE_UNUSED,
{
macinfo_entry e;
/* Insert a dummy first entry to be able to optimize the whole
- predefined macro block using DW_MACRO_GNU_transparent_include. */
+ predefined macro block using DW_MACRO_import. */
if (macinfo_table->is_empty () && lineno <= 1)
{
e.code = 0;
@@ -25192,7 +26539,7 @@ dwarf2out_undef (unsigned int lineno ATTRIBUTE_UNUSED,
{
macinfo_entry e;
/* Insert a dummy first entry to be able to optimize the whole
- predefined macro block using DW_MACRO_GNU_transparent_include. */
+ predefined macro block using DW_MACRO_import. */
if (macinfo_table->is_empty () && lineno <= 1)
{
e.code = 0;
@@ -25264,8 +26611,7 @@ output_macinfo_op (macinfo_entry *ref)
&& (debug_str_section->common.flags & SECTION_MERGE) != 0)
{
ref->code = ref->code == DW_MACINFO_define
- ? DW_MACRO_GNU_define_indirect
- : DW_MACRO_GNU_undef_indirect;
+ ? DW_MACRO_define_strp : DW_MACRO_undef_strp;
output_macinfo_op (ref);
return;
}
@@ -25276,16 +26622,16 @@ output_macinfo_op (macinfo_entry *ref)
(unsigned long) ref->lineno);
dw2_asm_output_nstring (ref->info, -1, "The macro");
break;
- case DW_MACRO_GNU_define_indirect:
- case DW_MACRO_GNU_undef_indirect:
+ case DW_MACRO_define_strp:
+ case DW_MACRO_undef_strp:
node = find_AT_string (ref->info);
gcc_assert (node
- && ((node->form == DW_FORM_strp)
- || (node->form == DW_FORM_GNU_str_index)));
+ && (node->form == DW_FORM_strp
+ || node->form == DW_FORM_GNU_str_index));
dw2_asm_output_data (1, ref->code,
- ref->code == DW_MACRO_GNU_define_indirect
- ? "Define macro indirect"
- : "Undefine macro indirect");
+ ref->code == DW_MACRO_define_strp
+ ? "Define macro strp"
+ : "Undefine macro strp");
dw2_asm_output_data_uleb128 (ref->lineno, "At line number %lu",
(unsigned long) ref->lineno);
if (node->form == DW_FORM_strp)
@@ -25296,8 +26642,8 @@ output_macinfo_op (macinfo_entry *ref)
dw2_asm_output_data_uleb128 (node->index, "The macro: \"%s\"",
ref->info);
break;
- case DW_MACRO_GNU_transparent_include:
- dw2_asm_output_data (1, ref->code, "Transparent include");
+ case DW_MACRO_import:
+ dw2_asm_output_data (1, ref->code, "Import");
ASM_GENERATE_INTERNAL_LABEL (label,
DEBUG_MACRO_SECTION_LABEL, ref->lineno);
dw2_asm_output_offset (DWARF_OFFSET_SIZE, label, NULL, NULL);
@@ -25313,7 +26659,7 @@ output_macinfo_op (macinfo_entry *ref)
other compilation unit .debug_macinfo sections. IDX is the first
index of a define/undef, return the number of ops that should be
emitted in a comdat .debug_macinfo section and emit
- a DW_MACRO_GNU_transparent_include entry referencing it.
+ a DW_MACRO_import entry referencing it.
If the define/undef entry should be emitted normally, return 0. */
static unsigned
@@ -25399,10 +26745,10 @@ optimize_macinfo_range (unsigned int idx, vec<macinfo_entry, va_gc> *files,
for (i = 0; i < 16; i++)
sprintf (tail + i * 2, "%02x", checksum[i] & 0xff);
- /* Construct a macinfo_entry for DW_MACRO_GNU_transparent_include
+ /* Construct a macinfo_entry for DW_MACRO_import
in the empty vector entry before the first define/undef. */
inc = &(*macinfo_table)[idx - 1];
- inc->code = DW_MACRO_GNU_transparent_include;
+ inc->code = DW_MACRO_import;
inc->lineno = 0;
inc->info = ggc_strdup (grp_name);
if (!*macinfo_htab)
@@ -25414,7 +26760,7 @@ optimize_macinfo_range (unsigned int idx, vec<macinfo_entry, va_gc> *files,
inc->code = 0;
inc->info = NULL;
/* If such an entry has been used before, just emit
- a DW_MACRO_GNU_transparent_include op. */
+ a DW_MACRO_import op. */
inc = *slot;
output_macinfo_op (inc);
/* And clear all macinfo_entry in the range to avoid emitting them
@@ -25460,8 +26806,8 @@ save_macinfo_strings (void)
&& (debug_str_section->common.flags & SECTION_MERGE) != 0)
set_indirect_string (find_AT_string (ref->info));
break;
- case DW_MACRO_GNU_define_indirect:
- case DW_MACRO_GNU_undef_indirect:
+ case DW_MACRO_define_strp:
+ case DW_MACRO_undef_strp:
set_indirect_string (find_AT_string (ref->info));
break;
default:
@@ -25485,15 +26831,16 @@ output_macinfo (void)
return;
/* output_macinfo* uses these interchangeably. */
- gcc_assert ((int) DW_MACINFO_define == (int) DW_MACRO_GNU_define
- && (int) DW_MACINFO_undef == (int) DW_MACRO_GNU_undef
- && (int) DW_MACINFO_start_file == (int) DW_MACRO_GNU_start_file
- && (int) DW_MACINFO_end_file == (int) DW_MACRO_GNU_end_file);
+ gcc_assert ((int) DW_MACINFO_define == (int) DW_MACRO_define
+ && (int) DW_MACINFO_undef == (int) DW_MACRO_undef
+ && (int) DW_MACINFO_start_file == (int) DW_MACRO_start_file
+ && (int) DW_MACINFO_end_file == (int) DW_MACRO_end_file);
/* For .debug_macro emit the section header. */
- if (!dwarf_strict)
+ if (!dwarf_strict || dwarf_version >= 5)
{
- dw2_asm_output_data (2, 4, "DWARF macro version number");
+ dw2_asm_output_data (2, dwarf_version >= 5 ? 5 : 4,
+ "DWARF macro version number");
if (DWARF_OFFSET_SIZE == 8)
dw2_asm_output_data (1, 3, "Flags: 64-bit, lineptr present");
else
@@ -25507,8 +26854,7 @@ output_macinfo (void)
/* In the first loop, it emits the primary .debug_macinfo section
and after each emitted op the macinfo_entry is cleared.
If a longer range of define/undef ops can be optimized using
- DW_MACRO_GNU_transparent_include, the
- DW_MACRO_GNU_transparent_include op is emitted and kept in
+ DW_MACRO_import, the DW_MACRO_import op is emitted and kept in
the vector before the first define/undef in the range and the
whole range of define/undef ops is not emitted and kept. */
for (i = 0; macinfo_table->iterate (i, &ref); i++)
@@ -25524,7 +26870,7 @@ output_macinfo (void)
break;
case DW_MACINFO_define:
case DW_MACINFO_undef:
- if (!dwarf_strict
+ if ((!dwarf_strict || dwarf_version >= 5)
&& HAVE_COMDAT_GROUP
&& vec_safe_length (files) != 1
&& i > 0
@@ -25558,16 +26904,15 @@ output_macinfo (void)
delete macinfo_htab;
macinfo_htab = NULL;
- /* If any DW_MACRO_GNU_transparent_include were used, on those
- DW_MACRO_GNU_transparent_include entries terminate the
- current chain and switch to a new comdat .debug_macinfo
+ /* If any DW_MACRO_import were used, on those DW_MACRO_import entries
+ terminate the current chain and switch to a new comdat .debug_macinfo
section and emit the define/undef entries within it. */
for (i = 0; macinfo_table->iterate (i, &ref); i++)
switch (ref->code)
{
case 0:
continue;
- case DW_MACRO_GNU_transparent_include:
+ case DW_MACRO_import:
{
char label[MAX_ARTIFICIAL_LABEL_BYTES];
tree comdat_key = get_identifier (ref->info);
@@ -25583,7 +26928,8 @@ output_macinfo (void)
ASM_OUTPUT_LABEL (asm_out_file, label);
ref->code = 0;
ref->info = NULL;
- dw2_asm_output_data (2, 4, "DWARF macro version number");
+ dw2_asm_output_data (2, dwarf_version >= 5 ? 5 : 4,
+ "DWARF macro version number");
if (DWARF_OFFSET_SIZE == 8)
dw2_asm_output_data (1, 1, "Flags: 64-bit");
else
@@ -25612,10 +26958,13 @@ init_sections_and_labels (void)
SECTION_DEBUG, NULL);
debug_abbrev_section = get_section (DEBUG_ABBREV_SECTION,
SECTION_DEBUG, NULL);
- debug_loc_section = get_section (DEBUG_LOC_SECTION,
+ debug_loc_section = get_section (dwarf_version >= 5
+ ? DEBUG_LOCLISTS_SECTION
+ : DEBUG_LOC_SECTION,
SECTION_DEBUG, NULL);
debug_macinfo_section_name
- = dwarf_strict ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
+ = (dwarf_strict && dwarf_version < 5)
+ ? DEBUG_MACINFO_SECTION : DEBUG_MACRO_SECTION;
debug_macinfo_section = get_section (debug_macinfo_section_name,
SECTION_DEBUG, NULL);
}
@@ -25647,12 +26996,15 @@ init_sections_and_labels (void)
NULL);
ASM_GENERATE_INTERNAL_LABEL (debug_skeleton_info_section_label,
DEBUG_SKELETON_INFO_SECTION_LABEL, 0);
- debug_loc_section = get_section (DEBUG_DWO_LOC_SECTION,
+ debug_loc_section = get_section (dwarf_version >= 5
+ ? DEBUG_DWO_LOCLISTS_SECTION
+ : DEBUG_DWO_LOC_SECTION,
SECTION_DEBUG | SECTION_EXCLUDE, NULL);
debug_str_dwo_section = get_section (DEBUG_STR_DWO_SECTION,
DEBUG_STR_DWO_SECTION_FLAGS, NULL);
debug_macinfo_section_name
- = dwarf_strict ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
+ = (dwarf_strict && dwarf_version < 5)
+ ? DEBUG_DWO_MACINFO_SECTION : DEBUG_DWO_MACRO_SECTION;
debug_macinfo_section = get_section (debug_macinfo_section_name,
SECTION_DEBUG | SECTION_EXCLUDE,
NULL);
@@ -25667,7 +27019,13 @@ init_sections_and_labels (void)
SECTION_DEBUG, NULL);
debug_str_section = get_section (DEBUG_STR_SECTION,
DEBUG_STR_SECTION_FLAGS, NULL);
- debug_ranges_section = get_section (DEBUG_RANGES_SECTION,
+ if (!dwarf_split_debug_info && !DWARF2_ASM_LINE_DEBUG_INFO)
+ debug_line_str_section = get_section (DEBUG_LINE_STR_SECTION,
+ DEBUG_STR_SECTION_FLAGS, NULL);
+
+ debug_ranges_section = get_section (dwarf_version >= 5
+ ? DEBUG_RNGLISTS_SECTION
+ : DEBUG_RANGES_SECTION,
SECTION_DEBUG, NULL);
debug_frame_section = get_section (DEBUG_FRAME_SECTION,
SECTION_DEBUG, NULL);
@@ -25680,10 +27038,13 @@ init_sections_and_labels (void)
DEBUG_LINE_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (ranges_section_label,
DEBUG_RANGES_SECTION_LABEL, 0);
+ if (dwarf_version >= 5 && dwarf_split_debug_info)
+ ASM_GENERATE_INTERNAL_LABEL (ranges_base_label,
+ DEBUG_RANGES_SECTION_LABEL, 1);
ASM_GENERATE_INTERNAL_LABEL (debug_addr_section_label,
DEBUG_ADDR_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (macinfo_section_label,
- dwarf_strict
+ (dwarf_strict && dwarf_version < 5)
? DEBUG_MACINFO_SECTION_LABEL
: DEBUG_MACRO_SECTION_LABEL, 0);
ASM_GENERATE_INTERNAL_LABEL (loc_section_label, DEBUG_LOC_SECTION_LABEL, 0);
@@ -25719,11 +27080,9 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED)
vec_alloc (decl_scope_table, 256);
/* Allocate the initial hunk of the abbrev_die_table. */
- abbrev_die_table = ggc_cleared_vec_alloc<dw_die_ref>
- (ABBREV_DIE_TABLE_INCREMENT);
- abbrev_die_table_allocated = ABBREV_DIE_TABLE_INCREMENT;
+ vec_alloc (abbrev_die_table, 256);
/* Zero-th entry is allocated, but unused. */
- abbrev_die_table_in_use = 1;
+ abbrev_die_table->quick_push (NULL);
/* Allocate the dwarf_proc_stack_usage_map. */
dwarf_proc_stack_usage_map = new hash_map<dw_die_ref, int>;
@@ -25843,12 +27202,12 @@ output_index_string (indirect_string_node **h, unsigned int *cur_idx)
htab_traverse. Emit one queued .debug_str string. */
int
-output_indirect_string (indirect_string_node **h, void *)
+output_indirect_string (indirect_string_node **h, enum dwarf_form form)
{
struct indirect_string_node *node = *h;
node->form = find_string_form (node);
- if (node->form == DW_FORM_strp && node->refcount > 0)
+ if (node->form == form && node->refcount > 0)
{
ASM_OUTPUT_LABEL (asm_out_file, node->label);
assemble_string (node->str, strlen (node->str) + 1);
@@ -25864,13 +27223,15 @@ output_indirect_strings (void)
{
switch_to_section (debug_str_section);
if (!dwarf_split_debug_info)
- debug_str_hash->traverse<void *, output_indirect_string> (NULL);
+ debug_str_hash->traverse<enum dwarf_form,
+ output_indirect_string> (DW_FORM_strp);
else
{
unsigned int offset = 0;
unsigned int cur_idx = 0;
- skeleton_debug_str_hash->traverse<void *, output_indirect_string> (NULL);
+ skeleton_debug_str_hash->traverse<enum dwarf_form,
+ output_indirect_string> (DW_FORM_strp);
switch_to_section (debug_str_offsets_section);
debug_str_hash->traverse_noresize
@@ -25971,6 +27332,9 @@ prune_unused_types_walk_loc_descr (dw_loc_descr_ref loc)
for (; loc != NULL; loc = loc->dw_loc_next)
switch (loc->dw_loc_opc)
{
+ case DW_OP_implicit_pointer:
+ case DW_OP_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_implicit_pointer:
case DW_OP_GNU_convert:
case DW_OP_GNU_reinterpret:
@@ -25980,16 +27344,20 @@ prune_unused_types_walk_loc_descr (dw_loc_descr_ref loc)
case DW_OP_call2:
case DW_OP_call4:
case DW_OP_call_ref:
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
case DW_OP_GNU_parameter_ref:
gcc_assert (loc->dw_loc_oprnd1.val_class == dw_val_class_die_ref);
prune_unused_types_mark (loc->dw_loc_oprnd1.v.val_die_ref.die, 1);
break;
+ case DW_OP_regval_type:
+ case DW_OP_deref_type:
case DW_OP_GNU_regval_type:
case DW_OP_GNU_deref_type:
gcc_assert (loc->dw_loc_oprnd2.val_class == dw_val_class_die_ref);
prune_unused_types_mark (loc->dw_loc_oprnd2.v.val_die_ref.die, 1);
break;
+ case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
gcc_assert (loc->dw_loc_oprnd1.val_class == dw_val_class_loc);
prune_unused_types_walk_loc_descr (loc->dw_loc_oprnd1.v.val_loc);
@@ -26451,18 +27819,24 @@ mark_base_types (dw_loc_descr_ref loc)
{
switch (loc->dw_loc_opc)
{
+ case DW_OP_regval_type:
+ case DW_OP_deref_type:
case DW_OP_GNU_regval_type:
case DW_OP_GNU_deref_type:
base_type = loc->dw_loc_oprnd2.v.val_die_ref.die;
break;
+ case DW_OP_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_convert:
case DW_OP_GNU_reinterpret:
if (loc->dw_loc_oprnd1.val_class == dw_val_class_unsigned_const)
continue;
/* FALLTHRU */
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
base_type = loc->dw_loc_oprnd1.v.val_die_ref.die;
break;
+ case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
mark_base_types (loc->dw_loc_oprnd1.v.val_loc);
continue;
@@ -26607,7 +27981,7 @@ resolve_one_addr (rtx *addr)
/* For STRING_CST, return SYMBOL_REF of its constant pool entry,
if possible, and create DW_TAG_dwarf_procedure that can be referenced
- from DW_OP_GNU_implicit_pointer if the string hasn't been seen yet. */
+ from DW_OP_implicit_pointer if the string hasn't been seen yet. */
static rtx
string_cst_pool_decl (tree t)
@@ -26649,7 +28023,7 @@ string_cst_pool_decl (tree t)
a DW_OP_addr followed by DW_OP_stack_value, either at the start
of exprloc or after DW_OP_{,bit_}piece, and val_addr can't be
resolved. Replace it (both DW_OP_addr and DW_OP_stack_value)
- with DW_OP_GNU_implicit_pointer if possible
+ with DW_OP_implicit_pointer if possible
and return true, if unsuccessful, return false. */
static bool
@@ -26688,7 +28062,7 @@ optimize_one_addr_into_implicit_ptr (dw_loc_descr_ref loc)
if (ref && (get_AT (ref, DW_AT_location)
|| get_AT (ref, DW_AT_const_value)))
{
- loc->dw_loc_opc = DW_OP_GNU_implicit_pointer;
+ loc->dw_loc_opc = dwarf_OP (DW_OP_implicit_pointer);
loc->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
loc->dw_loc_oprnd1.val_entry = NULL;
loc->dw_loc_oprnd1.v.val_die_ref.die = ref;
@@ -26721,7 +28095,7 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
|| prev->dw_loc_opc == DW_OP_bit_piece)
&& loc->dw_loc_next
&& loc->dw_loc_next->dw_loc_opc == DW_OP_stack_value
- && !dwarf_strict
+ && (!dwarf_strict || dwarf_version >= 5)
&& optimize_one_addr_into_implicit_ptr (loc))
break;
return false;
@@ -26736,8 +28110,8 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
if (!resolve_one_addr (&rtl))
return false;
remove_addr_table_entry (loc->dw_loc_oprnd1.val_entry);
- loc->dw_loc_oprnd1.val_entry =
- add_addr_table_entry (rtl, ate_kind_rtx);
+ loc->dw_loc_oprnd1.val_entry
+ = add_addr_table_entry (rtl, ate_kind_rtx);
}
break;
case DW_OP_const4u:
@@ -26764,6 +28138,7 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
&& !resolve_one_addr (&loc->dw_loc_oprnd2.v.val_addr))
return false;
break;
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
case DW_OP_GNU_parameter_ref:
if (loc->dw_loc_oprnd1.val_class == dw_val_class_decl_ref)
@@ -26777,17 +28152,25 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
loc->dw_loc_oprnd1.v.val_die_ref.external = 0;
}
break;
+ case DW_OP_const_type:
+ case DW_OP_regval_type:
+ case DW_OP_deref_type:
+ case DW_OP_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_const_type:
case DW_OP_GNU_regval_type:
case DW_OP_GNU_deref_type:
case DW_OP_GNU_convert:
case DW_OP_GNU_reinterpret:
while (loc->dw_loc_next
- && loc->dw_loc_next->dw_loc_opc == DW_OP_GNU_convert)
+ && (loc->dw_loc_next->dw_loc_opc == DW_OP_convert
+ || loc->dw_loc_next->dw_loc_opc == DW_OP_GNU_convert))
{
dw_die_ref base1, base2;
unsigned enc1, enc2, size1, size2;
- if (loc->dw_loc_opc == DW_OP_GNU_regval_type
+ if (loc->dw_loc_opc == DW_OP_regval_type
+ || loc->dw_loc_opc == DW_OP_deref_type
+ || loc->dw_loc_opc == DW_OP_GNU_regval_type
|| loc->dw_loc_opc == DW_OP_GNU_deref_type)
base1 = loc->dw_loc_oprnd2.v.val_die_ref.die;
else if (loc->dw_loc_oprnd1.val_class
@@ -26811,9 +28194,11 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
&& loc != keep)
|| enc1 == enc2))
{
- /* Optimize away next DW_OP_GNU_convert after
+ /* Optimize away next DW_OP_convert after
adjusting LOC's base type die reference. */
- if (loc->dw_loc_opc == DW_OP_GNU_regval_type
+ if (loc->dw_loc_opc == DW_OP_regval_type
+ || loc->dw_loc_opc == DW_OP_deref_type
+ || loc->dw_loc_opc == DW_OP_GNU_regval_type
|| loc->dw_loc_opc == DW_OP_GNU_deref_type)
loc->dw_loc_oprnd2.v.val_die_ref.die = base2;
else
@@ -26821,7 +28206,7 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
loc->dw_loc_next = loc->dw_loc_next->dw_loc_next;
continue;
}
- /* Don't change integer DW_OP_GNU_convert after e.g. floating
+ /* Don't change integer DW_OP_convert after e.g. floating
point typed stack entry. */
else if (enc1 != DW_ATE_unsigned && enc1 != DW_ATE_signed)
keep = loc->dw_loc_next;
@@ -26838,7 +28223,7 @@ resolve_addr_in_expr (dw_loc_descr_ref loc)
DW_OP_addr alone, which referred to DECL in DW_OP_addr's operand
and DW_OP_addr couldn't be resolved. resolve_addr has already
removed the DW_AT_location attribute. This function attempts to
- add a new DW_AT_location attribute with DW_OP_GNU_implicit_pointer
+ add a new DW_AT_location attribute with DW_OP_implicit_pointer
to it or DW_AT_const_value attribute, if possible. */
static void
@@ -26860,13 +28245,13 @@ optimize_location_into_implicit_ptr (dw_die_ref die, tree decl)
DW_AT_const_value instead. */
if (tree_add_const_value_attribute (die, init))
return;
- if (dwarf_strict)
+ if (dwarf_strict && dwarf_version < 5)
return;
/* If init is ADDR_EXPR or POINTER_PLUS_EXPR of ADDR_EXPR,
and ADDR_EXPR refers to a decl that has DW_AT_location or
DW_AT_const_value (but isn't addressable, otherwise
resolving the original DW_OP_addr wouldn't fail), see if
- we can add DW_OP_GNU_implicit_pointer. */
+ we can add DW_OP_implicit_pointer. */
STRIP_NOPS (init);
if (TREE_CODE (init) == POINTER_PLUS_EXPR
&& tree_fits_shwi_p (TREE_OPERAND (init, 1)))
@@ -26900,7 +28285,7 @@ optimize_location_into_implicit_ptr (dw_die_ref die, tree decl)
|| (!get_AT (ref, DW_AT_location)
&& !get_AT (ref, DW_AT_const_value)))
return;
- l = new_loc_descr (DW_OP_GNU_implicit_pointer, 0, offset);
+ l = new_loc_descr (dwarf_OP (DW_OP_implicit_pointer), 0, offset);
l->dw_loc_oprnd1.val_class = dw_val_class_die_ref;
l->dw_loc_oprnd1.v.val_die_ref.die = ref;
l->dw_loc_oprnd1.v.val_die_ref.external = 0;
@@ -26923,6 +28308,7 @@ non_dwarf_expression (dw_loc_descr_ref l)
case DW_OP_regx:
case DW_OP_implicit_value:
case DW_OP_stack_value:
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
case DW_OP_GNU_parameter_ref:
case DW_OP_piece:
@@ -27227,8 +28613,10 @@ resolve_addr (dw_die_ref die)
remove_AT (die, a->dw_attr);
ix--;
}
- if (die->die_tag == DW_TAG_GNU_call_site
- && a->dw_attr == DW_AT_abstract_origin)
+ if ((die->die_tag == DW_TAG_call_site
+ && a->dw_attr == DW_AT_call_origin)
+ || (die->die_tag == DW_TAG_GNU_call_site
+ && a->dw_attr == DW_AT_abstract_origin))
{
tree tdecl = SYMBOL_REF_DECL (a->dw_attr_val.v.val_addr);
dw_die_ref tdie = lookup_decl_die (tdecl);
@@ -27412,12 +28800,16 @@ hash_loc_operands (dw_loc_descr_ref loc, inchash::hash &hstate)
inchash::add_rtx (val1->val_entry->addr.rtl, hstate);
}
break;
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
hstate.add_int (val2->v.val_int);
break;
+ case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
hstate.add_object (val1->v.val_loc);
break;
+ case DW_OP_regval_type:
+ case DW_OP_deref_type:
case DW_OP_GNU_regval_type:
case DW_OP_GNU_deref_type:
{
@@ -27430,6 +28822,8 @@ hash_loc_operands (dw_loc_descr_ref loc, inchash::hash &hstate)
hstate.add_object (encoding);
}
break;
+ case DW_OP_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_convert:
case DW_OP_GNU_reinterpret:
if (val1->val_class == dw_val_class_unsigned_const)
@@ -27438,6 +28832,7 @@ hash_loc_operands (dw_loc_descr_ref loc, inchash::hash &hstate)
break;
}
/* FALLTHRU */
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
{
unsigned int byte_size
@@ -27446,7 +28841,8 @@ hash_loc_operands (dw_loc_descr_ref loc, inchash::hash &hstate)
= get_AT_unsigned (val1->v.val_die_ref.die, DW_AT_encoding);
hstate.add_object (byte_size);
hstate.add_object (encoding);
- if (loc->dw_loc_opc != DW_OP_GNU_const_type)
+ if (loc->dw_loc_opc != DW_OP_const_type
+ && loc->dw_loc_opc != DW_OP_GNU_const_type)
break;
hstate.add_object (val2->val_class);
switch (val2->val_class)
@@ -27639,13 +29035,16 @@ compare_loc_operands (dw_loc_descr_ref x, dw_loc_descr_ref y)
rtx ay1 = valy1->val_entry->addr.rtl;
return rtx_equal_p (ax1, ay1);
}
+ case DW_OP_implicit_pointer:
case DW_OP_GNU_implicit_pointer:
return valx1->val_class == dw_val_class_die_ref
&& valx1->val_class == valy1->val_class
&& valx1->v.val_die_ref.die == valy1->v.val_die_ref.die
&& valx2->v.val_int == valy2->v.val_int;
+ case DW_OP_entry_value:
case DW_OP_GNU_entry_value:
return compare_loc_operands (valx1->v.val_loc, valy1->v.val_loc);
+ case DW_OP_const_type:
case DW_OP_GNU_const_type:
if (valx1->v.val_die_ref.die != valy1->v.val_die_ref.die
|| valx2->val_class != valy2->val_class)
@@ -27668,10 +29067,14 @@ compare_loc_operands (dw_loc_descr_ref x, dw_loc_descr_ref y)
default:
gcc_unreachable ();
}
+ case DW_OP_regval_type:
+ case DW_OP_deref_type:
case DW_OP_GNU_regval_type:
case DW_OP_GNU_deref_type:
return valx1->v.val_int == valy1->v.val_int
&& valx2->v.val_die_ref.die == valy2->v.val_die_ref.die;
+ case DW_OP_convert:
+ case DW_OP_reinterpret:
case DW_OP_GNU_convert:
case DW_OP_GNU_reinterpret:
if (valx1->val_class != valy1->val_class)
@@ -27795,8 +29198,7 @@ index_location_lists (dw_die_ref die)
continue;
curr->begin_entry
- = add_addr_table_entry (xstrdup (curr->begin),
- ate_kind_label);
+ = add_addr_table_entry (xstrdup (curr->begin), ate_kind_label);
}
}
@@ -27878,6 +29280,7 @@ dwarf2out_finish (const char *)
{
comdat_type_node *ctnode;
dw_die_ref main_comp_unit_die;
+ unsigned char checksum[16];
/* Flush out any latecomers to the limbo party. */
flush_limbo_die_list ();
@@ -27923,6 +29326,8 @@ dwarf2out_finish (const char *)
{
limbo_die_node *cu;
main_comp_unit_die = gen_compile_unit_die (NULL);
+ if (dwarf_version >= 5)
+ main_comp_unit_die->die_tag = DW_TAG_skeleton_unit;
cu = limbo_die_list;
gcc_assert (cu->die == main_comp_unit_die);
limbo_die_list = limbo_die_list->next;
@@ -27999,17 +29404,24 @@ dwarf2out_finish (const char *)
if (have_macinfo)
add_AT_macptr (comp_unit_die (),
- dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
+ dwarf_version >= 5 ? DW_AT_macros
+ : dwarf_strict ? DW_AT_macro_info : DW_AT_GNU_macros,
macinfo_section_label);
if (dwarf_split_debug_info)
{
- /* optimize_location_lists calculates the size of the lists,
- so index them first, and assign indices to the entries.
- Although optimize_location_lists will remove entries from
- the table, it only does so for duplicates, and therefore
- only reduces ref_counts to 1. */
- index_location_lists (comp_unit_die ());
+ if (have_location_lists)
+ {
+ if (dwarf_version >= 5)
+ add_AT_loclistsptr (comp_unit_die (), DW_AT_loclists_base,
+ loc_section_label);
+ /* optimize_location_lists calculates the size of the lists,
+ so index them first, and assign indices to the entries.
+ Although optimize_location_lists will remove entries from
+ the table, it only does so for duplicates, and therefore
+ only reduces ref_counts to 1. */
+ index_location_lists (comp_unit_die ());
+ }
if (addr_index_table != NULL)
{
@@ -28020,8 +29432,14 @@ dwarf2out_finish (const char *)
}
}
+ loc_list_idx = 0;
if (have_location_lists)
- optimize_location_lists (comp_unit_die ());
+ {
+ optimize_location_lists (comp_unit_die ());
+ /* And finally assign indexes to the entries for -gsplit-dwarf. */
+ if (dwarf_version >= 5 && dwarf_split_debug_info)
+ assign_location_list_indexes (comp_unit_die ());
+ }
save_macinfo_strings ();
@@ -28041,7 +29459,7 @@ dwarf2out_finish (const char *)
/* Output all of the compilation units. We put the main one last so that
the offsets are available to output_pubnames. */
for (node = cu_die_list; node; node = node->next)
- output_comp_unit (node->die, 0);
+ output_comp_unit (node->die, 0, NULL);
hash_table<comdat_type_hasher> comdat_type_table (100);
for (ctnode = comdat_type_list; ctnode != NULL; ctnode = ctnode->next)
@@ -28075,9 +29493,11 @@ dwarf2out_finish (const char *)
if (dwarf_split_debug_info)
{
int mark;
- unsigned char checksum[16];
struct md5_ctx ctx;
+ if (dwarf_version >= 5 && !vec_safe_is_empty (ranges_table))
+ index_rnglists ();
+
/* Compute a checksum of the comp_unit to use as the dwo_id. */
md5_init_ctx (&ctx);
mark = 0;
@@ -28085,16 +29505,25 @@ dwarf2out_finish (const char *)
unmark_all_dies (comp_unit_die ());
md5_finish_ctx (&ctx, checksum);
- /* Use the first 8 bytes of the checksum as the dwo_id,
- and add it to both comp-unit DIEs. */
- add_AT_data8 (main_comp_unit_die, DW_AT_GNU_dwo_id, checksum);
- add_AT_data8 (comp_unit_die (), DW_AT_GNU_dwo_id, checksum);
+ if (dwarf_version < 5)
+ {
+ /* Use the first 8 bytes of the checksum as the dwo_id,
+ and add it to both comp-unit DIEs. */
+ add_AT_data8 (main_comp_unit_die, DW_AT_GNU_dwo_id, checksum);
+ add_AT_data8 (comp_unit_die (), DW_AT_GNU_dwo_id, checksum);
+ }
/* Add the base offset of the ranges table to the skeleton
comp-unit DIE. */
if (!vec_safe_is_empty (ranges_table))
- add_AT_lineptr (main_comp_unit_die, DW_AT_GNU_ranges_base,
- ranges_section_label);
+ {
+ if (dwarf_version >= 5)
+ add_AT_lineptr (main_comp_unit_die, DW_AT_rnglists_base,
+ ranges_base_label);
+ else
+ add_AT_lineptr (main_comp_unit_die, DW_AT_GNU_ranges_base,
+ ranges_section_label);
+ }
switch_to_section (debug_addr_section);
ASM_OUTPUT_LABEL (asm_out_file, debug_addr_section_label);
@@ -28103,13 +29532,14 @@ dwarf2out_finish (const char *)
/* Output the main compilation unit if non-empty or if .debug_macinfo
or .debug_macro will be emitted. */
- output_comp_unit (comp_unit_die (), have_macinfo);
+ output_comp_unit (comp_unit_die (), have_macinfo,
+ dwarf_split_debug_info ? checksum : NULL);
if (dwarf_split_debug_info && info_section_emitted)
- output_skeleton_debug_sections (main_comp_unit_die);
+ output_skeleton_debug_sections (main_comp_unit_die, checksum);
/* Output the abbreviation table. */
- if (abbrev_die_table_in_use != 1)
+ if (vec_safe_length (abbrev_die_table) != 1)
{
switch_to_section (debug_abbrev_section);
ASM_OUTPUT_LABEL (asm_out_file, abbrev_section_label);
@@ -28119,10 +29549,38 @@ dwarf2out_finish (const char *)
/* Output location list section if necessary. */
if (have_location_lists)
{
+ char l1[MAX_ARTIFICIAL_LABEL_BYTES];
+ char l2[MAX_ARTIFICIAL_LABEL_BYTES];
/* Output the location lists info. */
switch_to_section (debug_loc_section);
+ if (dwarf_version >= 5)
+ {
+ ASM_GENERATE_INTERNAL_LABEL (l1, DEBUG_LOC_SECTION_LABEL, 1);
+ ASM_GENERATE_INTERNAL_LABEL (l2, DEBUG_LOC_SECTION_LABEL, 2);
+ if (DWARF_INITIAL_LENGTH_SIZE - DWARF_OFFSET_SIZE == 4)
+ dw2_asm_output_data (4, 0xffffffff,
+ "Initial length escape value indicating "
+ "64-bit DWARF extension");
+ dw2_asm_output_delta (DWARF_OFFSET_SIZE, l2, l1,
+ "Length of Location Lists");
+ ASM_OUTPUT_LABEL (asm_out_file, l1);
+ dw2_asm_output_data (2, dwarf_version, "DWARF Version");
+ dw2_asm_output_data (1, DWARF2_ADDR_SIZE, "Address Size");
+ dw2_asm_output_data (1, 0, "Segment Size");
+ dw2_asm_output_data (4, dwarf_split_debug_info ? loc_list_idx : 0,
+ "Offset Entry Count");
+ }
ASM_OUTPUT_LABEL (asm_out_file, loc_section_label);
+ if (dwarf_version >= 5 && dwarf_split_debug_info)
+ {
+ unsigned int save_loc_list_idx = loc_list_idx;
+ loc_list_idx = 0;
+ output_loclists_offsets (comp_unit_die ());
+ gcc_assert (save_loc_list_idx == loc_list_idx);
+ }
output_location_lists (comp_unit_die ());
+ if (dwarf_version >= 5)
+ ASM_OUTPUT_LABEL (asm_out_file, l2);
}
output_pubtables ();
@@ -28141,9 +29599,10 @@ dwarf2out_finish (const char *)
/* Output ranges section if necessary. */
if (!vec_safe_is_empty (ranges_table))
{
- switch_to_section (debug_ranges_section);
- ASM_OUTPUT_LABEL (asm_out_file, ranges_section_label);
- output_ranges ();
+ if (dwarf_version >= 5)
+ output_rnglists ();
+ else
+ output_ranges ();
}
/* Have to end the macro section. */
@@ -28176,6 +29635,13 @@ dwarf2out_finish (const char *)
/* If we emitted any indirect strings, output the string table too. */
if (debug_str_hash || skeleton_debug_str_hash)
output_indirect_strings ();
+ if (debug_line_str_hash)
+ {
+ switch_to_section (debug_line_str_section);
+ const enum dwarf_form form = DW_FORM_line_strp;
+ debug_line_str_hash->traverse<enum dwarf_form,
+ output_indirect_string> (form);
+ }
}
/* Perform any cleanups needed after the early debug generation pass
@@ -28199,6 +29665,34 @@ dwarf2out_early_finish (const char *filename)
add_name_attribute (comp_unit_die (), remap_debug_filename (filename));
add_comp_dir_attribute (comp_unit_die ());
+ /* When emitting DWARF5 .debug_line_str, move DW_AT_name and
+ DW_AT_comp_dir into .debug_line_str section. */
+ if (!DWARF2_ASM_LINE_DEBUG_INFO
+ && dwarf_version >= 5
+ && DWARF5_USE_DEBUG_LINE_STR)
+ {
+ for (int i = 0; i < 2; i++)
+ {
+ dw_attr_node *a = get_AT (comp_unit_die (),
+ i ? DW_AT_comp_dir : DW_AT_name);
+ if (a == NULL
+ || AT_class (a) != dw_val_class_str
+ || strlen (AT_string (a)) + 1 <= DWARF_OFFSET_SIZE)
+ continue;
+
+ if (! debug_line_str_hash)
+ debug_line_str_hash
+ = hash_table<indirect_string_hasher>::create_ggc (10);
+
+ struct indirect_string_node *node
+ = find_AT_string_in_table (AT_string (a), debug_line_str_hash);
+ set_indirect_string (node);
+ node->form = DW_FORM_line_strp;
+ a->dw_attr_val.v.val_str->refcount--;
+ a->dw_attr_val.v.val_str = node;
+ }
+ }
+
/* With LTO early dwarf was really finished at compile-time, so make
sure to adjust the phase after annotating the LTRANS CU DIE. */
if (in_lto_p)
@@ -28304,12 +29798,14 @@ dwarf2out_c_finalize (void)
debug_pubnames_section = NULL;
debug_pubtypes_section = NULL;
debug_str_section = NULL;
+ debug_line_str_section = NULL;
debug_str_dwo_section = NULL;
debug_str_offsets_section = NULL;
debug_ranges_section = NULL;
debug_frame_section = NULL;
fde_vec = NULL;
debug_str_hash = NULL;
+ debug_line_str_hash = NULL;
skeleton_debug_str_hash = NULL;
dw2_string_counter = 0;
have_multiple_function_sections = false;
@@ -28332,8 +29828,6 @@ dwarf2out_c_finalize (void)
tail_call_site_count = -1;
cached_dw_loc_list_table = NULL;
abbrev_die_table = NULL;
- abbrev_die_table_allocated = 0;
- abbrev_die_table_in_use = 0;
delete dwarf_proc_stack_usage_map;
dwarf_proc_stack_usage_map = NULL;
line_info_label_num = 0;
@@ -28347,6 +29841,7 @@ dwarf2out_c_finalize (void)
macinfo_table = NULL;
ranges_table = NULL;
ranges_by_label = NULL;
+ rnglist_idx = 0;
have_location_lists = false;
loclabel_num = 0;
poc_label_num = 0;
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index abf05505900..ae1af572f5d 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -147,13 +147,17 @@ enum dw_val_class
dw_val_class_lineptr,
dw_val_class_str,
dw_val_class_macptr,
+ dw_val_class_loclistsptr,
dw_val_class_file,
dw_val_class_data8,
dw_val_class_decl_ref,
dw_val_class_vms_delta,
dw_val_class_high_pc,
dw_val_class_discr_value,
- dw_val_class_discr_list
+ dw_val_class_discr_list,
+ dw_val_class_const_implicit,
+ dw_val_class_unsigned_const_implicit,
+ dw_val_class_file_implicit
};
/* Describe a floating point constant value, or a vector constant value. */
@@ -198,7 +202,8 @@ struct GTY(()) dw_val_node {
dw_loc_list_ref GTY ((tag ("dw_val_class_loc_list"))) val_loc_list;
dw_loc_descr_ref GTY ((tag ("dw_val_class_loc"))) val_loc;
HOST_WIDE_INT GTY ((default)) val_int;
- unsigned HOST_WIDE_INT GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
+ unsigned HOST_WIDE_INT
+ GTY ((tag ("dw_val_class_unsigned_const"))) val_unsigned;
double_int GTY ((tag ("dw_val_class_const_double"))) val_double;
wide_int_ptr GTY ((tag ("dw_val_class_wide_int"))) val_wide;
dw_vec_const GTY ((tag ("dw_val_class_vec"))) val_vec;
@@ -212,6 +217,8 @@ struct GTY(()) dw_val_node {
char * GTY ((tag ("dw_val_class_lbl_id"))) val_lbl_id;
unsigned char GTY ((tag ("dw_val_class_flag"))) val_flag;
struct dwarf_file_data * GTY ((tag ("dw_val_class_file"))) val_file;
+ struct dwarf_file_data *
+ GTY ((tag ("dw_val_class_file_implicit"))) val_file_implicit;
unsigned char GTY ((tag ("dw_val_class_data8"))) val_data8[8];
tree GTY ((tag ("dw_val_class_decl_ref"))) val_decl_ref;
struct dw_val_vms_delta_union
@@ -234,9 +241,9 @@ struct GTY((chain_next ("%h.dw_loc_next"))) dw_loc_descr_node {
/* Used to distinguish DW_OP_addr with a direct symbol relocation
from DW_OP_addr with a dtp-relative symbol relocation. */
unsigned int dtprel : 1;
- /* For DW_OP_pick operations: true iff. it targets a DWARF prodecure
- argument. In this case, it needs to be relocated according to the current
- frame offset. */
+ /* For DW_OP_pick, DW_OP_dup and DW_OP_over operations: true iff.
+ it targets a DWARF prodecure argument. In this case, it needs to be
+ relocated according to the current frame offset. */
unsigned int frame_offset_rel : 1;
int dw_loc_addr;
dw_val_node dw_loc_oprnd1;
@@ -322,6 +329,7 @@ struct array_descr_info
tree allocated;
tree associated;
tree stride;
+ tree rank;
bool stride_in_bits;
struct array_descr_dimen
{
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 8afcfbec98a..9ea0c8fb888 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -3354,9 +3354,8 @@ prev_nonnote_insn (rtx_insn *insn)
not look inside SEQUENCEs. */
rtx_insn *
-prev_nonnote_insn_bb (rtx uncast_insn)
+prev_nonnote_insn_bb (rtx_insn *insn)
{
- rtx_insn *insn = safe_as_a <rtx_insn *> (uncast_insn);
while (insn)
{
@@ -4813,7 +4812,7 @@ emit_pattern_before (rtx pattern, rtx uncast_before, bool skip_debug_insns,
insnp, make_raw);
else
return emit_pattern_before_noloc (pattern, before,
- insnp ? before : NULL_RTX,
+ insnp ? before : NULL_RTX,
NULL, make_raw);
}
@@ -6169,17 +6168,19 @@ emit_copy_of_insn_after (rtx_insn *insn, rtx_insn *after)
which may be duplicated by the basic block reordering code. */
RTX_FRAME_RELATED_P (new_rtx) = RTX_FRAME_RELATED_P (insn);
+ /* Locate the end of existing REG_NOTES in NEW_RTX. */
+ rtx *ptail = &REG_NOTES (new_rtx);
+ while (*ptail != NULL_RTX)
+ ptail = &XEXP (*ptail, 1);
+
/* Copy all REG_NOTES except REG_LABEL_OPERAND since mark_jump_label
will make them. REG_LABEL_TARGETs are created there too, but are
supposed to be sticky, so we copy them. */
for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
if (REG_NOTE_KIND (link) != REG_LABEL_OPERAND)
{
- if (GET_CODE (link) == EXPR_LIST)
- add_reg_note (new_rtx, REG_NOTE_KIND (link),
- copy_insn_1 (XEXP (link, 0)));
- else
- add_shallow_copy_of_reg_note (new_rtx, link);
+ *ptail = duplicate_reg_note (link);
+ ptail = &XEXP (*ptail, 1);
}
INSN_CODE (new_rtx) = INSN_CODE (insn);
diff --git a/gcc/except.c b/gcc/except.c
index f0a1be0099f..e811b56074d 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -909,7 +909,7 @@ assign_filter_values (void)
first instruction of some existing BB and return the newly
produced block. */
static basic_block
-emit_to_new_bb_before (rtx_insn *seq, rtx insn)
+emit_to_new_bb_before (rtx_insn *seq, rtx_insn *insn)
{
rtx_insn *last;
basic_block bb;
diff --git a/gcc/expr.c b/gcc/expr.c
index 6420e278f3d..0b0946de345 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -2591,7 +2591,7 @@ maybe_emit_group_store (rtx x, tree type)
This is used on targets that return BLKmode values in registers. */
-void
+static void
copy_blkmode_from_reg (rtx target, rtx srcreg, tree type)
{
unsigned HOST_WIDE_INT bytes = int_size_in_bytes (type);
@@ -7681,10 +7681,6 @@ expand_operands (tree exp0, tree exp1, rtx target, rtx *op0, rtx *op1,
}
else
{
- /* If we need to preserve evaluation order, copy exp0 into its own
- temporary variable so that it can't be clobbered by exp1. */
- if (flag_evaluation_order && TREE_SIDE_EFFECTS (exp1))
- exp0 = save_expr (exp0);
*op0 = expand_expr (exp0, target, VOIDmode, modifier);
*op1 = expand_expr (exp1, NULL_RTX, VOIDmode, modifier);
}
@@ -10422,10 +10418,35 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
{
if (bitpos == 0
&& bitsize == GET_MODE_BITSIZE (GET_MODE (op0))
- && COMPLEX_MODE_P (mode1))
+ && COMPLEX_MODE_P (mode1)
+ && COMPLEX_MODE_P (GET_MODE (op0))
+ && (GET_MODE_PRECISION (GET_MODE_INNER (mode1))
+ == GET_MODE_PRECISION (GET_MODE_INNER (GET_MODE (op0)))))
{
if (reversep)
op0 = flip_storage_order (GET_MODE (op0), op0);
+ if (mode1 != GET_MODE (op0))
+ {
+ rtx parts[2];
+ for (int i = 0; i < 2; i++)
+ {
+ rtx op = read_complex_part (op0, i != 0);
+ if (GET_CODE (op) == SUBREG)
+ op = force_reg (GET_MODE (op), op);
+ rtx temp = gen_lowpart_common (GET_MODE_INNER (mode1),
+ op);
+ if (temp)
+ op = temp;
+ else
+ {
+ if (!REG_P (op) && !MEM_P (op))
+ op = force_reg (GET_MODE (op), op);
+ op = gen_lowpart (GET_MODE_INNER (mode1), op);
+ }
+ parts[i] = op;
+ }
+ op0 = gen_rtx_CONCAT (mode1, parts[0], parts[1]);
+ }
return op0;
}
if (bitpos == 0
diff --git a/gcc/expr.h b/gcc/expr.h
index a77f6e53cd3..558721d7d8a 100644
--- a/gcc/expr.h
+++ b/gcc/expr.h
@@ -146,9 +146,6 @@ extern void emit_group_store (rtx, rtx, tree, int);
extern rtx maybe_emit_group_store (rtx, tree);
-/* Copy BLKmode object from a set of registers. */
-extern void copy_blkmode_from_reg (rtx, rtx, tree);
-
/* Mark REG as holding a parameter for the next CALL_INSN.
Mode is TYPE_MODE of the non-promoted parameter, or VOIDmode. */
extern void use_reg_mode (rtx *, rtx, machine_mode);
diff --git a/gcc/final.c b/gcc/final.c
index 36ef755aec8..5709d0e2406 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -214,7 +214,7 @@ static void leaf_renumber_regs (rtx_insn *);
static int alter_cond (rtx);
#endif
#ifndef ADDR_VEC_ALIGN
-static int final_addr_vec_align (rtx);
+static int final_addr_vec_align (rtx_insn *);
#endif
static int align_fuzz (rtx, rtx, int, unsigned);
static void collect_fn_hard_reg_usage (void);
@@ -513,7 +513,7 @@ default_jump_align_max_skip (rtx_insn *insn ATTRIBUTE_UNUSED)
#ifndef ADDR_VEC_ALIGN
static int
-final_addr_vec_align (rtx addr_vec)
+final_addr_vec_align (rtx_insn *addr_vec)
{
int align = GET_MODE_SIZE (GET_MODE (PATTERN (addr_vec)));
@@ -2323,6 +2323,7 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
/* Mark this block as output. */
TREE_ASM_WRITTEN (NOTE_BLOCK (insn)) = 1;
+ BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn)) = in_cold_section_p;
}
if (write_symbols == DBX_DEBUG
|| write_symbols == SDB_DEBUG)
@@ -2355,6 +2356,8 @@ final_scan_insn (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED,
if (!DECL_IGNORED_P (current_function_decl))
debug_hooks->end_block (high_block_linenum, n);
+ gcc_assert (BLOCK_IN_COLD_SECTION_P (NOTE_BLOCK (insn))
+ == in_cold_section_p);
}
if (write_symbols == DBX_DEBUG
|| write_symbols == SDB_DEBUG)
diff --git a/gcc/fold-const-call.c b/gcc/fold-const-call.c
index 05a15f974e9..1b3a755df34 100644
--- a/gcc/fold-const-call.c
+++ b/gcc/fold-const-call.c
@@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
#include "case-cfn-macros.h"
#include "tm.h" /* For C[LT]Z_DEFINED_AT_ZERO. */
#include "builtins.h"
+#include "gimple-expr.h"
/* Functions that test for certain constant types, abstracting away the
decision about whether to check for overflow. */
@@ -57,7 +58,8 @@ complex_cst_p (tree t)
static inline bool
host_size_t_cst_p (tree t, size_t *size_out)
{
- if (integer_cst_p (t)
+ if (types_compatible_p (size_type_node, TREE_TYPE (t))
+ && integer_cst_p (t)
&& wi::min_precision (t, UNSIGNED) <= sizeof (size_t) * CHAR_BIT)
{
*size_out = tree_to_uhwi (t);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index fb6e45dd393..b78b6d855a1 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -80,10 +80,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree-ssanames.h"
#include "selftest.h"
-#ifndef LOAD_EXTEND_OP
-#define LOAD_EXTEND_OP(M) UNKNOWN
-#endif
-
/* Nonzero if we are folding constants inside an initializer; zero
otherwise. */
int folding_initializer = 0;
@@ -137,7 +133,6 @@ static tree fold_binary_op_with_conditional_arg (location_t,
tree, tree,
tree, tree, int);
static tree fold_div_compare (location_t, enum tree_code, tree, tree, tree);
-static bool reorder_operands_p (const_tree, const_tree);
static tree fold_negate_const (tree, tree);
static tree fold_not_const (const_tree, tree);
static tree fold_relational_const (enum tree_code, tree, tree, tree);
@@ -439,9 +434,7 @@ negate_expr_p (tree t)
&& ! TYPE_OVERFLOW_WRAPS (type)))
return false;
/* -(A + B) -> (-B) - A. */
- if (negate_expr_p (TREE_OPERAND (t, 1))
- && reorder_operands_p (TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1)))
+ if (negate_expr_p (TREE_OPERAND (t, 1)))
return true;
/* -(A + B) -> (-A) - B. */
return negate_expr_p (TREE_OPERAND (t, 0));
@@ -451,9 +444,7 @@ negate_expr_p (tree t)
return !HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
&& !HONOR_SIGNED_ZEROS (element_mode (type))
&& (! INTEGRAL_TYPE_P (type)
- || TYPE_OVERFLOW_WRAPS (type))
- && reorder_operands_p (TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1));
+ || TYPE_OVERFLOW_WRAPS (type));
case MULT_EXPR:
if (TYPE_UNSIGNED (type))
@@ -610,9 +601,7 @@ fold_negate_expr (location_t loc, tree t)
&& !HONOR_SIGNED_ZEROS (element_mode (type)))
{
/* -(A + B) -> (-B) - A. */
- if (negate_expr_p (TREE_OPERAND (t, 1))
- && reorder_operands_p (TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1)))
+ if (negate_expr_p (TREE_OPERAND (t, 1)))
{
tem = negate_expr (TREE_OPERAND (t, 1));
return fold_build2_loc (loc, MINUS_EXPR, type,
@@ -632,8 +621,7 @@ fold_negate_expr (location_t loc, tree t)
case MINUS_EXPR:
/* - (A - B) -> B - A */
if (!HONOR_SIGN_DEPENDENT_ROUNDING (element_mode (type))
- && !HONOR_SIGNED_ZEROS (element_mode (type))
- && reorder_operands_p (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1)))
+ && !HONOR_SIGNED_ZEROS (element_mode (type)))
return fold_build2_loc (loc, MINUS_EXPR, type,
TREE_OPERAND (t, 1), TREE_OPERAND (t, 0));
break;
@@ -5082,12 +5070,10 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
case EQ_EXPR:
case UNEQ_EXPR:
tem = fold_convert_loc (loc, arg1_type, arg1);
- return pedantic_non_lvalue_loc (loc,
- fold_convert_loc (loc, type,
- negate_expr (tem)));
+ return fold_convert_loc (loc, type, negate_expr (tem));
case NE_EXPR:
case LTGT_EXPR:
- return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
+ return fold_convert_loc (loc, type, arg1);
case UNGE_EXPR:
case UNGT_EXPR:
if (flag_trapping_math)
@@ -5098,7 +5084,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
if (TYPE_UNSIGNED (TREE_TYPE (arg1)))
break;
tem = fold_build1_loc (loc, ABS_EXPR, TREE_TYPE (arg1), arg1);
- return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
+ return fold_convert_loc (loc, type, tem);
case UNLE_EXPR:
case UNLT_EXPR:
if (flag_trapping_math)
@@ -5124,7 +5110,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
&& integer_zerop (arg01) && integer_zerop (arg2))
{
if (comp_code == NE_EXPR)
- return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
+ return fold_convert_loc (loc, type, arg1);
else if (comp_code == EQ_EXPR)
return build_zero_cst (type);
}
@@ -5170,20 +5156,12 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
tree comp_op1 = arg01;
tree comp_type = TREE_TYPE (comp_op0);
- /* Avoid adding NOP_EXPRs in case this is an lvalue. */
- if (TYPE_MAIN_VARIANT (comp_type) == TYPE_MAIN_VARIANT (type))
- {
- comp_type = type;
- comp_op0 = arg1;
- comp_op1 = arg2;
- }
-
switch (comp_code)
{
case EQ_EXPR:
- return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg2));
+ return fold_convert_loc (loc, type, arg2);
case NE_EXPR:
- return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, arg1));
+ return fold_convert_loc (loc, type, arg1);
case LE_EXPR:
case LT_EXPR:
case UNLE_EXPR:
@@ -5200,8 +5178,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
? fold_build2_loc (loc, MIN_EXPR, comp_type, comp_op0, comp_op1)
: fold_build2_loc (loc, MIN_EXPR, comp_type,
comp_op1, comp_op0);
- return pedantic_non_lvalue_loc (loc,
- fold_convert_loc (loc, type, tem));
+ return fold_convert_loc (loc, type, tem);
}
break;
case GE_EXPR:
@@ -5216,19 +5193,16 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
? fold_build2_loc (loc, MAX_EXPR, comp_type, comp_op0, comp_op1)
: fold_build2_loc (loc, MAX_EXPR, comp_type,
comp_op1, comp_op0);
- return pedantic_non_lvalue_loc (loc,
- fold_convert_loc (loc, type, tem));
+ return fold_convert_loc (loc, type, tem);
}
break;
case UNEQ_EXPR:
if (!HONOR_NANS (arg1))
- return pedantic_non_lvalue_loc (loc,
- fold_convert_loc (loc, type, arg2));
+ return fold_convert_loc (loc, type, arg2);
break;
case LTGT_EXPR:
if (!HONOR_NANS (arg1))
- return pedantic_non_lvalue_loc (loc,
- fold_convert_loc (loc, type, arg1));
+ return fold_convert_loc (loc, type, arg1);
break;
default:
gcc_assert (TREE_CODE_CLASS (comp_code) == tcc_comparison);
@@ -5267,8 +5241,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
fold_convert_loc (loc, TREE_TYPE (arg00),
arg2));
- return pedantic_non_lvalue_loc (loc,
- fold_convert_loc (loc, type, tem));
+ return fold_convert_loc (loc, type, tem);
}
break;
@@ -5285,8 +5258,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
tem = fold_build2_loc (loc, MIN_EXPR, TREE_TYPE (arg00), arg00,
fold_convert_loc (loc, TREE_TYPE (arg00),
arg2));
- return pedantic_non_lvalue_loc (loc,
- fold_convert_loc (loc, type, tem));
+ return fold_convert_loc (loc, type, tem);
}
break;
@@ -5303,7 +5275,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00,
fold_convert_loc (loc, TREE_TYPE (arg00),
arg2));
- return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
+ return fold_convert_loc (loc, type, tem);
}
break;
@@ -5319,7 +5291,7 @@ fold_cond_expr_with_comparison (location_t loc, tree type,
tem = fold_build2_loc (loc, MAX_EXPR, TREE_TYPE (arg00), arg00,
fold_convert_loc (loc, TREE_TYPE (arg00),
arg2));
- return pedantic_non_lvalue_loc (loc, fold_convert_loc (loc, type, tem));
+ return fold_convert_loc (loc, type, tem);
}
break;
case NE_EXPR:
@@ -6781,27 +6753,12 @@ fold_single_bit_test (location_t loc, enum tree_code code,
return NULL_TREE;
}
-/* Check whether we are allowed to reorder operands arg0 and arg1,
- such that the evaluation of arg1 occurs before arg0. */
-
-static bool
-reorder_operands_p (const_tree arg0, const_tree arg1)
-{
- if (! flag_evaluation_order)
- return true;
- if (TREE_CONSTANT (arg0) || TREE_CONSTANT (arg1))
- return true;
- return ! TREE_SIDE_EFFECTS (arg0)
- && ! TREE_SIDE_EFFECTS (arg1);
-}
-
/* Test whether it is preferable two swap two operands, ARG0 and
ARG1, for example because ARG0 is an integer constant and ARG1
- isn't. If REORDER is true, only recommend swapping if we can
- evaluate the operands in reverse order. */
+ isn't. */
bool
-tree_swap_operands_p (const_tree arg0, const_tree arg1, bool reorder)
+tree_swap_operands_p (const_tree arg0, const_tree arg1, bool)
{
if (CONSTANT_CLASS_P (arg1))
return 0;
@@ -6816,10 +6773,6 @@ tree_swap_operands_p (const_tree arg0, const_tree arg1, bool reorder)
if (TREE_CONSTANT (arg0))
return 1;
- if (reorder && flag_evaluation_order
- && (TREE_SIDE_EFFECTS (arg0) || TREE_SIDE_EFFECTS (arg1)))
- return 0;
-
/* It is preferable to swap two SSA_NAME to ensure a canonical form
for commutative and comparison operators. Ensuring a canonical
form allows the optimizers to find additional redundancies without
@@ -9244,8 +9197,7 @@ fold_binary_loc (location_t loc,
return build2_loc (loc, COMPOUND_EXPR, type, TREE_OPERAND (arg0, 0),
tem);
}
- if (TREE_CODE (arg1) == COMPOUND_EXPR
- && reorder_operands_p (arg0, TREE_OPERAND (arg1, 0)))
+ if (TREE_CODE (arg1) == COMPOUND_EXPR)
{
tem = fold_build2_loc (loc, code, type, op0,
fold_convert_loc (loc, TREE_TYPE (op1),
@@ -9734,8 +9686,7 @@ fold_binary_loc (location_t loc,
case MINUS_EXPR:
/* (-A) - B -> (-B) - A where B is easily negated and we can swap. */
if (TREE_CODE (arg0) == NEGATE_EXPR
- && negate_expr_p (op1)
- && reorder_operands_p (arg0, arg1))
+ && negate_expr_p (op1))
return fold_build2_loc (loc, MINUS_EXPR, type,
negate_expr (op1),
fold_convert_loc (loc, type,
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 625189fd8e8..bb0beb713e9 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,177 @@
+2016-11-09 Paul Thomas <pault@gcc.gnu.org>
+
+ * check.c (gfc_check_move_alloc): Prevent error that avoids
+ aliasing between to and from arguments from rejecting valid
+ code.
+
+2016-11-09 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/71894
+ * class.c (gfc_add_component_ref): Add safety checks to avoid ICE.
+
+2016-11-08 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/68440
+ * expr.c (check_alloc_comp_init): Loosen an assert.
+ * resolve.c (resolve_fl_parameter): Reject class parameters.
+
+2016-11-08 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/77596
+ * expr.c (gfc_check_pointer_assign): Add special check for procedure-
+ pointer component with absent interface.
+
+2016-11-07 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/78226
+ * expr.c (gfc_generate_initializer): Add where to EXPR_NULL
+ statement.
+ * iresolve.c (gfc_resolve_extends_type_of): Add where to
+ both arguments of the function.
+ * resolve.c (resolve_select_type): Add where to the
+ second argument of the new statement.
+
+2016-11-07 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/78226
+ * match.c (gfc_match_select_type): Add where for expr1.
+ * resolve.c (resolev_select_type): Add where for expr1 of new
+ statement.
+
+2016-11-06 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/78226
+ resolve.c (build_loc_call): Add location to return value.
+
+2016-11-06 Andre Vehreschild <vehre@gcc.gnu.org>
+
+ * expr.c (is_non_empty_structure_constructor): New function to detect
+ non-empty structure constructor.
+ (gfc_has_default_initializer): Analyse initializers.
+ * resolve.c (cond_init): Removed.
+ (resolve_allocate_expr): Removed dead code. Moved invariant code out
+ of the loop over all objects to allocate.
+ (resolve_allocate_deallocate): Added the invariant code remove from
+ resolve_allocate_expr.
+ * trans-array.c (gfc_array_allocate): Removed nullify of structure
+ components in favour of doing this in gfc_trans_allocate for both
+ scalars and arrays in the same place.
+ * trans-expr.c (gfc_trans_init_assign): Always using _vptr->copy for
+ class objects.
+ * trans-stmt.c (allocate_get_initializer): Get the initializer
+ expression for object allocated.
+ (gfc_trans_allocate): Nullify a derived type only, when no SOURCE=
+ or MOLD= is present preventing duplicate work. Moved the creation
+ of the init-expression here to prevent code for conditions that
+ can not occur on freshly allocated object, like checking for the need
+ to free allocatable components.
+
+2016-11-06 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/78221
+ * arith.c (gfc_complex2real): Change gfc_warning_now to
+ gfc_warning.
+
+2016-11-05 Paul Thomas <pault@gcc.gnu.org>
+
+ * check.c (gfc_check_move_alloc): Introduce error to prevent
+ aliasing between to and from arguments.
+
+2016-11-05 Janus Weil <janus@gcc.gnu.org>
+ Manuel Lopez-Ibanez <manu@gcc.gnu.org>
+
+ PR fortran/69495
+ * invoke.texi: Mention -Wpedantic as an alias of -pedantic.
+ * check.c (gfc_check_transfer): Mention responsible flag in warning
+ message.
+ * frontend-passes.c (do_warn_function_elimination): Ditto.
+ * resolve.c (resolve_elemental_actual): Ditto.
+ (resolve_operator): Ditto.
+ (warn_unused_fortran_label): Ditto.
+ * trans-common.c (translate_common): Ditto.
+
+2016-11-05 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/67564
+ * trans-expr.c (gfc_conv_class_to_class): Return _len component
+ of unlimited polymorphic entities.
+
+2016-11-04 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/64933
+ * primary.c (gfc_match_varspec): If selector expression is
+ unambiguously an array, make sure that the associate name
+ is an array and has an array spec. Modify the original
+ condition for doing this to exclude character types.
+
+2016-11-03 Fritz Reese <fritzoreese@gmail.com>
+
+ * gfortran.texi: Document.
+ * gfortran.h (gfc_dt): New field default_exp.
+ * primary.c (match_real_constant): Default exponent with -fdec.
+ * io.c (match_io): Set dt.default_exp with -fdec.
+ * ioparm.def (IOPARM_dt_default_exp): New.
+ * trans-io.c (build_dt): Set IOPARM_dt_default_exp with -fdec.
+
+2016-11-03 Fritz O. Reese <fritzoreese@gmail.com>
+
+ * decl.c (gfc_match_parameter): Allow omitted '()' with -std=legacy.
+ * parse.c (decode_statement): Match "parameter" before assignments.
+ * gfortran.texi: Document.
+
+2016-11-02 Fritz O. Reese <fritzoreese@gmail.com>
+
+ * lang.opt, invoke.texi: New argument -Wargument-mismatch.
+ * interface.c (compare_parameter, compare_actual_formal,
+ gfc_check_typebound_override, argument_rank_mismatch): Control argument
+ mismatch warnings with -Wargument-mismatch.
+ * resolve.c (resolve_structure_cons, resolve_global_procedure): Ditto.
+
+2016-11-02 Fritz Reese <fritzoreese@gmail.com>
+
+ * gfortran.h (gfc_error): New declaration for gfc_error with 'opt'.
+ * error.c (gfc_error): Add optional 'opt' argument.
+ * error.c (gfc_notify_std): Call fully-qualified gfc_error.
+
+2016-11-01 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/78178
+ * match.c (match_simple_where): Fill in locus for assigment
+ in simple WHERE statement.
+
+2016-11-01 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/69544
+ * match.c (gfc_match_where): Fill in locus for assigment
+ in simple WHERE statement.
+
+2016-10-31 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/54679
+ * io.c (check_format): Adjust checks for FMT_L to treat a zero
+ width as an extension, giving warnings or error as appropriate.
+ Improve messages.
+
+2016-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ * trans-types.c (gfc_get_array_descr_info): For -gdwarf-5 or
+ -gno-strict-dwarf, handle assumed rank arrays the way dwarf2out
+ expects.
+
+2016-10-30 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/67219
+ * arith.c (gfc_int2real): Change gfc_warning_now
+ to gfc_warning.
+ * primary.c (match_complex_constant): If there
+ is no comma, throw away any warning which might have
+ been issued by gfc_int2real.
+
+2016-10-28 Steven G. Kargl <kargl@gcc.gnu.org>
+
+ PR fortran/71891
+ * symbol.c (gfc_type_compatible): Fix typo.
+
2016-10-27 Jakub Jelinek <jakub@redhat.com>
PR fortran/78026
diff --git a/gcc/fortran/arith.c b/gcc/fortran/arith.c
index 8af75400d80..2781f103841 100644
--- a/gcc/fortran/arith.c
+++ b/gcc/fortran/arith.c
@@ -2072,11 +2072,11 @@ gfc_int2real (gfc_expr *src, int kind)
if (warn_conversion
&& wprecision_int_real (src->value.integer, result->value.real))
- gfc_warning_now (OPT_Wconversion, "Change of value in conversion "
- "from %qs to %qs at %L",
- gfc_typename (&src->ts),
- gfc_typename (&result->ts),
- &src->where);
+ gfc_warning (OPT_Wconversion, "Change of value in conversion "
+ "from %qs to %qs at %L",
+ gfc_typename (&src->ts),
+ gfc_typename (&result->ts),
+ &src->where);
return result;
}
@@ -2369,10 +2369,10 @@ gfc_complex2real (gfc_expr *src, int kind)
/* See if we discarded an imaginary part. */
if (mpfr_cmp_si (mpc_imagref (src->value.complex), 0) != 0)
{
- gfc_warning_now (w, "Non-zero imaginary part discarded "
- "in conversion from %qs to %qs at %L",
- gfc_typename(&src->ts), gfc_typename (&result->ts),
- &src->where);
+ gfc_warning (w, "Non-zero imaginary part discarded "
+ "in conversion from %qs to %qs at %L",
+ gfc_typename(&src->ts), gfc_typename (&result->ts),
+ &src->where);
did_warn = true;
}
diff --git a/gcc/fortran/check.c b/gcc/fortran/check.c
index ff5e80b9df5..265fe22594f 100644
--- a/gcc/fortran/check.c
+++ b/gcc/fortran/check.c
@@ -880,7 +880,7 @@ gfc_check_a_p (gfc_expr *a, gfc_expr *p)
if (a->ts.kind != p->ts.kind)
{
- if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
+ if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
&p->where))
return false;
}
@@ -1797,7 +1797,7 @@ gfc_check_count (gfc_expr *mask, gfc_expr *dim, gfc_expr *kind)
if (!kind_check (kind, 2, BT_INTEGER))
return false;
if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
+ "with KIND argument at %L",
gfc_current_intrinsic, &kind->where))
return false;
@@ -2127,11 +2127,11 @@ gfc_check_eoshift (gfc_expr *array, gfc_expr *shift, gfc_expr *boundary,
}
else if (boundary->rank == array->rank - 1)
{
- if (!gfc_check_conformance (shift, boundary,
+ if (!gfc_check_conformance (shift, boundary,
"arguments '%s' and '%s' for "
- "intrinsic %s",
- gfc_current_intrinsic_arg[1]->name,
- gfc_current_intrinsic_arg[2]->name,
+ "intrinsic %s",
+ gfc_current_intrinsic_arg[1]->name,
+ gfc_current_intrinsic_arg[2]->name,
gfc_current_intrinsic))
return false;
}
@@ -2156,7 +2156,7 @@ gfc_check_float (gfc_expr *a)
if ((a->ts.kind != gfc_default_integer_kind)
&& !gfc_notify_std (GFC_STD_GNU, "non-default INTEGER "
- "kind argument to %s intrinsic at %L",
+ "kind argument to %s intrinsic at %L",
gfc_current_intrinsic, &a->where))
return false;
@@ -2283,7 +2283,7 @@ gfc_check_iand (gfc_expr *i, gfc_expr *j)
if (i->ts.kind != j->ts.kind)
{
- if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
+ if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
&i->where))
return false;
}
@@ -2329,7 +2329,7 @@ gfc_check_ichar_iachar (gfc_expr *c, gfc_expr *kind)
return false;
if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
+ "with KIND argument at %L",
gfc_current_intrinsic, &kind->where))
return false;
@@ -2409,7 +2409,7 @@ gfc_check_ieor (gfc_expr *i, gfc_expr *j)
if (i->ts.kind != j->ts.kind)
{
- if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
+ if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
&i->where))
return false;
}
@@ -2432,7 +2432,7 @@ gfc_check_index (gfc_expr *string, gfc_expr *substring, gfc_expr *back,
if (!kind_check (kind, 3, BT_INTEGER))
return false;
if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
+ "with KIND argument at %L",
gfc_current_intrinsic, &kind->where))
return false;
@@ -2483,7 +2483,7 @@ gfc_check_ior (gfc_expr *i, gfc_expr *j)
if (i->ts.kind != j->ts.kind)
{
- if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
+ if (!gfc_notify_std (GFC_STD_GNU, "Different type kinds at %L",
&i->where))
return false;
}
@@ -2633,7 +2633,7 @@ gfc_check_lbound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
if (!kind_check (kind, 2, BT_INTEGER))
return false;
if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
+ "with KIND argument at %L",
gfc_current_intrinsic, &kind->where))
return false;
@@ -2678,7 +2678,7 @@ gfc_check_len_lentrim (gfc_expr *s, gfc_expr *kind)
if (!kind_check (kind, 1, BT_INTEGER))
return false;
if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
+ "with KIND argument at %L",
gfc_current_intrinsic, &kind->where))
return false;
@@ -2948,7 +2948,7 @@ gfc_check_min_max (gfc_actual_arglist *arg)
if (x->ts.type == BT_CHARACTER)
{
if (!gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with CHARACTER argument at %L",
+ "with CHARACTER argument at %L",
gfc_current_intrinsic, &x->where))
return false;
}
@@ -3118,10 +3118,10 @@ gfc_check_minloc_maxloc (gfc_actual_arglist *ap)
return false;
if (m != NULL
- && !gfc_check_conformance (a, m,
- "arguments '%s' and '%s' for intrinsic %s",
- gfc_current_intrinsic_arg[0]->name,
- gfc_current_intrinsic_arg[2]->name,
+ && !gfc_check_conformance (a, m,
+ "arguments '%s' and '%s' for intrinsic %s",
+ gfc_current_intrinsic_arg[0]->name,
+ gfc_current_intrinsic_arg[2]->name,
gfc_current_intrinsic))
return false;
@@ -3172,10 +3172,10 @@ check_reduction (gfc_actual_arglist *ap)
return false;
if (m != NULL
- && !gfc_check_conformance (a, m,
- "arguments '%s' and '%s' for intrinsic %s",
- gfc_current_intrinsic_arg[0]->name,
- gfc_current_intrinsic_arg[2]->name,
+ && !gfc_check_conformance (a, m,
+ "arguments '%s' and '%s' for intrinsic %s",
+ gfc_current_intrinsic_arg[0]->name,
+ gfc_current_intrinsic_arg[2]->name,
gfc_current_intrinsic))
return false;
@@ -3342,6 +3342,46 @@ gfc_check_move_alloc (gfc_expr *from, gfc_expr *to)
return false;
}
+ /* This is based losely on F2003 12.4.1.7. It is intended to prevent
+ the likes of to = sym->cmp1->cmp2 and from = sym->cmp1, where cmp1
+ and cmp2 are allocatable. After the allocation is transferred,
+ the 'to' chain is broken by the nullification of the 'from'. A bit
+ of reflection reveals that this can only occur for derived types
+ with recursive allocatable components. */
+ if (to->expr_type == EXPR_VARIABLE && from->expr_type == EXPR_VARIABLE
+ && !strcmp (to->symtree->n.sym->name, from->symtree->n.sym->name))
+ {
+ gfc_ref *to_ref, *from_ref;
+ to_ref = to->ref;
+ from_ref = from->ref;
+ bool aliasing = true;
+
+ for (; from_ref && to_ref;
+ from_ref = from_ref->next, to_ref = to_ref->next)
+ {
+ if (to_ref->type != from->ref->type)
+ aliasing = false;
+ else if (to_ref->type == REF_ARRAY
+ && to_ref->u.ar.type != AR_FULL
+ && from_ref->u.ar.type != AR_FULL)
+ /* Play safe; assume sections and elements are different. */
+ aliasing = false;
+ else if (to_ref->type == REF_COMPONENT
+ && to_ref->u.c.component != from_ref->u.c.component)
+ aliasing = false;
+
+ if (!aliasing)
+ break;
+ }
+
+ if (aliasing)
+ {
+ gfc_error ("The FROM and TO arguments at %L violate aliasing "
+ "restrictions (F2003 12.4.1.7)", &to->where);
+ return false;
+ }
+ }
+
/* CLASS arguments: Make sure the vtab of from is present. */
if (to->ts.type == BT_CLASS && !UNLIMITED_POLY (from))
gfc_find_vtab (&from->ts);
@@ -3447,10 +3487,10 @@ gfc_check_pack (gfc_expr *array, gfc_expr *mask, gfc_expr *vector)
if (!type_check (mask, 1, BT_LOGICAL))
return false;
- if (!gfc_check_conformance (array, mask,
- "arguments '%s' and '%s' for intrinsic '%s'",
- gfc_current_intrinsic_arg[0]->name,
- gfc_current_intrinsic_arg[1]->name,
+ if (!gfc_check_conformance (array, mask,
+ "arguments '%s' and '%s' for intrinsic '%s'",
+ gfc_current_intrinsic_arg[0]->name,
+ gfc_current_intrinsic_arg[1]->name,
gfc_current_intrinsic))
return false;
@@ -3989,7 +4029,7 @@ gfc_check_scan (gfc_expr *x, gfc_expr *y, gfc_expr *z, gfc_expr *kind)
if (!kind_check (kind, 3, BT_INTEGER))
return false;
if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
+ "with KIND argument at %L",
gfc_current_intrinsic, &kind->where))
return false;
@@ -4050,7 +4090,7 @@ gfc_check_selected_real_kind (gfc_expr *p, gfc_expr *r, gfc_expr *radix)
{
if (p == NULL && r == NULL
&& !gfc_notify_std (GFC_STD_F2008, "SELECTED_REAL_KIND with"
- " neither %<P%> nor %<R%> argument at %L",
+ " neither %<P%> nor %<R%> argument at %L",
gfc_current_intrinsic_where))
return false;
@@ -4081,7 +4121,7 @@ gfc_check_selected_real_kind (gfc_expr *p, gfc_expr *r, gfc_expr *radix)
return false;
if (!gfc_notify_std (GFC_STD_F2008, "%qs intrinsic with "
- "RADIX argument at %L", gfc_current_intrinsic,
+ "RADIX argument at %L", gfc_current_intrinsic,
&radix->where))
return false;
}
@@ -4123,7 +4163,7 @@ gfc_check_shape (gfc_expr *source, gfc_expr *kind)
if (!kind_check (kind, 1, BT_INTEGER))
return false;
if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
+ "with KIND argument at %L",
gfc_current_intrinsic, &kind->where))
return false;
@@ -4178,7 +4218,7 @@ gfc_check_size (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
if (!kind_check (kind, 2, BT_INTEGER))
return false;
if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
+ "with KIND argument at %L",
gfc_current_intrinsic, &kind->where))
return false;
@@ -4621,9 +4661,9 @@ gfc_check_c_loc (gfc_expr *x)
&x->where);
return false;
}
-
+
if (x->rank
- && !gfc_notify_std (GFC_STD_F2008_TS,
+ && !gfc_notify_std (GFC_STD_F2008_TS,
"Noninteroperable array at %L as"
" argument to C_LOC: %s", &x->where, msg))
return false;
@@ -4634,7 +4674,7 @@ gfc_check_c_loc (gfc_expr *x)
if (ar->as->type != AS_EXPLICIT && ar->as->type != AS_ASSUMED_SIZE
&& !attr.allocatable
- && !gfc_notify_std (GFC_STD_F2008,
+ && !gfc_notify_std (GFC_STD_F2008,
"Array of interoperable type at %L "
"to C_LOC which is nonallocatable and neither "
"assumed size nor explicit size", &x->where))
@@ -4669,7 +4709,7 @@ gfc_check_sngl (gfc_expr *a)
if ((a->ts.kind != gfc_default_double_kind)
&& !gfc_notify_std (GFC_STD_GNU, "non double precision "
- "REAL argument to %s intrinsic at %L",
+ "REAL argument to %s intrinsic at %L",
gfc_current_intrinsic, &a->where))
return false;
@@ -5182,12 +5222,13 @@ gfc_check_transfer (gfc_expr *source, gfc_expr *mold, gfc_expr *size)
/* If we can't calculate the sizes, we cannot check any more.
Return true for that case. */
- if (!gfc_calculate_transfer_sizes (source, mold, size, &source_size,
+ if (!gfc_calculate_transfer_sizes (source, mold, size, &source_size,
&result_size, NULL))
return true;
if (source_size < result_size)
- gfc_warning (0, "Intrinsic TRANSFER at %L has partly undefined result: "
+ gfc_warning (OPT_Wsurprising,
+ "Intrinsic TRANSFER at %L has partly undefined result: "
"source size %ld < result size %ld", &source->where,
(long) source_size, (long) result_size);
@@ -5220,7 +5261,7 @@ gfc_check_ubound (gfc_expr *array, gfc_expr *dim, gfc_expr *kind)
if (!kind_check (kind, 2, BT_INTEGER))
return false;
if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
+ "with KIND argument at %L",
gfc_current_intrinsic, &kind->where))
return false;
@@ -5349,7 +5390,7 @@ gfc_check_verify (gfc_expr *x, gfc_expr *y, gfc_expr *z, gfc_expr *kind)
if (!kind_check (kind, 3, BT_INTEGER))
return false;
if (kind && !gfc_notify_std (GFC_STD_F2003, "%qs intrinsic "
- "with KIND argument at %L",
+ "with KIND argument at %L",
gfc_current_intrinsic, &kind->where))
return false;
diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index 400c22abaf5..b7f68d2f19a 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -224,7 +224,8 @@ gfc_add_component_ref (gfc_expr *e, const char *name)
break;
tail = &((*tail)->next);
}
- if (derived->components->next->ts.type == BT_DERIVED &&
+ if (derived->components && derived->components->next &&
+ derived->components->next->ts.type == BT_DERIVED &&
derived->components->next->ts.u.derived == NULL)
{
/* Fix up missing vtype. */
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index f18eb41bc50..0120cebb322 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -7821,10 +7821,16 @@ cleanup:
match
gfc_match_parameter (void)
{
+ const char *term = " )%t";
match m;
if (gfc_match_char ('(') == MATCH_NO)
- return MATCH_NO;
+ {
+ /* With legacy PARAMETER statements, don't expect a terminating ')'. */
+ if (!gfc_notify_std (GFC_STD_LEGACY, "PARAMETER without '()' at %C"))
+ return MATCH_NO;
+ term = " %t";
+ }
for (;;)
{
@@ -7832,7 +7838,7 @@ gfc_match_parameter (void)
if (m != MATCH_YES)
break;
- if (gfc_match (" )%t") == MATCH_YES)
+ if (gfc_match (term) == MATCH_YES)
break;
if (gfc_match_char (',') != MATCH_YES)
diff --git a/gcc/fortran/error.c b/gcc/fortran/error.c
index fe91419ce44..0fd8a4e74e3 100644
--- a/gcc/fortran/error.c
+++ b/gcc/fortran/error.c
@@ -67,7 +67,7 @@ gfc_push_suppress_errors (void)
}
static void
-gfc_error (const char *gmsgid, va_list ap) ATTRIBUTE_GCC_GFC(1,0);
+gfc_error (int opt, const char *gmsgid, va_list ap) ATTRIBUTE_GCC_GFC(2,0);
static bool
gfc_warning (int opt, const char *gmsgid, va_list ap) ATTRIBUTE_GCC_GFC(2,0);
@@ -902,7 +902,7 @@ gfc_notify_std (int std, const char *gmsgid, ...)
if (warning)
gfc_warning (0, buffer, argp);
else
- gfc_error (buffer, argp);
+ gfc_error (0, buffer, argp);
va_end (argp);
return (warning && !warnings_are_errors) ? true : false;
@@ -1233,7 +1233,7 @@ gfc_warning_check (void)
/* Issue an error. */
static void
-gfc_error (const char *gmsgid, va_list ap)
+gfc_error (int opt, const char *gmsgid, va_list ap)
{
va_list argp;
va_copy (argp, ap);
@@ -1241,7 +1241,7 @@ gfc_error (const char *gmsgid, va_list ap)
if (warnings_not_errors)
{
- gfc_warning (/*opt=*/0, gmsgid, argp);
+ gfc_warning (opt, gmsgid, argp);
va_end (argp);
return;
}
@@ -1289,11 +1289,21 @@ gfc_error (const char *gmsgid, va_list ap)
void
+gfc_error (int opt, const char *gmsgid, ...)
+{
+ va_list argp;
+ va_start (argp, gmsgid);
+ gfc_error (opt, gmsgid, argp);
+ va_end (argp);
+}
+
+
+void
gfc_error (const char *gmsgid, ...)
{
va_list argp;
va_start (argp, gmsgid);
- gfc_error (gmsgid, argp);
+ gfc_error (0, gmsgid, argp);
va_end (argp);
}
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index bb183d411e6..b2ffaae246a 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -2206,7 +2206,7 @@ check_alloc_comp_init (gfc_expr *e)
gfc_constructor *ctor;
gcc_assert (e->expr_type == EXPR_STRUCTURE);
- gcc_assert (e->ts.type == BT_DERIVED);
+ gcc_assert (e->ts.type == BT_DERIVED || e->ts.type == BT_CLASS);
for (comp = e->ts.u.derived->components,
ctor = gfc_constructor_first (e->value.constructor);
@@ -3445,7 +3445,7 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
{
char err[200];
gfc_symbol *s1,*s2;
- gfc_component *comp;
+ gfc_component *comp1, *comp2;
const char *name;
attr = gfc_expr_attr (rvalue);
@@ -3549,9 +3549,9 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
}
}
- comp = gfc_get_proc_ptr_comp (lvalue);
- if (comp)
- s1 = comp->ts.interface;
+ comp1 = gfc_get_proc_ptr_comp (lvalue);
+ if (comp1)
+ s1 = comp1->ts.interface;
else
{
s1 = lvalue->symtree->n.sym;
@@ -3559,18 +3559,18 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
s1 = s1->ts.interface;
}
- comp = gfc_get_proc_ptr_comp (rvalue);
- if (comp)
+ comp2 = gfc_get_proc_ptr_comp (rvalue);
+ if (comp2)
{
if (rvalue->expr_type == EXPR_FUNCTION)
{
- s2 = comp->ts.interface->result;
+ s2 = comp2->ts.interface->result;
name = s2->name;
}
else
{
- s2 = comp->ts.interface;
- name = comp->name;
+ s2 = comp2->ts.interface;
+ name = comp2->name;
}
}
else if (rvalue->expr_type == EXPR_FUNCTION)
@@ -3591,6 +3591,15 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
if (s2 && s2->attr.proc_pointer && s2->ts.interface)
s2 = s2->ts.interface;
+ /* Special check for the case of absent interface on the lvalue.
+ * All other interface checks are done below. */
+ if (!s1 && comp1 && comp1->attr.subroutine && s2 && s2->attr.function)
+ {
+ gfc_error ("Interface mismatch in procedure pointer assignment "
+ "at %L: '%s' is not a subroutine", &rvalue->where, name);
+ return false;
+ }
+
if (s1 == s2 || !s1 || !s2)
return true;
@@ -4131,6 +4140,26 @@ gfc_apply_init (gfc_typespec *ts, symbol_attribute *attr, gfc_expr *init)
}
+/* Check whether an expression is a structure constructor and whether it has
+ other values than NULL. */
+
+bool
+is_non_empty_structure_constructor (gfc_expr * e)
+{
+ if (e->expr_type != EXPR_STRUCTURE)
+ return false;
+
+ gfc_constructor *cons = gfc_constructor_first (e->value.constructor);
+ while (cons)
+ {
+ if (!cons->expr || cons->expr->expr_type != EXPR_NULL)
+ return true;
+ cons = gfc_constructor_next (cons);
+ }
+ return false;
+}
+
+
/* Check for default initializer; sym->value is not enough
as it is also set for EXPR_NULL of allocatables. */
@@ -4145,7 +4174,9 @@ gfc_has_default_initializer (gfc_symbol *der)
{
if (!c->attr.pointer && !c->attr.proc_pointer
&& !(c->attr.allocatable && der == c->ts.u.derived)
- && gfc_has_default_initializer (c->ts.u.derived))
+ && ((c->initializer
+ && is_non_empty_structure_constructor (c->initializer))
+ || gfc_has_default_initializer (c->ts.u.derived)))
return true;
if (c->attr.pointer && c->initializer)
return true;
@@ -4345,6 +4376,7 @@ gfc_generate_initializer (gfc_typespec *ts, bool generate)
{
ctor->expr = gfc_get_expr ();
ctor->expr->expr_type = EXPR_NULL;
+ ctor->expr->where = init->where;
ctor->expr->ts = comp->ts;
}
diff --git a/gcc/fortran/frontend-passes.c b/gcc/fortran/frontend-passes.c
index e61673fc6e4..1ad797b579c 100644
--- a/gcc/fortran/frontend-passes.c
+++ b/gcc/fortran/frontend-passes.c
@@ -747,10 +747,12 @@ do_warn_function_elimination (gfc_expr *e)
if (e->expr_type != EXPR_FUNCTION)
return;
if (e->value.function.esym)
- gfc_warning (0, "Removing call to function %qs at %L",
+ gfc_warning (OPT_Wfunction_elimination,
+ "Removing call to function %qs at %L",
e->value.function.esym->name, &(e->where));
else if (e->value.function.isym)
- gfc_warning (0, "Removing call to function %qs at %L",
+ gfc_warning (OPT_Wfunction_elimination,
+ "Removing call to function %qs at %L",
e->value.function.isym->name, &(e->where));
}
/* Callback function for the code walker for doing common function
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index ea4437c5d83..3fb6f4152ce 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -2336,6 +2336,7 @@ typedef struct
gfc_expr *io_unit, *format_expr, *rec, *advance, *iostat, *size, *iomsg,
*id, *pos, *asynchronous, *blank, *decimal, *delim, *pad, *round,
*sign, *extra_comma, *dt_io_kind, *udtio;
+ char default_exp;
gfc_symbol *namelist;
/* A format_label of `format_asterisk' indicates the "*" format */
@@ -2730,6 +2731,7 @@ bool gfc_warning_now_at (location_t loc, int opt, const char *gmsgid, ...)
void gfc_clear_warning (void);
void gfc_warning_check (void);
+void gfc_error (int opt, const char *, ...) ATTRIBUTE_GCC_GFC(2,3);
void gfc_error (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
void gfc_error_now (const char *, ...) ATTRIBUTE_GCC_GFC(1,2);
void gfc_fatal_error (const char *, ...) ATTRIBUTE_NORETURN ATTRIBUTE_GCC_GFC(1,2);
diff --git a/gcc/fortran/gfortran.texi b/gcc/fortran/gfortran.texi
index e65c2decad2..6de6c9bfeeb 100644
--- a/gcc/fortran/gfortran.texi
+++ b/gcc/fortran/gfortran.texi
@@ -1471,6 +1471,8 @@ compatibility extensions along with those enabled by @option{-std=legacy}.
* .XOR. operator::
* Bitwise logical operators::
* Extended I/O specifiers::
+* Legacy PARAMETER statements::
+* Default exponents::
@end menu
@node Old-style kind specifications
@@ -2696,6 +2698,31 @@ supported on other systems.
@end table
+@node Legacy PARAMETER statements
+@subsection Legacy PARAMETER statements
+@cindex PARAMETER
+
+For compatibility, GNU Fortran supports legacy PARAMETER statements without
+parentheses with @option{-std=legacy}. A warning is emitted if used with
+@option{-std=gnu}, and an error is acknowledged with a real Fortran standard
+flag (@option{-std=f95}, etc...). These statements take the following form:
+
+@smallexample
+implicit real (E)
+parameter e = 2.718282
+real c
+parameter c = 3.0e8
+@end smallexample
+
+@node Default exponents
+@subsection Default exponents
+@cindex exponent
+
+For compatibility, GNU Fortran supports a default exponent of zero in real
+constants with @option{-fdec}. For example, @code{9e} would be
+interpreted as @code{9e0}, rather than an error.
+
+
@node Extensions not implemented in GNU Fortran
@section Extensions not implemented in GNU Fortran
@cindex extensions, not implemented
diff --git a/gcc/fortran/interface.c b/gcc/fortran/interface.c
index b851d5a425b..4dd432ef23d 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -2139,17 +2139,17 @@ argument_rank_mismatch (const char *name, locus *where,
}
else if (rank1 == 0)
{
- gfc_error ("Rank mismatch in argument %qs at %L "
+ gfc_error (OPT_Wargument_mismatch, "Rank mismatch in argument %qs at %L "
"(scalar and rank-%d)", name, where, rank2);
}
else if (rank2 == 0)
{
- gfc_error ("Rank mismatch in argument %qs at %L "
+ gfc_error (OPT_Wargument_mismatch, "Rank mismatch in argument %qs at %L "
"(rank-%d and scalar)", name, where, rank1);
}
else
{
- gfc_error ("Rank mismatch in argument %qs at %L "
+ gfc_error (OPT_Wargument_mismatch, "Rank mismatch in argument %qs at %L "
"(rank-%d and rank-%d)", name, where, rank1, rank2);
}
}
@@ -2200,7 +2200,8 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
sizeof(err), NULL, NULL))
{
if (where)
- gfc_error ("Interface mismatch in dummy procedure %qs at %L: %s",
+ gfc_error (OPT_Wargument_mismatch,
+ "Interface mismatch in dummy procedure %qs at %L: %s",
formal->name, &actual->where, err);
return 0;
}
@@ -2227,7 +2228,8 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
err, sizeof(err), NULL, NULL))
{
if (where)
- gfc_error ("Interface mismatch in dummy procedure %qs at %L: %s",
+ gfc_error (OPT_Wargument_mismatch,
+ "Interface mismatch in dummy procedure %qs at %L: %s",
formal->name, &actual->where, err);
return 0;
}
@@ -2253,7 +2255,8 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
CLASS_DATA (actual)->ts.u.derived)))
{
if (where)
- gfc_error ("Type mismatch in argument %qs at %L; passed %s to %s",
+ gfc_error (OPT_Wargument_mismatch,
+ "Type mismatch in argument %qs at %L; passed %s to %s",
formal->name, where, gfc_typename (&actual->ts),
gfc_typename (&formal->ts));
return 0;
@@ -2957,7 +2960,7 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
f->sym->ts.u.cl->length->value.integer) != 0))
{
if (where && (f->sym->attr.pointer || f->sym->attr.allocatable))
- gfc_warning (0,
+ gfc_warning (OPT_Wargument_mismatch,
"Character length mismatch (%ld/%ld) between actual "
"argument and pointer or allocatable dummy argument "
"%qs at %L",
@@ -2965,7 +2968,7 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
mpz_get_si (f->sym->ts.u.cl->length->value.integer),
f->sym->name, &a->expr->where);
else if (where)
- gfc_warning (0,
+ gfc_warning (OPT_Wargument_mismatch,
"Character length mismatch (%ld/%ld) between actual "
"argument and assumed-shape dummy argument %qs "
"at %L",
@@ -2997,12 +3000,14 @@ compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
&& f->sym->attr.flavor != FL_PROCEDURE)
{
if (a->expr->ts.type == BT_CHARACTER && !f->sym->as && where)
- gfc_warning (0, "Character length of actual argument shorter "
+ gfc_warning (OPT_Wargument_mismatch,
+ "Character length of actual argument shorter "
"than of dummy argument %qs (%lu/%lu) at %L",
f->sym->name, actual_size, formal_size,
&a->expr->where);
else if (where)
- gfc_warning (0, "Actual argument contains too few "
+ gfc_warning (OPT_Wargument_mismatch,
+ "Actual argument contains too few "
"elements for dummy argument %qs (%lu/%lu) at %L",
f->sym->name, actual_size, formal_size,
&a->expr->where);
@@ -4547,7 +4552,8 @@ gfc_check_typebound_override (gfc_symtree* proc, gfc_symtree* old)
if (!gfc_check_dummy_characteristics (proc_formal->sym, old_formal->sym,
check_type, err, sizeof(err)))
{
- gfc_error ("Argument mismatch for the overriding procedure "
+ gfc_error (OPT_Wargument_mismatch,
+ "Argument mismatch for the overriding procedure "
"%qs at %L: %s", proc->name, &where, err);
return false;
}
diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi
index ebf3aba8d4a..39a0232f71a 100644
--- a/gcc/fortran/invoke.texi
+++ b/gcc/fortran/invoke.texi
@@ -141,7 +141,7 @@ by type. Explanations are in the following sections.
@item Error and Warning Options
@xref{Error and Warning Options,,Options to request or suppress errors
and warnings}.
-@gccoptlist{-Waliasing -Wall -Wampersand -Warray-bounds
+@gccoptlist{-Waliasing -Wall -Wampersand -Wargument-mismatch -Warray-bounds
-Wc-binding-type -Wcharacter-truncation @gol
-Wconversion -Wfunction-elimination -Wimplicit-interface @gol
-Wimplicit-procedure -Wintrinsic-shadow -Wuse-without-only -Wintrinsics-std @gol
@@ -749,8 +749,10 @@ Check the code for syntax errors, but do not actually compile it. This
will generate module files for each module present in the code, but no
other output file.
-@item -pedantic
+@item -Wpedantic
+@itemx -pedantic
@opindex @code{pedantic}
+@opindex @code{Wpedantic}
Issue warnings for uses of extensions to Fortran 95.
@option{-pedantic} also applies to C-language constructs where they
occur in GNU Fortran source files, such as use of @samp{\e} in a
@@ -821,6 +823,15 @@ given in a continued character constant, GNU Fortran assumes continuation
at the first non-comment, non-whitespace character after the ampersand
that initiated the continuation.
+@item -Wargument-mismatch
+@opindex @code{Wargument-mismatch}
+@cindex warnings, argument mismatch
+@cindex warnings, parameter mismatch
+@cindex warnings, interface mismatch
+Warn about type, rank, and other mismatches between formal parameters and actual
+arguments to functions and subroutines. These warnings are recommended and
+thus enabled by default.
+
@item -Warray-temporaries
@opindex @code{Warray-temporaries}
@cindex warnings, array temporaries
diff --git a/gcc/fortran/io.c b/gcc/fortran/io.c
index dce0f7cd970..04cc1a25358 100644
--- a/gcc/fortran/io.c
+++ b/gcc/fortran/io.c
@@ -601,7 +601,7 @@ check_format (bool is_input)
const char *unexpected_end = _("Unexpected end of format string");
const char *zero_width = _("Zero width in format descriptor");
- const char *error;
+ const char *error = NULL;
format_token t, u;
int level;
int repeat;
@@ -867,27 +867,31 @@ data_desc:
goto fail;
if (t == FMT_POSINT)
break;
-
- switch (gfc_notification_std (GFC_STD_GNU))
+ if (mode != MODE_FORMAT)
+ format_locus.nextc += format_string_pos;
+ if (t == FMT_ZERO)
{
- case WARNING:
- if (mode != MODE_FORMAT)
- format_locus.nextc += format_string_pos;
- gfc_warning (0, "Extension: Missing positive width after L "
- "descriptor at %L", &format_locus);
- saved_token = t;
- break;
-
- case ERROR:
- error = posint_required;
- goto syntax;
-
- case SILENT:
- saved_token = t;
- break;
-
- default:
- gcc_unreachable ();
+ switch (gfc_notification_std (GFC_STD_GNU))
+ {
+ case WARNING:
+ gfc_warning (0, "Extension: Zero width after L "
+ "descriptor at %L", &format_locus);
+ break;
+ case ERROR:
+ gfc_error ("Extension: Zero width after L "
+ "descriptor at %L", &format_locus);
+ goto fail;
+ case SILENT:
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ }
+ else
+ {
+ saved_token = t;
+ gfc_notify_std (GFC_STD_GNU, "Missing positive width after "
+ "L descriptor at %L", &format_locus);
}
break;
@@ -4163,6 +4167,10 @@ get_io_list:
goto syntax;
}
+ /* See if we want to use defaults for missing exponents in real transfers. */
+ if (flag_dec)
+ dt->default_exp = 1;
+
/* A full IO statement has been matched. Check the constraints. spec_end is
supplied for cases where no locus is supplied. */
m = check_io_constraints (k, dt, io_code, &spec_end);
diff --git a/gcc/fortran/ioparm.def b/gcc/fortran/ioparm.def
index f1bf7330fd0..46691874e10 100644
--- a/gcc/fortran/ioparm.def
+++ b/gcc/fortran/ioparm.def
@@ -118,4 +118,5 @@ IOPARM (dt, round, 1 << 23, char2)
IOPARM (dt, sign, 1 << 24, char1)
#define IOPARM_dt_f2003 (1 << 25)
#define IOPARM_dt_dtio (1 << 26)
+#define IOPARM_dt_default_exp (1 << 27)
IOPARM (dt, u, 0, pad)
diff --git a/gcc/fortran/iresolve.c b/gcc/fortran/iresolve.c
index 078e47dbaa0..b289c9f6840 100644
--- a/gcc/fortran/iresolve.c
+++ b/gcc/fortran/iresolve.c
@@ -1044,15 +1044,19 @@ gfc_resolve_extends_type_of (gfc_expr *f, gfc_expr *a, gfc_expr *mo)
gfc_add_vptr_component (a);
else if (a->ts.type == BT_DERIVED)
{
+ locus where;
+
vtab = gfc_find_derived_vtab (a->ts.u.derived);
/* Clear the old expr. */
gfc_free_ref_list (a->ref);
+ where = a->where;
memset (a, '\0', sizeof (gfc_expr));
/* Construct a new one. */
a->expr_type = EXPR_VARIABLE;
st = gfc_find_symtree (vtab->ns->sym_root, vtab->name);
a->symtree = st;
a->ts = vtab->ts;
+ a->where = where;
}
/* Replace the second argument with the corresponding vtab. */
@@ -1060,8 +1064,11 @@ gfc_resolve_extends_type_of (gfc_expr *f, gfc_expr *a, gfc_expr *mo)
gfc_add_vptr_component (mo);
else if (mo->ts.type == BT_DERIVED)
{
+ locus where;
+
vtab = gfc_find_derived_vtab (mo->ts.u.derived);
/* Clear the old expr. */
+ where = mo->where;
gfc_free_ref_list (mo->ref);
memset (mo, '\0', sizeof (gfc_expr));
/* Construct a new one. */
@@ -1069,6 +1076,7 @@ gfc_resolve_extends_type_of (gfc_expr *f, gfc_expr *a, gfc_expr *mo)
st = gfc_find_symtree (vtab->ns->sym_root, vtab->name);
mo->symtree = st;
mo->ts = vtab->ts;
+ mo->where = where;
}
f->ts.type = BT_LOGICAL;
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 2e7640302ee..e39e555792f 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -209,6 +209,10 @@ Warray-temporaries
Fortran Warning Var(warn_array_temporaries)
Warn about creation of array temporaries.
+Wargument-mismatch
+Fortran Warning Var(warn_argument_mismatch) Init(1)
+Warn about type and rank mismatches between arguments and parameters.
+
Wc-binding-type
Fortran Var(warn_c_binding_type) Warning LangEnabledBy(Fortran,Wall)
Warn if the type of a variable might be not interoperable with C.
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index 0996a9efae6..5a7451ec9c4 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -5898,6 +5898,7 @@ gfc_match_select_type (void)
{
expr1 = gfc_get_expr ();
expr1->expr_type = EXPR_VARIABLE;
+ expr1->where = expr2->where;
if (gfc_get_sym_tree (name, NULL, &expr1->symtree, false))
{
m = MATCH_ERROR;
@@ -6219,6 +6220,7 @@ match_simple_where (void)
c->next = XCNEW (gfc_code);
*c->next = new_st;
+ c->next->loc = gfc_current_locus;
gfc_clear_new_st ();
new_st.op = EXEC_WHERE;
@@ -6275,8 +6277,12 @@ gfc_match_where (gfc_statement *st)
c = gfc_get_code (EXEC_WHERE);
c->expr1 = expr;
+ /* Put in the assignment. It will not be processed by add_statement, so we
+ need to copy the location here. */
+
c->next = XCNEW (gfc_code);
*c->next = new_st;
+ c->next->loc = gfc_current_locus;
gfc_clear_new_st ();
new_st.op = EXEC_WHERE;
diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
index 2aa2afc24e8..0ee054a014c 100644
--- a/gcc/fortran/parse.c
+++ b/gcc/fortran/parse.c
@@ -352,6 +352,9 @@ decode_statement (void)
}
gfc_matching_function = false;
+ /* Legacy parameter statements are ambiguous with assignments so try parameter
+ first. */
+ match ("parameter", gfc_match_parameter, ST_PARAMETER);
/* Match statements whose error messages are meant to be overwritten
by something better. */
@@ -528,7 +531,6 @@ decode_statement (void)
case 'p':
match ("print", gfc_match_print, ST_WRITE);
- match ("parameter", gfc_match_parameter, ST_PARAMETER);
match ("pause", gfc_match_pause, ST_PAUSE);
match ("pointer", gfc_match_pointer, ST_ATTR_DECL);
if (gfc_match_private (&st) == MATCH_YES)
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index bcbaeaa6369..50d7072b670 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -483,7 +483,7 @@ backup:
static match
match_real_constant (gfc_expr **result, int signflag)
{
- int kind, count, seen_dp, seen_digits, is_iso_c;
+ int kind, count, seen_dp, seen_digits, is_iso_c, default_exponent;
locus old_loc, temp_loc;
char *p, *buffer, c, exp_char;
gfc_expr *e;
@@ -494,6 +494,7 @@ match_real_constant (gfc_expr **result, int signflag)
e = NULL;
+ default_exponent = 0;
count = 0;
seen_dp = 0;
seen_digits = 0;
@@ -575,8 +576,14 @@ match_real_constant (gfc_expr **result, int signflag)
if (!ISDIGIT (c))
{
- gfc_error ("Missing exponent in real number at %C");
- return MATCH_ERROR;
+ /* With -fdec, default exponent to 0 instead of complaining. */
+ if (flag_dec)
+ default_exponent = 1;
+ else
+ {
+ gfc_error ("Missing exponent in real number at %C");
+ return MATCH_ERROR;
+ }
}
while (ISDIGIT (c))
@@ -597,8 +604,8 @@ done:
gfc_current_locus = old_loc;
gfc_gobble_whitespace ();
- buffer = (char *) alloca (count + 1);
- memset (buffer, '\0', count + 1);
+ buffer = (char *) alloca (count + default_exponent + 1);
+ memset (buffer, '\0', count + default_exponent + 1);
p = buffer;
c = gfc_next_ascii_char ();
@@ -621,6 +628,8 @@ done:
c = gfc_next_ascii_char ();
}
+ if (default_exponent)
+ *p++ = '0';
kind = get_kind (&is_iso_c);
if (kind == -1)
@@ -1353,6 +1362,10 @@ match_complex_constant (gfc_expr **result)
if (gfc_match_char (',') == MATCH_NO)
{
+ /* It is possible that gfc_int2real issued a warning when
+ converting an integer to real. Throw this away here. */
+
+ gfc_clear_warning ();
gfc_pop_error (&old_error);
m = MATCH_NO;
goto cleanup;
@@ -1918,15 +1931,36 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
}
/* For associate names, we may not yet know whether they are arrays or not.
- Thus if we have one and parentheses follow, we have to assume that it
- actually is one for now. The final decision will be made at
- resolution time, of course. */
- if (sym->assoc && gfc_peek_ascii_char () == '('
- && !(sym->assoc->dangling && sym->assoc->st
+ If the selector expression is unambiguously an array; eg. a full array
+ or an array section, then the associate name must be an array and we can
+ fix it now. Otherwise, if parentheses follow and it is not a character
+ type, we have to assume that it actually is one for now. The final
+ decision will be made at resolution, of course. */
+ if (sym->assoc
+ && gfc_peek_ascii_char () == '('
+ && sym->ts.type != BT_CLASS
+ && !sym->attr.dimension)
+ {
+ if ((!sym->assoc->dangling
+ && sym->assoc->target
+ && sym->assoc->target->ref
+ && sym->assoc->target->ref->type == REF_ARRAY
+ && (sym->assoc->target->ref->u.ar.type == AR_FULL
+ || sym->assoc->target->ref->u.ar.type == AR_SECTION))
+ ||
+ (!(sym->assoc->dangling || sym->ts.type == BT_CHARACTER)
+ && sym->assoc->st
&& sym->assoc->st->n.sym
- && sym->assoc->st->n.sym->attr.dimension == 0)
- && sym->ts.type != BT_CLASS)
+ && sym->assoc->st->n.sym->attr.dimension == 0))
+ {
sym->attr.dimension = 1;
+ if (sym->as == NULL && sym->assoc
+ && sym->assoc->st
+ && sym->assoc->st->n.sym
+ && sym->assoc->st->n.sym->as)
+ sym->as = gfc_copy_array_spec (sym->assoc->st->n.sym->as);
+ }
+ }
if ((equiv_flag && gfc_peek_ascii_char () == '(')
|| gfc_peek_ascii_char () == '[' || sym->attr.codimension
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index f9d11be5997..f4d346ed0f3 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -1317,7 +1317,8 @@ resolve_structure_cons (gfc_expr *expr, int init)
if (s2 && !gfc_compare_interfaces (comp->ts.interface, s2, name, 0, 1,
err, sizeof (err), NULL, NULL))
{
- gfc_error ("Interface mismatch for procedure-pointer component "
+ gfc_error (OPT_Wargument_mismatch,
+ "Interface mismatch for procedure-pointer component "
"%qs in structure constructor at %L: %s",
comp->name, &cons->expr->where, err);
return false;
@@ -2139,7 +2140,8 @@ resolve_elemental_actual (gfc_expr *expr, gfc_code *c)
&& (set_by_optional || arg->expr->rank != rank)
&& !(isym && isym->id == GFC_ISYM_CONVERSION))
{
- gfc_warning (0, "%qs at %L is an array and OPTIONAL; IF IT IS "
+ gfc_warning (OPT_Wpedantic,
+ "%qs at %L is an array and OPTIONAL; IF IT IS "
"MISSING, it cannot be the actual argument of an "
"ELEMENTAL procedure unless there is a non-optional "
"argument with the same rank (12.4.1.5)",
@@ -2469,7 +2471,8 @@ resolve_global_procedure (gfc_symbol *sym, locus *where,
if (!gfc_compare_interfaces (sym, def_sym, sym->name, 0, 1,
reason, sizeof(reason), NULL, NULL))
{
- gfc_error ("Interface mismatch in global procedure %qs at %L: %s ",
+ gfc_error (OPT_Wargument_mismatch,
+ "Interface mismatch in global procedure %qs at %L: %s ",
sym->name, &sym->declared_at, reason);
goto done;
}
@@ -3809,7 +3812,8 @@ resolve_operator (gfc_expr *e)
else
msg = "Inequality comparison for %s at %L";
- gfc_warning (0, msg, gfc_typename (&op1->ts), &op1->where);
+ gfc_warning (OPT_Wcompare_reals, msg,
+ gfc_typename (&op1->ts), &op1->where);
}
}
@@ -7044,35 +7048,6 @@ conformable_arrays (gfc_expr *e1, gfc_expr *e2)
return true;
}
-static void
-cond_init (gfc_code *code, gfc_expr *e, int pointer, gfc_expr *init_e)
-{
- gfc_code *block;
- gfc_expr *cond;
- gfc_code *init_st;
- gfc_expr *e_to_init = gfc_expr_to_initialize (e);
-
- cond = pointer
- ? gfc_build_intrinsic_call (gfc_current_ns, GFC_ISYM_ASSOCIATED,
- "associated", code->loc, 2, gfc_copy_expr (e_to_init), NULL)
- : gfc_build_intrinsic_call (gfc_current_ns, GFC_ISYM_ALLOCATED,
- "allocated", code->loc, 1, gfc_copy_expr (e_to_init));
-
- init_st = gfc_get_code (EXEC_INIT_ASSIGN);
- init_st->loc = code->loc;
- init_st->expr1 = e_to_init;
- init_st->expr2 = init_e;
-
- block = gfc_get_code (EXEC_IF);
- block->loc = code->loc;
- block->block = gfc_get_code (EXEC_IF);
- block->block->loc = code->loc;
- block->block->expr1 = cond;
- block->block->next = init_st;
- block->next = code->next;
-
- code->next = block;
-}
/* Resolve the expression in an ALLOCATE statement, doing the additional
checks to see whether the expression is OK or not. The expression must
@@ -7323,34 +7298,6 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool *array_alloc_wo_spec)
/* We have to zero initialize the integer variable. */
code->expr3 = gfc_get_int_expr (gfc_default_integer_kind, &e->where, 0);
}
- else if (!code->expr3)
- {
- /* Set up default initializer if needed. */
- gfc_typespec ts;
- gfc_expr *init_e;
-
- if (gfc_bt_struct (code->ext.alloc.ts.type))
- ts = code->ext.alloc.ts;
- else
- ts = e->ts;
-
- if (ts.type == BT_CLASS)
- ts = ts.u.derived->components->ts;
-
- if (gfc_bt_struct (ts.type) && (init_e = gfc_default_initializer (&ts)))
- cond_init (code, e, pointer, init_e);
- }
- else if (code->expr3->mold && code->expr3->ts.type == BT_DERIVED)
- {
- /* Default initialization via MOLD (non-polymorphic). */
- gfc_expr *rhs = gfc_default_initializer (&code->expr3->ts);
- if (rhs != NULL)
- {
- gfc_resolve_expr (rhs);
- gfc_free_expr (code->expr3);
- code->expr3 = rhs;
- }
- }
if (e->ts.type == BT_CLASS && !unlimited && !UNLIMITED_POLY (code->expr3))
{
@@ -7362,10 +7309,9 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool *array_alloc_wo_spec)
else if (code->ext.alloc.ts.type == BT_DERIVED)
ts = code->ext.alloc.ts;
+ /* Finding the vtab also publishes the type's symbol. Therefore this
+ statement is necessary. */
gfc_find_derived_vtab (ts.u.derived);
-
- if (dimension)
- e = gfc_expr_to_initialize (e);
}
else if (unlimited && !UNLIMITED_POLY (code->expr3))
{
@@ -7379,10 +7325,9 @@ resolve_allocate_expr (gfc_expr *e, gfc_code *code, bool *array_alloc_wo_spec)
gcc_assert (ts);
+ /* Finding the vtab also publishes the type's symbol. Therefore this
+ statement is necessary. */
gfc_find_vtab (ts);
-
- if (dimension)
- e = gfc_expr_to_initialize (e);
}
if (dimension == 0 && codimension == 0)
@@ -7686,6 +7631,22 @@ resolve_allocate_deallocate (gfc_code *code, const char *fcn)
if (strcmp (fcn, "ALLOCATE") == 0)
{
bool arr_alloc_wo_spec = false;
+
+ /* Resolving the expr3 in the loop over all objects to allocate would
+ execute loop invariant code for each loop item. Therefore do it just
+ once here. */
+ if (code->expr3 && code->expr3->mold
+ && code->expr3->ts.type == BT_DERIVED)
+ {
+ /* Default initialization via MOLD (non-polymorphic). */
+ gfc_expr *rhs = gfc_default_initializer (&code->expr3->ts);
+ if (rhs != NULL)
+ {
+ gfc_resolve_expr (rhs);
+ gfc_free_expr (code->expr3);
+ code->expr3 = rhs;
+ }
+ }
for (a = code->ext.alloc.list; a; a = a->next)
resolve_allocate_expr (a->expr, code, &arr_alloc_wo_spec);
@@ -8496,6 +8457,7 @@ build_loc_call (gfc_expr *sym_expr)
loc_call->value.function.isym = gfc_intrinsic_function_by_id (GFC_ISYM_LOC);
loc_call->value.function.actual = gfc_get_actual_arglist ();
loc_call->value.function.actual->expr = sym_expr;
+ loc_call->where = sym_expr->where;
return loc_call;
}
@@ -8895,11 +8857,13 @@ resolve_select_type (gfc_code *code, gfc_namespace *old_ns)
new_st->expr1->value.function.actual = gfc_get_actual_arglist ();
new_st->expr1->value.function.actual->expr = gfc_get_variable_expr (selector_expr->symtree);
new_st->expr1->value.function.actual->expr->where = code->loc;
+ new_st->expr1->where = code->loc;
gfc_add_vptr_component (new_st->expr1->value.function.actual->expr);
vtab = gfc_find_derived_vtab (body->ext.block.case_list->ts.u.derived);
st = gfc_find_symtree (vtab->ns->sym_root, vtab->name);
new_st->expr1->value.function.actual->next = gfc_get_actual_arglist ();
new_st->expr1->value.function.actual->next->expr = gfc_get_variable_expr (st);
+ new_st->expr1->value.function.actual->next->expr->where = code->loc;
new_st->next = body->next;
}
if (default_case->next)
@@ -14037,6 +14001,15 @@ resolve_fl_parameter (gfc_symbol *sym)
&sym->value->where);
return false;
}
+
+ /* F03:C509,C514. */
+ if (sym->ts.type == BT_CLASS)
+ {
+ gfc_error ("CLASS variable %qs at %L cannot have the PARAMETER attribute",
+ sym->name, &sym->declared_at);
+ return false;
+ }
+
return true;
}
@@ -15391,12 +15364,13 @@ warn_unused_fortran_label (gfc_st_label *label)
switch (label->referenced)
{
case ST_LABEL_UNKNOWN:
- gfc_warning (0, "Label %d at %L defined but not used", label->value,
- &label->where);
+ gfc_warning (OPT_Wunused_label, "Label %d at %L defined but not used",
+ label->value, &label->where);
break;
case ST_LABEL_BAD_TARGET:
- gfc_warning (0, "Label %d at %L defined but cannot be used",
+ gfc_warning (OPT_Wunused_label,
+ "Label %d at %L defined but cannot be used",
label->value, &label->where);
break;
diff --git a/gcc/fortran/symbol.c b/gcc/fortran/symbol.c
index cbe4347351f..85ed375e297 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -4901,7 +4901,7 @@ gfc_type_compatible (gfc_typespec *ts1, gfc_typespec *ts2)
&& !is_union1 && !is_union2)
return (ts1->type == ts2->type);
- if ((is_derived1 && is_derived2) || (is_union1 && is_union1))
+ if ((is_derived1 && is_derived2) || (is_union1 && is_union2))
return gfc_compare_derived_types (ts1->u.derived, ts2->u.derived);
if (is_derived1 && is_class2)
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index 74935b181f6..1708f7c8e44 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -5623,14 +5623,6 @@ gfc_array_allocate (gfc_se * se, gfc_expr * expr, tree status, tree errmsg,
else
gfc_add_expr_to_block (&se->pre, set_descriptor);
- if (expr->ts.type == BT_DERIVED && expr->ts.u.derived->attr.alloc_comp
- && !coarray)
- {
- tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, se->expr,
- ref->u.ar.as->rank);
- gfc_add_expr_to_block (&se->pre, tmp);
- }
-
return true;
}
diff --git a/gcc/fortran/trans-common.c b/gcc/fortran/trans-common.c
index ee12fa22dc0..0c030584b68 100644
--- a/gcc/fortran/trans-common.c
+++ b/gcc/fortran/trans-common.c
@@ -1149,13 +1149,13 @@ translate_common (gfc_common_head *common, gfc_symbol *var_list)
if (warn_align_commons)
{
if (strcmp (common->name, BLANK_COMMON_NAME))
- gfc_warning (0,
+ gfc_warning (OPT_Walign_commons,
"Padding of %d bytes required before %qs in "
"COMMON %qs at %L; reorder elements or use "
"-fno-align-commons", (int)offset,
s->sym->name, common->name, &common->where);
else
- gfc_warning (0,
+ gfc_warning (OPT_Walign_commons,
"Padding of %d bytes required before %qs in "
"COMMON at %L; reorder elements or use "
"-fno-align-commons", (int)offset,
diff --git a/gcc/fortran/trans-expr.c b/gcc/fortran/trans-expr.c
index 7159b172eea..61214295f66 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -1091,6 +1091,12 @@ gfc_conv_class_to_class (gfc_se *parmse, gfc_expr *e, gfc_typespec class_ts,
tmp = integer_zero_node;
gfc_add_modify (&parmse->pre, ctree,
fold_convert (TREE_TYPE (ctree), tmp));
+
+ /* Return the len component, except in the case of scalarized array
+ references, where the dynamic type cannot change. */
+ if (!elemental && full_array && copyback)
+ gfc_add_modify (&parmse->post, tmp,
+ fold_convert (TREE_TYPE (tmp), ctree));
}
if (optional)
@@ -10036,7 +10042,7 @@ gfc_trans_assignment (gfc_expr * expr1, gfc_expr * expr2, bool init_flag,
tree
gfc_trans_init_assign (gfc_code * code)
{
- return gfc_trans_assignment (code->expr1, code->expr2, true, false);
+ return gfc_trans_assignment (code->expr1, code->expr2, true, false, true);
}
tree
diff --git a/gcc/fortran/trans-io.c b/gcc/fortran/trans-io.c
index 285e551585c..253a5ac70a9 100644
--- a/gcc/fortran/trans-io.c
+++ b/gcc/fortran/trans-io.c
@@ -1911,6 +1911,9 @@ build_dt (tree function, gfc_code * code)
if (dt->udtio)
mask |= IOPARM_dt_dtio;
+ if (dt->default_exp)
+ mask |= IOPARM_dt_default_exp;
+
if (dt->namelist)
{
if (dt->format_expr || dt->format_label)
diff --git a/gcc/fortran/trans-stmt.c b/gcc/fortran/trans-stmt.c
index c52066ffd20..490b18dae31 100644
--- a/gcc/fortran/trans-stmt.c
+++ b/gcc/fortran/trans-stmt.c
@@ -5450,13 +5450,41 @@ gfc_trans_exit (gfc_code * code)
}
+/* Get the initializer expression for the code and expr of an allocate.
+ When no initializer is needed return NULL. */
+
+static gfc_expr *
+allocate_get_initializer (gfc_code * code, gfc_expr * expr)
+{
+ if (!gfc_bt_struct (expr->ts.type) && expr->ts.type != BT_CLASS)
+ return NULL;
+
+ /* An explicit type was given in allocate ( T:: object). */
+ if (code->ext.alloc.ts.type == BT_DERIVED
+ && (code->ext.alloc.ts.u.derived->attr.alloc_comp
+ || gfc_has_default_initializer (code->ext.alloc.ts.u.derived)))
+ return gfc_default_initializer (&code->ext.alloc.ts);
+
+ if (gfc_bt_struct (expr->ts.type)
+ && (expr->ts.u.derived->attr.alloc_comp
+ || gfc_has_default_initializer (expr->ts.u.derived)))
+ return gfc_default_initializer (&expr->ts);
+
+ if (expr->ts.type == BT_CLASS
+ && (CLASS_DATA (expr)->ts.u.derived->attr.alloc_comp
+ || gfc_has_default_initializer (CLASS_DATA (expr)->ts.u.derived)))
+ return gfc_default_initializer (&CLASS_DATA (expr)->ts);
+
+ return NULL;
+}
+
/* Translate the ALLOCATE statement. */
tree
gfc_trans_allocate (gfc_code * code)
{
gfc_alloc *al;
- gfc_expr *expr, *e3rhs = NULL;
+ gfc_expr *expr, *e3rhs = NULL, *init_expr;
gfc_se se, se_sz;
tree tmp;
tree parm;
@@ -6080,14 +6108,6 @@ gfc_trans_allocate (gfc_code * code)
label_finish, expr, 0);
else
gfc_allocate_using_malloc (&se.pre, se.expr, memsz, stat);
-
- if (al->expr->ts.type == BT_DERIVED
- && expr->ts.u.derived->attr.alloc_comp)
- {
- tmp = build_fold_indirect_ref_loc (input_location, se.expr);
- tmp = gfc_nullify_alloc_comp (expr->ts.u.derived, tmp, 0);
- gfc_add_expr_to_block (&se.pre, tmp);
- }
}
else
{
@@ -6217,6 +6237,8 @@ gfc_trans_allocate (gfc_code * code)
fold_convert (TREE_TYPE (al_len),
integer_zero_node));
}
+
+ init_expr = NULL;
if (code->expr3 && !code->expr3->mold && e3_is != E3_MOLD)
{
/* Initialization via SOURCE block (or static default initializer).
@@ -6246,6 +6268,23 @@ gfc_trans_allocate (gfc_code * code)
gfc_free_statements (ini);
gfc_add_expr_to_block (&block, tmp);
}
+ else if ((init_expr = allocate_get_initializer (code, expr)))
+ {
+ /* Use class_init_assign to initialize expr. */
+ gfc_code *ini;
+ int realloc_lhs = flag_realloc_lhs;
+ ini = gfc_get_code (EXEC_INIT_ASSIGN);
+ ini->expr1 = gfc_expr_to_initialize (expr);
+ ini->expr2 = init_expr;
+ flag_realloc_lhs = 0;
+ tmp= gfc_trans_init_assign (ini);
+ flag_realloc_lhs = realloc_lhs;
+ gfc_free_statements (ini);
+ /* Init_expr is freeed by above free_statements, just need to null
+ it here. */
+ init_expr = NULL;
+ gfc_add_expr_to_block (&block, tmp);
+ }
gfc_free_expr (expr);
} // for-loop
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index eda0351119a..6f9bc381df6 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -3139,7 +3139,7 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
int rank, dim;
bool indirect = false;
tree etype, ptype, field, t, base_decl;
- tree data_off, dim_off, dim_size, elem_size;
+ tree data_off, dim_off, dtype_off, dim_size, elem_size;
tree lower_suboff, upper_suboff, stride_suboff;
if (! GFC_DESCRIPTOR_TYPE_P (type))
@@ -3203,6 +3203,7 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
data_off = byte_position (field);
field = DECL_CHAIN (field);
field = DECL_CHAIN (field);
+ dtype_off = byte_position (field);
field = DECL_CHAIN (field);
dim_off = byte_position (field);
dim_size = TYPE_SIZE_UNIT (TREE_TYPE (TREE_TYPE (field)));
@@ -3225,6 +3226,24 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
|| GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_POINTER_CONT)
info->associated = build2 (NE_EXPR, boolean_type_node,
info->data_location, null_pointer_node);
+ if ((GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK
+ || GFC_TYPE_ARRAY_AKIND (type) == GFC_ARRAY_ASSUMED_RANK_CONT)
+ && dwarf_version >= 5)
+ {
+ rank = 1;
+ info->ndimensions = 1;
+ t = base_decl;
+ if (!integer_zerop (dtype_off))
+ t = fold_build_pointer_plus (t, dtype_off);
+ t = build1 (NOP_EXPR, build_pointer_type (gfc_array_index_type), t);
+ t = build1 (INDIRECT_REF, gfc_array_index_type, t);
+ info->rank = build2 (BIT_AND_EXPR, gfc_array_index_type, t,
+ build_int_cst (gfc_array_index_type,
+ GFC_DTYPE_RANK_MASK));
+ t = build0 (PLACEHOLDER_EXPR, TREE_TYPE (dim_off));
+ t = size_binop (MULT_EXPR, t, dim_size);
+ dim_off = build2 (PLUS_EXPR, TREE_TYPE (dim_off), t, dim_off);
+ }
for (dim = 0; dim < rank; dim++)
{
@@ -3260,7 +3279,8 @@ gfc_get_array_descr_info (const_tree type, struct array_descr_info *info)
t = build1 (INDIRECT_REF, gfc_array_index_type, t);
t = build2 (MULT_EXPR, gfc_array_index_type, t, elem_size);
info->dimen[dim].stride = t;
- dim_off = size_binop (PLUS_EXPR, dim_off, dim_size);
+ if (dim + 1 < rank)
+ dim_off = size_binop (PLUS_EXPR, dim_off, dim_size);
}
return true;
diff --git a/gcc/fwprop.c b/gcc/fwprop.c
index 4365ff0db90..b2d670061be 100644
--- a/gcc/fwprop.c
+++ b/gcc/fwprop.c
@@ -1051,9 +1051,7 @@ free_load_extend (rtx src, rtx_insn *insn)
df_ref def, use;
reg = XEXP (src, 0);
-#ifdef LOAD_EXTEND_OP
if (LOAD_EXTEND_OP (GET_MODE (reg)) != GET_CODE (src))
-#endif
return false;
FOR_EACH_INSN_USE (use, insn)
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 10bf80139b6..f588f5e445e 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -728,6 +728,12 @@ pp_points_to_solution (pretty_printer *buffer, struct pt_solution *pt)
{
pp_string (buffer, comma);
pp_string (buffer, "restrict");
+ comma = ", ";
+ }
+ if (pt->vars_contains_interposable)
+ {
+ pp_string (buffer, comma);
+ pp_string (buffer, "interposable");
}
pp_string (buffer, ")");
}
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 5a293d7f307..bd9ba28ee51 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -125,6 +125,8 @@
#include "tree-cfg.h"
#include "tree-eh.h"
#include "target.h"
+#include "gimplify-me.h"
+#include "selftest.h"
/* The maximum size (in bits) of the stores this pass should generate. */
#define MAX_STORE_BITSIZE (BITS_PER_WORD)
@@ -140,19 +142,17 @@ struct store_immediate_info
{
unsigned HOST_WIDE_INT bitsize;
unsigned HOST_WIDE_INT bitpos;
- tree val;
- tree dest;
gimple *stmt;
unsigned int order;
- store_immediate_info (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT, tree,
- tree, gimple *, unsigned int);
+ store_immediate_info (unsigned HOST_WIDE_INT, unsigned HOST_WIDE_INT,
+ gimple *, unsigned int);
};
store_immediate_info::store_immediate_info (unsigned HOST_WIDE_INT bs,
- unsigned HOST_WIDE_INT bp, tree v,
- tree d, gimple *st,
+ unsigned HOST_WIDE_INT bp,
+ gimple *st,
unsigned int ord)
- : bitsize (bs), bitpos (bp), val (v), dest (d), stmt (st), order (ord)
+ : bitsize (bs), bitpos (bp), stmt (st), order (ord)
{
}
@@ -338,7 +338,7 @@ clear_bit_region (unsigned char *ptr, unsigned int start,
else if (start != 0)
{
clear_bit_region (ptr, start, BITS_PER_UNIT - start);
- clear_bit_region (ptr + 1, 0, len - (BITS_PER_UNIT - start) + 1);
+ clear_bit_region (ptr + 1, 0, len - (BITS_PER_UNIT - start));
}
/* Whole bytes need to be cleared. */
else if (start == 0 && len > BITS_PER_UNIT)
@@ -432,13 +432,24 @@ encode_tree_to_bitpos (tree expr, unsigned char *ptr, int bitlen, int bitpos,
contain a sign bit due to sign-extension). */
unsigned int padding
= byte_size - ROUND_UP (bitlen, BITS_PER_UNIT) / BITS_PER_UNIT - 1;
- if (BYTES_BIG_ENDIAN)
+ if (padding != 0
+ || bitlen % BITS_PER_UNIT != 0)
{
- tmpbuf += padding;
+ /* On big-endian the padding is at the 'front' so just skip the initial
+ bytes. */
+ if (BYTES_BIG_ENDIAN)
+ tmpbuf += padding;
+
byte_size -= padding;
if (bitlen % BITS_PER_UNIT != 0)
- clear_bit_region_be (tmpbuf, BITS_PER_UNIT - 1,
- BITS_PER_UNIT - (bitlen % BITS_PER_UNIT));
+ {
+ if (BYTES_BIG_ENDIAN)
+ clear_bit_region_be (tmpbuf, BITS_PER_UNIT - 1,
+ BITS_PER_UNIT - (bitlen % BITS_PER_UNIT));
+ else
+ clear_bit_region (tmpbuf, bitlen,
+ byte_size * BITS_PER_UNIT - bitlen);
+ }
}
/* Clear the bit region in PTR where the bits from TMPBUF will be
@@ -547,7 +558,7 @@ merged_store_group::merged_store_group (store_immediate_info *info)
/* VAL has memory allocated for it in apply_stores once the group
width has been finalized. */
val = NULL;
- align = get_object_alignment (info->dest);
+ align = get_object_alignment (gimple_assign_lhs (info->stmt));
stores.create (1);
stores.safe_push (info);
last_stmt = info->stmt;
@@ -644,14 +655,16 @@ merged_store_group::apply_stores ()
FOR_EACH_VEC_ELT (stores, i, info)
{
unsigned int pos_in_buffer = info->bitpos - start;
- bool ret = encode_tree_to_bitpos (info->val, val, info->bitsize,
- pos_in_buffer, buf_size);
+ bool ret = encode_tree_to_bitpos (gimple_assign_rhs1 (info->stmt),
+ val, info->bitsize,
+ pos_in_buffer, buf_size);
if (dump_file && (dump_flags & TDF_DETAILS))
{
if (ret)
{
fprintf (dump_file, "After writing ");
- print_generic_expr (dump_file, info->val, 0);
+ print_generic_expr (dump_file,
+ gimple_assign_rhs1 (info->stmt), 0);
fprintf (dump_file, " of size " HOST_WIDE_INT_PRINT_DEC
" at position %d the merged region contains:\n",
info->bitsize, pos_in_buffer);
@@ -670,13 +683,15 @@ merged_store_group::apply_stores ()
struct imm_store_chain_info
{
+ tree base_addr;
auto_vec<struct store_immediate_info *> m_store_info;
auto_vec<merged_store_group *> m_merged_store_groups;
- bool terminate_and_process_chain (tree);
+ imm_store_chain_info (tree b_a) : base_addr (b_a) {}
+ bool terminate_and_process_chain ();
bool coalesce_immediate_stores ();
- bool output_merged_store (tree, merged_store_group *);
- bool output_merged_stores (tree);
+ bool output_merged_store (merged_store_group *);
+ bool output_merged_stores ();
};
const pass_data pass_data_tree_store_merging = {
@@ -712,8 +727,9 @@ private:
hash_map<tree_operand_hash, struct imm_store_chain_info *> m_stores;
bool terminate_and_process_all_chains ();
- bool terminate_all_aliasing_chains (tree, tree, bool, gimple *);
- bool terminate_and_release_chain (tree);
+ bool terminate_all_aliasing_chains (imm_store_chain_info **,
+ bool, gimple *);
+ bool terminate_and_release_chain (imm_store_chain_info *);
}; // class pass_store_merging
/* Terminate and process all recorded chains. Return true if any changes
@@ -726,7 +742,7 @@ pass_store_merging::terminate_and_process_all_chains ()
= m_stores.begin ();
bool ret = false;
for (; iter != m_stores.end (); ++iter)
- ret |= terminate_and_release_chain ((*iter).first);
+ ret |= terminate_and_release_chain ((*iter).second);
return ret;
}
@@ -740,7 +756,8 @@ pass_store_merging::terminate_and_process_all_chains ()
If that is the case we have to terminate any chain anchored at BASE. */
bool
-pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base,
+pass_store_merging::terminate_all_aliasing_chains (imm_store_chain_info
+ **chain_info,
bool var_offset_p,
gimple *stmt)
{
@@ -750,44 +767,41 @@ pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base,
if (!gimple_vuse (stmt))
return false;
- struct imm_store_chain_info **chain_info = NULL;
-
/* Check if the assignment destination (BASE) is part of a store chain.
This is to catch non-constant stores to destinations that may be part
of a chain. */
- if (base)
+ if (chain_info)
{
- chain_info = m_stores.get (base);
- if (chain_info)
+ /* We have a chain at BASE and we're writing to [BASE + <variable>].
+ This can interfere with any of the stores so terminate
+ the chain. */
+ if (var_offset_p)
{
- /* We have a chain at BASE and we're writing to [BASE + <variable>].
- This can interfere with any of the stores so terminate
- the chain. */
- if (var_offset_p)
- {
- terminate_and_release_chain (base);
- ret = true;
- }
- /* Otherwise go through every store in the chain to see if it
- aliases with any of them. */
- else
+ terminate_and_release_chain (*chain_info);
+ ret = true;
+ }
+ /* Otherwise go through every store in the chain to see if it
+ aliases with any of them. */
+ else
+ {
+ struct store_immediate_info *info;
+ unsigned int i;
+ FOR_EACH_VEC_ELT ((*chain_info)->m_store_info, i, info)
{
- struct store_immediate_info *info;
- unsigned int i;
- FOR_EACH_VEC_ELT ((*chain_info)->m_store_info, i, info)
+ if (ref_maybe_used_by_stmt_p (stmt,
+ gimple_assign_lhs (info->stmt))
+ || stmt_may_clobber_ref_p (stmt,
+ gimple_assign_lhs (info->stmt)))
{
- if (refs_may_alias_p (info->dest, dest))
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file,
- "stmt causes chain termination:\n");
- print_gimple_stmt (dump_file, stmt, 0, 0);
- }
- terminate_and_release_chain (base);
- ret = true;
- break;
+ fprintf (dump_file,
+ "stmt causes chain termination:\n");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
}
+ terminate_and_release_chain (*chain_info);
+ ret = true;
+ break;
}
}
}
@@ -804,11 +818,16 @@ pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base,
if (chain_info && (*chain_info) == (*iter).second)
continue;
- tree key = (*iter).first;
- if (ref_maybe_used_by_stmt_p (stmt, key)
- || stmt_may_clobber_ref_p (stmt, key))
+ /* We can't use the base object here as that does not reliably exist.
+ Build a ao_ref from the base object address (if we know the
+ minimum and maximum offset and the maximum size we could improve
+ things here). */
+ ao_ref chain_ref;
+ ao_ref_init_from_ptr_and_size (&chain_ref, (*iter).first, NULL_TREE);
+ if (ref_maybe_used_by_stmt_p (stmt, &chain_ref)
+ || stmt_may_clobber_ref_p_1 (stmt, &chain_ref))
{
- terminate_and_release_chain (key);
+ terminate_and_release_chain ((*iter).second);
ret = true;
}
}
@@ -821,19 +840,11 @@ pass_store_merging::terminate_all_aliasing_chains (tree dest, tree base,
entry is removed after the processing in any case. */
bool
-pass_store_merging::terminate_and_release_chain (tree base)
+pass_store_merging::terminate_and_release_chain (imm_store_chain_info *chain_info)
{
- struct imm_store_chain_info **chain_info = m_stores.get (base);
-
- if (!chain_info)
- return false;
-
- gcc_assert (*chain_info);
-
- bool ret = (*chain_info)->terminate_and_process_chain (base);
- delete *chain_info;
- m_stores.remove (base);
-
+ bool ret = chain_info->terminate_and_process_chain ();
+ m_stores.remove (chain_info->base_addr);
+ delete chain_info;
return ret;
}
@@ -870,7 +881,7 @@ imm_store_chain_info::coalesce_immediate_stores ()
fprintf (dump_file, "Store %u:\nbitsize:" HOST_WIDE_INT_PRINT_DEC
" bitpos:" HOST_WIDE_INT_PRINT_DEC " val:\n",
i, info->bitsize, info->bitpos);
- print_generic_expr (dump_file, info->val, 0);
+ print_generic_expr (dump_file, gimple_assign_rhs1 (info->stmt), 0);
fprintf (dump_file, "\n------------\n");
}
@@ -1093,7 +1104,7 @@ split_group (merged_store_group *group,
return true. */
bool
-imm_store_chain_info::output_merged_store (tree base, merged_store_group *group)
+imm_store_chain_info::output_merged_store (merged_store_group *group)
{
unsigned HOST_WIDE_INT start_byte_pos = group->start / BITS_PER_UNIT;
@@ -1121,6 +1132,8 @@ imm_store_chain_info::output_merged_store (tree base, merged_store_group *group)
unsigned int i;
bool fail = false;
+ tree addr = force_gimple_operand_1 (unshare_expr (base_addr), &seq,
+ is_gimple_mem_ref_addr, NULL_TREE);
FOR_EACH_VEC_ELT (split_stores, i, split_store)
{
unsigned HOST_WIDE_INT try_size = split_store->size;
@@ -1130,8 +1143,7 @@ imm_store_chain_info::output_merged_store (tree base, merged_store_group *group)
location_t loc = get_location_for_stmts (split_store->orig_stmts);
tree int_type = build_nonstandard_integer_type (try_size, UNSIGNED);
- SET_TYPE_ALIGN (int_type, align);
- tree addr = build_fold_addr_expr (base);
+ int_type = build_aligned_type (int_type, align);
tree dest = fold_build2 (MEM_REF, int_type, addr,
build_int_cst (offset_type, try_pos));
@@ -1203,14 +1215,14 @@ imm_store_chain_info::output_merged_store (tree base, merged_store_group *group)
successful. Return true iff any changes were made. */
bool
-imm_store_chain_info::output_merged_stores (tree base)
+imm_store_chain_info::output_merged_stores ()
{
unsigned int i;
merged_store_group *merged_store;
bool ret = false;
FOR_EACH_VEC_ELT (m_merged_store_groups, i, merged_store)
{
- if (output_merged_store (base, merged_store))
+ if (output_merged_store (merged_store))
{
unsigned int j;
store_immediate_info *store;
@@ -1240,7 +1252,7 @@ imm_store_chain_info::output_merged_stores (tree base)
Return true if any changes were made. */
bool
-imm_store_chain_info::terminate_and_process_chain (tree base)
+imm_store_chain_info::terminate_and_process_chain ()
{
/* Process store chain. */
bool ret = false;
@@ -1248,7 +1260,7 @@ imm_store_chain_info::terminate_and_process_chain (tree base)
{
ret = coalesce_immediate_stores ();
if (ret)
- ret = output_merged_stores (base);
+ ret = output_merged_stores ();
}
/* Delete all the entries we allocated ourselves. */
@@ -1361,37 +1373,58 @@ pass_store_merging::execute (function *fun)
&unsignedp, &reversep, &volatilep);
/* As a future enhancement we could handle stores with the same
base and offset. */
- bool invalid = offset || reversep
+ bool invalid = reversep
|| ((bitsize > MAX_BITSIZE_MODE_ANY_INT)
&& (TREE_CODE (rhs) != INTEGER_CST))
- || !rhs_valid_for_store_merging_p (rhs)
- /* An access may not be volatile itself but base_addr may be
- a volatile decl i.e. MEM[&volatile-decl]. The hashing for
- tree_operand_hash won't consider such stores equal to each
- other so we can't track chains on them. */
- || TREE_THIS_VOLATILE (base_addr);
+ || !rhs_valid_for_store_merging_p (rhs);
+ /* We do not want to rewrite TARGET_MEM_REFs. */
+ if (TREE_CODE (base_addr) == TARGET_MEM_REF)
+ invalid = true;
/* In some cases get_inner_reference may return a
MEM_REF [ptr + byteoffset]. For the purposes of this pass
canonicalize the base_addr to MEM_REF [ptr] and take
byteoffset into account in the bitpos. This occurs in
PR 23684 and this way we can catch more chains. */
- if (TREE_CODE (base_addr) == MEM_REF
- && POINTER_TYPE_P (TREE_TYPE (TREE_OPERAND (base_addr, 0))))
+ else if (TREE_CODE (base_addr) == MEM_REF)
{
offset_int bit_off, byte_off = mem_ref_offset (base_addr);
bit_off = byte_off << LOG2_BITS_PER_UNIT;
bit_off += bitpos;
if (!wi::neg_p (bit_off) && wi::fits_shwi_p (bit_off))
- {
- bitpos = bit_off.to_shwi ();
- base_addr = build2 (MEM_REF, TREE_TYPE (base_addr),
- TREE_OPERAND (base_addr, 0),
- build_zero_cst (TREE_TYPE (
- TREE_OPERAND (base_addr, 1))));
- }
+ bitpos = bit_off.to_shwi ();
else
invalid = true;
+ base_addr = TREE_OPERAND (base_addr, 0);
+ }
+ /* get_inner_reference returns the base object, get at its
+ address now. */
+ else
+ {
+ if (bitpos < 0)
+ invalid = true;
+ base_addr = build_fold_addr_expr (base_addr);
+ }
+
+ if (! invalid
+ && offset != NULL_TREE)
+ {
+ /* If the access is variable offset then a base
+ decl has to be address-taken to be able to
+ emit pointer-based stores to it.
+ ??? We might be able to get away with
+ re-using the original base up to the first
+ variable part and then wrapping that inside
+ a BIT_FIELD_REF. */
+ tree base = get_base_address (base_addr);
+ if (! base
+ || (DECL_P (base)
+ && ! TREE_ADDRESSABLE (base)))
+ invalid = true;
+ else
+ base_addr = build2 (POINTER_PLUS_EXPR,
+ TREE_TYPE (base_addr),
+ base_addr, offset);
}
struct imm_store_chain_info **chain_info
@@ -1403,7 +1436,7 @@ pass_store_merging::execute (function *fun)
if (chain_info)
{
info = new store_immediate_info (
- bitsize, bitpos, rhs, lhs, stmt,
+ bitsize, bitpos, stmt,
(*chain_info)->m_store_info.length ());
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -1422,17 +1455,17 @@ pass_store_merging::execute (function *fun)
fprintf (dump_file,
"Reached maximum number of statements"
" to merge:\n");
- terminate_and_release_chain (base_addr);
+ terminate_and_release_chain (*chain_info);
}
continue;
}
/* Store aliases any existing chain? */
- terminate_all_aliasing_chains (lhs, base_addr, false, stmt);
+ terminate_all_aliasing_chains (chain_info, false, stmt);
/* Start a new chain. */
struct imm_store_chain_info *new_chain
- = new imm_store_chain_info;
- info = new store_immediate_info (bitsize, bitpos, rhs, lhs,
+ = new imm_store_chain_info (base_addr);
+ info = new store_immediate_info (bitsize, bitpos,
stmt, 0);
new_chain->m_store_info.safe_push (info);
m_stores.put (base_addr, new_chain);
@@ -1447,13 +1480,13 @@ pass_store_merging::execute (function *fun)
}
}
else
- terminate_all_aliasing_chains (lhs, base_addr,
+ terminate_all_aliasing_chains (chain_info,
offset != NULL_TREE, stmt);
continue;
}
- terminate_all_aliasing_chains (NULL_TREE, NULL_TREE, false, stmt);
+ terminate_all_aliasing_chains (NULL, false, stmt);
}
terminate_and_process_all_chains ();
}
@@ -1469,3 +1502,141 @@ make_pass_store_merging (gcc::context *ctxt)
{
return new pass_store_merging (ctxt);
}
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Selftests for store merging helpers. */
+
+/* Assert that all elements of the byte arrays X and Y, both of length N
+ are equal. */
+
+static void
+verify_array_eq (unsigned char *x, unsigned char *y, unsigned int n)
+{
+ for (unsigned int i = 0; i < n; i++)
+ {
+ if (x[i] != y[i])
+ {
+ fprintf (stderr, "Arrays do not match. X:\n");
+ dump_char_array (stderr, x, n);
+ fprintf (stderr, "Y:\n");
+ dump_char_array (stderr, y, n);
+ }
+ ASSERT_EQ (x[i], y[i]);
+ }
+}
+
+/* Test shift_bytes_in_array and that it carries bits across between
+ bytes correctly. */
+
+static void
+verify_shift_bytes_in_array (void)
+{
+ /* byte 1 | byte 0
+ 00011111 | 11100000. */
+ unsigned char orig[2] = { 0xe0, 0x1f };
+ unsigned char in[2];
+ memcpy (in, orig, sizeof orig);
+
+ unsigned char expected[2] = { 0x80, 0x7f };
+ shift_bytes_in_array (in, sizeof (in), 2);
+ verify_array_eq (in, expected, sizeof (in));
+
+ memcpy (in, orig, sizeof orig);
+ memcpy (expected, orig, sizeof orig);
+ /* Check that shifting by zero doesn't change anything. */
+ shift_bytes_in_array (in, sizeof (in), 0);
+ verify_array_eq (in, expected, sizeof (in));
+
+}
+
+/* Test shift_bytes_in_array_right and that it carries bits across between
+ bytes correctly. */
+
+static void
+verify_shift_bytes_in_array_right (void)
+{
+ /* byte 1 | byte 0
+ 00011111 | 11100000. */
+ unsigned char orig[2] = { 0x1f, 0xe0};
+ unsigned char in[2];
+ memcpy (in, orig, sizeof orig);
+ unsigned char expected[2] = { 0x07, 0xf8};
+ shift_bytes_in_array_right (in, sizeof (in), 2);
+ verify_array_eq (in, expected, sizeof (in));
+
+ memcpy (in, orig, sizeof orig);
+ memcpy (expected, orig, sizeof orig);
+ /* Check that shifting by zero doesn't change anything. */
+ shift_bytes_in_array_right (in, sizeof (in), 0);
+ verify_array_eq (in, expected, sizeof (in));
+}
+
+/* Test clear_bit_region that it clears exactly the bits asked and
+ nothing more. */
+
+static void
+verify_clear_bit_region (void)
+{
+ /* Start with all bits set and test clearing various patterns in them. */
+ unsigned char orig[3] = { 0xff, 0xff, 0xff};
+ unsigned char in[3];
+ unsigned char expected[3];
+ memcpy (in, orig, sizeof in);
+
+ /* Check zeroing out all the bits. */
+ clear_bit_region (in, 0, 3 * BITS_PER_UNIT);
+ expected[0] = expected[1] = expected[2] = 0;
+ verify_array_eq (in, expected, sizeof in);
+
+ memcpy (in, orig, sizeof in);
+ /* Leave the first and last bits intact. */
+ clear_bit_region (in, 1, 3 * BITS_PER_UNIT - 2);
+ expected[0] = 0x1;
+ expected[1] = 0;
+ expected[2] = 0x80;
+ verify_array_eq (in, expected, sizeof in);
+}
+
+/* Test verify_clear_bit_region_be that it clears exactly the bits asked and
+ nothing more. */
+
+static void
+verify_clear_bit_region_be (void)
+{
+ /* Start with all bits set and test clearing various patterns in them. */
+ unsigned char orig[3] = { 0xff, 0xff, 0xff};
+ unsigned char in[3];
+ unsigned char expected[3];
+ memcpy (in, orig, sizeof in);
+
+ /* Check zeroing out all the bits. */
+ clear_bit_region_be (in, BITS_PER_UNIT - 1, 3 * BITS_PER_UNIT);
+ expected[0] = expected[1] = expected[2] = 0;
+ verify_array_eq (in, expected, sizeof in);
+
+ memcpy (in, orig, sizeof in);
+ /* Leave the first and last bits intact. */
+ clear_bit_region_be (in, BITS_PER_UNIT - 2, 3 * BITS_PER_UNIT - 2);
+ expected[0] = 0x80;
+ expected[1] = 0;
+ expected[2] = 0x1;
+ verify_array_eq (in, expected, sizeof in);
+}
+
+
+/* Run all of the selftests within this file. */
+
+void
+store_merging_c_tests (void)
+{
+ verify_shift_bytes_in_array ();
+ verify_shift_bytes_in_array_right ();
+ verify_clear_bit_region ();
+ verify_clear_bit_region_be ();
+}
+
+} // namespace selftest
+#endif /* CHECKING_P. */
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index 5dad1193c27..bdfdb9a82b1 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -246,6 +246,13 @@ struct slsr_cand_d
replacement MEM_REF.) */
tree cand_type;
+ /* The type to be used to interpret the stride field when the stride
+ is not a constant. Normally the same as the type of the recorded
+ stride, but when the stride has been cast we need to maintain that
+ knowledge in order to make legal substitutions without losing
+ precision. When the stride is a constant, this will be sizetype. */
+ tree stride_type;
+
/* The kind of candidate (CAND_MULT, etc.). */
enum cand_kind kind;
@@ -502,6 +509,7 @@ find_basis_for_base_expr (slsr_cand_t c, tree base_expr)
|| one_basis->cand_stmt == c->cand_stmt
|| !operand_equal_p (one_basis->stride, c->stride, 0)
|| !types_compatible_p (one_basis->cand_type, c->cand_type)
+ || !types_compatible_p (one_basis->stride_type, c->stride_type)
|| !dominated_by_p (CDI_DOMINATORS,
gimple_bb (c->cand_stmt),
gimple_bb (one_basis->cand_stmt)))
@@ -615,7 +623,7 @@ record_potential_basis (slsr_cand_t c, tree base)
static slsr_cand_t
alloc_cand_and_find_basis (enum cand_kind kind, gimple *gs, tree base,
const widest_int &index, tree stride, tree ctype,
- unsigned savings)
+ tree stype, unsigned savings)
{
slsr_cand_t c = (slsr_cand_t) obstack_alloc (&cand_obstack,
sizeof (slsr_cand));
@@ -624,6 +632,7 @@ alloc_cand_and_find_basis (enum cand_kind kind, gimple *gs, tree base,
c->stride = stride;
c->index = index;
c->cand_type = ctype;
+ c->stride_type = stype;
c->kind = kind;
c->cand_num = cand_vec.length () + 1;
c->next_interp = 0;
@@ -809,7 +818,8 @@ slsr_process_phi (gphi *phi, bool speed)
base_type = TREE_TYPE (arg0_base);
c = alloc_cand_and_find_basis (CAND_PHI, phi, arg0_base,
- 0, integer_one_node, base_type, savings);
+ 0, integer_one_node, base_type,
+ sizetype, savings);
/* Add the candidate to the statement-candidate mapping. */
add_cand_for_stmt (phi, c);
@@ -838,7 +848,8 @@ backtrace_base_for_ref (tree *pbase)
e.g. 'B' is widened from an 'int' in order to calculate
a 64-bit address. */
if (CONVERT_EXPR_P (base_in)
- && legal_cast_p_1 (base_in, TREE_OPERAND (base_in, 0)))
+ && legal_cast_p_1 (TREE_TYPE (base_in),
+ TREE_TYPE (TREE_OPERAND (base_in, 0))))
base_in = get_unwidened (base_in, NULL_TREE);
if (TREE_CODE (base_in) != SSA_NAME)
@@ -995,7 +1006,7 @@ slsr_process_ref (gimple *gs)
return;
c = alloc_cand_and_find_basis (CAND_REF, gs, base, index, offset,
- type, 0);
+ type, sizetype, 0);
/* Add the candidate to the statement-candidate mapping. */
add_cand_for_stmt (gs, c);
@@ -1010,6 +1021,7 @@ static slsr_cand_t
create_mul_ssa_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
{
tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
+ tree stype = NULL_TREE;
widest_int index;
unsigned savings = 0;
slsr_cand_t c;
@@ -1030,6 +1042,7 @@ create_mul_ssa_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
index = base_cand->index;
stride = stride_in;
ctype = base_cand->cand_type;
+ stype = TREE_TYPE (stride_in);
if (has_single_use (base_in))
savings = (base_cand->dead_savings
+ stmt_cost (base_cand->cand_stmt, speed));
@@ -1045,6 +1058,7 @@ create_mul_ssa_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
index = base_cand->index * wi::to_widest (base_cand->stride);
stride = stride_in;
ctype = base_cand->cand_type;
+ stype = TREE_TYPE (stride_in);
if (has_single_use (base_in))
savings = (base_cand->dead_savings
+ stmt_cost (base_cand->cand_stmt, speed));
@@ -1064,10 +1078,11 @@ create_mul_ssa_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
index = 0;
stride = stride_in;
ctype = TREE_TYPE (base_in);
+ stype = TREE_TYPE (stride_in);
}
c = alloc_cand_and_find_basis (CAND_MULT, gs, base, index, stride,
- ctype, savings);
+ ctype, stype, savings);
return c;
}
@@ -1156,7 +1171,7 @@ create_mul_imm_cand (gimple *gs, tree base_in, tree stride_in, bool speed)
}
c = alloc_cand_and_find_basis (CAND_MULT, gs, base, index, stride,
- ctype, savings);
+ ctype, sizetype, savings);
return c;
}
@@ -1212,7 +1227,8 @@ static slsr_cand_t
create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
bool subtract_p, bool speed)
{
- tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL;
+ tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
+ tree stype = NULL_TREE;
widest_int index;
unsigned savings = 0;
slsr_cand_t c;
@@ -1237,6 +1253,7 @@ create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
index = -index;
stride = addend_cand->base_expr;
ctype = TREE_TYPE (base_in);
+ stype = addend_cand->cand_type;
if (has_single_use (addend_in))
savings = (addend_cand->dead_savings
+ stmt_cost (addend_cand->cand_stmt, speed));
@@ -1263,6 +1280,8 @@ create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
index = subtract_p ? -1 : 1;
stride = addend_in;
ctype = base_cand->cand_type;
+ stype = (TREE_CODE (addend_in) == INTEGER_CST ? sizetype
+ : TREE_TYPE (addend_in));
if (has_single_use (base_in))
savings = (base_cand->dead_savings
+ stmt_cost (base_cand->cand_stmt, speed));
@@ -1286,6 +1305,7 @@ create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
index = -index;
stride = subtrahend_cand->base_expr;
ctype = TREE_TYPE (base_in);
+ stype = subtrahend_cand->cand_type;
if (has_single_use (addend_in))
savings = (subtrahend_cand->dead_savings
+ stmt_cost (subtrahend_cand->cand_stmt, speed));
@@ -1312,10 +1332,12 @@ create_add_ssa_cand (gimple *gs, tree base_in, tree addend_in,
index = subtract_p ? -1 : 1;
stride = addend_in;
ctype = TREE_TYPE (base_in);
+ stype = (TREE_CODE (addend_in) == INTEGER_CST ? sizetype
+ : TREE_TYPE (addend_in));
}
c = alloc_cand_and_find_basis (CAND_ADD, gs, base, index, stride,
- ctype, savings);
+ ctype, stype, savings);
return c;
}
@@ -1329,6 +1351,7 @@ create_add_imm_cand (gimple *gs, tree base_in, const widest_int &index_in,
{
enum cand_kind kind = CAND_ADD;
tree base = NULL_TREE, stride = NULL_TREE, ctype = NULL_TREE;
+ tree stype = NULL_TREE;
widest_int index, multiple;
unsigned savings = 0;
slsr_cand_t c;
@@ -1356,6 +1379,7 @@ create_add_imm_cand (gimple *gs, tree base_in, const widest_int &index_in,
index = base_cand->index + multiple;
stride = base_cand->stride;
ctype = base_cand->cand_type;
+ stype = base_cand->stride_type;
if (has_single_use (base_in))
savings = (base_cand->dead_savings
+ stmt_cost (base_cand->cand_stmt, speed));
@@ -1376,10 +1400,11 @@ create_add_imm_cand (gimple *gs, tree base_in, const widest_int &index_in,
index = index_in;
stride = integer_one_node;
ctype = TREE_TYPE (base_in);
+ stype = sizetype;
}
c = alloc_cand_and_find_basis (kind, gs, base, index, stride,
- ctype, savings);
+ ctype, stype, savings);
return c;
}
@@ -1456,14 +1481,11 @@ slsr_process_neg (gimple *gs, tree rhs1, bool speed)
for more details. */
static bool
-legal_cast_p_1 (tree lhs, tree rhs)
+legal_cast_p_1 (tree lhs_type, tree rhs_type)
{
- tree lhs_type, rhs_type;
unsigned lhs_size, rhs_size;
bool lhs_wraps, rhs_wraps;
- lhs_type = TREE_TYPE (lhs);
- rhs_type = TREE_TYPE (rhs);
lhs_size = TYPE_PRECISION (lhs_type);
rhs_size = TYPE_PRECISION (rhs_type);
lhs_wraps = ANY_INTEGRAL_TYPE_P (lhs_type) && TYPE_OVERFLOW_WRAPS (lhs_type);
@@ -1521,7 +1543,7 @@ legal_cast_p (gimple *gs, tree rhs)
|| !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (gs)))
return false;
- return legal_cast_p_1 (gimple_assign_lhs (gs), rhs);
+ return legal_cast_p_1 (TREE_TYPE (gimple_assign_lhs (gs)), TREE_TYPE (rhs));
}
/* Given GS which is a cast to a scalar integer type, determine whether
@@ -1556,7 +1578,8 @@ slsr_process_cast (gimple *gs, tree rhs1, bool speed)
c = alloc_cand_and_find_basis (base_cand->kind, gs,
base_cand->base_expr,
base_cand->index, base_cand->stride,
- ctype, savings);
+ ctype, base_cand->stride_type,
+ savings);
if (base_cand->next_interp)
base_cand = lookup_cand (base_cand->next_interp);
else
@@ -1574,10 +1597,10 @@ slsr_process_cast (gimple *gs, tree rhs1, bool speed)
The first of these is somewhat arbitrary, but the choice of
1 for the stride simplifies the logic for propagating casts
into their uses. */
- c = alloc_cand_and_find_basis (CAND_ADD, gs, rhs1,
- 0, integer_one_node, ctype, 0);
- c2 = alloc_cand_and_find_basis (CAND_MULT, gs, rhs1,
- 0, integer_one_node, ctype, 0);
+ c = alloc_cand_and_find_basis (CAND_ADD, gs, rhs1, 0,
+ integer_one_node, ctype, sizetype, 0);
+ c2 = alloc_cand_and_find_basis (CAND_MULT, gs, rhs1, 0,
+ integer_one_node, ctype, sizetype, 0);
c->next_interp = c2->cand_num;
}
@@ -1613,7 +1636,8 @@ slsr_process_copy (gimple *gs, tree rhs1, bool speed)
c = alloc_cand_and_find_basis (base_cand->kind, gs,
base_cand->base_expr,
base_cand->index, base_cand->stride,
- base_cand->cand_type, savings);
+ base_cand->cand_type,
+ base_cand->stride_type, savings);
if (base_cand->next_interp)
base_cand = lookup_cand (base_cand->next_interp);
else
@@ -1631,10 +1655,12 @@ slsr_process_copy (gimple *gs, tree rhs1, bool speed)
The first of these is somewhat arbitrary, but the choice of
1 for the stride simplifies the logic for propagating casts
into their uses. */
- c = alloc_cand_and_find_basis (CAND_ADD, gs, rhs1,
- 0, integer_one_node, TREE_TYPE (rhs1), 0);
- c2 = alloc_cand_and_find_basis (CAND_MULT, gs, rhs1,
- 0, integer_one_node, TREE_TYPE (rhs1), 0);
+ c = alloc_cand_and_find_basis (CAND_ADD, gs, rhs1, 0,
+ integer_one_node, TREE_TYPE (rhs1),
+ sizetype, 0);
+ c2 = alloc_cand_and_find_basis (CAND_MULT, gs, rhs1, 0,
+ integer_one_node, TREE_TYPE (rhs1),
+ sizetype, 0);
c->next_interp = c2->cand_num;
}
@@ -1755,6 +1781,13 @@ dump_candidate (slsr_cand_t c)
fputs (" + ", dump_file);
print_decs (c->index, dump_file);
fputs (") * ", dump_file);
+ if (TREE_CODE (c->stride) != INTEGER_CST
+ && c->stride_type != TREE_TYPE (c->stride))
+ {
+ fputs ("(", dump_file);
+ print_generic_expr (dump_file, c->stride_type, 0);
+ fputs (")", dump_file);
+ }
print_generic_expr (dump_file, c->stride, 0);
fputs (" : ", dump_file);
break;
@@ -1764,6 +1797,13 @@ dump_candidate (slsr_cand_t c)
fputs (" + (", dump_file);
print_decs (c->index, dump_file);
fputs (" * ", dump_file);
+ if (TREE_CODE (c->stride) != INTEGER_CST
+ && c->stride_type != TREE_TYPE (c->stride))
+ {
+ fputs ("(", dump_file);
+ print_generic_expr (dump_file, c->stride_type, 0);
+ fputs (")", dump_file);
+ }
print_generic_expr (dump_file, c->stride, 0);
fputs (") : ", dump_file);
break;
@@ -2143,7 +2183,7 @@ create_add_on_incoming_edge (slsr_cand_t c, tree basis_name,
basic_block insert_bb;
gimple_stmt_iterator gsi;
tree lhs, basis_type;
- gassign *new_stmt;
+ gassign *new_stmt, *cast_stmt = NULL;
/* If the add candidate along this incoming edge has the same
index as C's hidden basis, the hidden basis represents this
@@ -2187,27 +2227,61 @@ create_add_on_incoming_edge (slsr_cand_t c, tree basis_name,
new_stmt = gimple_build_assign (lhs, code, basis_name,
incr_vec[i].initializer);
}
- else if (increment == 1)
- new_stmt = gimple_build_assign (lhs, plus_code, basis_name, c->stride);
- else if (increment == -1)
- new_stmt = gimple_build_assign (lhs, MINUS_EXPR, basis_name,
- c->stride);
- else
- gcc_unreachable ();
+ else {
+ tree stride;
+
+ if (!types_compatible_p (TREE_TYPE (c->stride), c->stride_type))
+ {
+ tree cast_stride = make_temp_ssa_name (c->stride_type, NULL,
+ "slsr");
+ cast_stmt = gimple_build_assign (cast_stride, NOP_EXPR,
+ c->stride);
+ stride = cast_stride;
+ }
+ else
+ stride = c->stride;
+
+ if (increment == 1)
+ new_stmt = gimple_build_assign (lhs, plus_code, basis_name, stride);
+ else if (increment == -1)
+ new_stmt = gimple_build_assign (lhs, MINUS_EXPR, basis_name, stride);
+ else
+ gcc_unreachable ();
+ }
}
insert_bb = single_succ_p (e->src) ? e->src : split_edge (e);
gsi = gsi_last_bb (insert_bb);
if (!gsi_end_p (gsi) && is_ctrl_stmt (gsi_stmt (gsi)))
- gsi_insert_before (&gsi, new_stmt, GSI_NEW_STMT);
+ {
+ gsi_insert_before (&gsi, new_stmt, GSI_SAME_STMT);
+ if (cast_stmt)
+ {
+ gsi_insert_before (&gsi, cast_stmt, GSI_SAME_STMT);
+ gimple_set_location (cast_stmt, loc);
+ }
+ }
else
- gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
+ {
+ if (cast_stmt)
+ {
+ gsi_insert_after (&gsi, cast_stmt, GSI_NEW_STMT);
+ gimple_set_location (cast_stmt, loc);
+ }
+ gsi_insert_after (&gsi, new_stmt, GSI_NEW_STMT);
+ }
gimple_set_location (new_stmt, loc);
if (dump_file && (dump_flags & TDF_DETAILS))
{
+ if (cast_stmt)
+ {
+ fprintf (dump_file, "Inserting cast in block %d: ",
+ insert_bb->index);
+ print_gimple_stmt (dump_file, cast_stmt, 0, 0);
+ }
fprintf (dump_file, "Inserting in block %d: ", insert_bb->index);
print_gimple_stmt (dump_file, new_stmt, 0, 0);
}
@@ -2825,40 +2899,35 @@ analyze_increments (slsr_cand_t first_dep, machine_mode mode, bool speed)
&& !POINTER_TYPE_P (first_dep->cand_type)))
incr_vec[i].cost = COST_NEUTRAL;
- /* FORNOW: If we need to add an initializer, give up if a cast from
- the candidate's type to its stride's type can lose precision.
- This could eventually be handled better by expressly retaining the
- result of a cast to a wider type in the stride. Example:
+ /* If we need to add an initializer, give up if a cast from the
+ candidate's type to its stride's type can lose precision.
+ Note that this already takes into account that the stride may
+ have been cast to a wider type, in which case this test won't
+ fire. Example:
short int _1;
_2 = (int) _1;
_3 = _2 * 10;
- _4 = x + _3; ADD: x + (10 * _1) : int
+ _4 = x + _3; ADD: x + (10 * (int)_1) : int
_5 = _2 * 15;
- _6 = x + _3; ADD: x + (15 * _1) : int
-
- Right now replacing _6 would cause insertion of an initializer
- of the form "short int T = _1 * 5;" followed by a cast to
- int, which could overflow incorrectly. Had we recorded _2 or
- (int)_1 as the stride, this wouldn't happen. However, doing
- this breaks other opportunities, so this will require some
- care. */
+ _6 = x + _5; ADD: x + (15 * (int)_1) : int
+
+ Although the stride was a short int initially, the stride
+ used in the analysis has been widened to an int, and such
+ widening will be done in the initializer as well. */
else if (!incr_vec[i].initializer
&& TREE_CODE (first_dep->stride) != INTEGER_CST
- && !legal_cast_p_1 (first_dep->stride,
- gimple_assign_lhs (first_dep->cand_stmt)))
-
+ && !legal_cast_p_1 (first_dep->stride_type,
+ TREE_TYPE (gimple_assign_lhs
+ (first_dep->cand_stmt))))
incr_vec[i].cost = COST_INFINITE;
/* If we need to add an initializer, make sure we don't introduce
a multiply by a pointer type, which can happen in certain cast
- scenarios. FIXME: When cleaning up these cast issues, we can
- afford to introduce the multiply provided we cast out to an
- unsigned int of appropriate size. */
+ scenarios. */
else if (!incr_vec[i].initializer
&& TREE_CODE (first_dep->stride) != INTEGER_CST
- && POINTER_TYPE_P (TREE_TYPE (first_dep->stride)))
-
+ && POINTER_TYPE_P (first_dep->stride_type))
incr_vec[i].cost = COST_INFINITE;
/* For any other increment, if this is a multiply candidate, we
@@ -3105,7 +3174,8 @@ insert_initializers (slsr_cand_t c)
basic_block bb;
slsr_cand_t where = NULL;
gassign *init_stmt;
- tree stride_type, new_name, incr_tree;
+ gassign *cast_stmt = NULL;
+ tree new_name, incr_tree, init_stride;
widest_int incr = incr_vec[i].incr;
if (!profitable_increment_p (i)
@@ -3134,37 +3204,74 @@ insert_initializers (slsr_cand_t c)
that block, the earliest one will be returned in WHERE. */
bb = nearest_common_dominator_for_cands (c, incr, &where);
+ /* If the nominal stride has a different type than the recorded
+ stride type, build a cast from the nominal stride to that type. */
+ if (!types_compatible_p (TREE_TYPE (c->stride), c->stride_type))
+ {
+ init_stride = make_temp_ssa_name (c->stride_type, NULL, "slsr");
+ cast_stmt = gimple_build_assign (init_stride, NOP_EXPR, c->stride);
+ }
+ else
+ init_stride = c->stride;
+
/* Create a new SSA name to hold the initializer's value. */
- stride_type = TREE_TYPE (c->stride);
- new_name = make_temp_ssa_name (stride_type, NULL, "slsr");
+ new_name = make_temp_ssa_name (c->stride_type, NULL, "slsr");
incr_vec[i].initializer = new_name;
/* Create the initializer and insert it in the latest possible
dominating position. */
- incr_tree = wide_int_to_tree (stride_type, incr);
+ incr_tree = wide_int_to_tree (c->stride_type, incr);
init_stmt = gimple_build_assign (new_name, MULT_EXPR,
- c->stride, incr_tree);
+ init_stride, incr_tree);
if (where)
{
gimple_stmt_iterator gsi = gsi_for_stmt (where->cand_stmt);
+ location_t loc = gimple_location (where->cand_stmt);
+
+ if (cast_stmt)
+ {
+ gsi_insert_before (&gsi, cast_stmt, GSI_SAME_STMT);
+ gimple_set_location (cast_stmt, loc);
+ }
+
gsi_insert_before (&gsi, init_stmt, GSI_SAME_STMT);
- gimple_set_location (init_stmt, gimple_location (where->cand_stmt));
+ gimple_set_location (init_stmt, loc);
}
else
{
gimple_stmt_iterator gsi = gsi_last_bb (bb);
gimple *basis_stmt = lookup_cand (c->basis)->cand_stmt;
+ location_t loc = gimple_location (basis_stmt);
if (!gsi_end_p (gsi) && is_ctrl_stmt (gsi_stmt (gsi)))
- gsi_insert_before (&gsi, init_stmt, GSI_SAME_STMT);
+ {
+ if (cast_stmt)
+ {
+ gsi_insert_before (&gsi, cast_stmt, GSI_SAME_STMT);
+ gimple_set_location (cast_stmt, loc);
+ }
+ gsi_insert_before (&gsi, init_stmt, GSI_SAME_STMT);
+ }
else
- gsi_insert_after (&gsi, init_stmt, GSI_SAME_STMT);
+ {
+ if (cast_stmt)
+ {
+ gsi_insert_after (&gsi, cast_stmt, GSI_NEW_STMT);
+ gimple_set_location (cast_stmt, loc);
+ }
+ gsi_insert_after (&gsi, init_stmt, GSI_SAME_STMT);
+ }
gimple_set_location (init_stmt, gimple_location (basis_stmt));
}
if (dump_file && (dump_flags & TDF_DETAILS))
{
+ if (cast_stmt)
+ {
+ fputs ("Inserting stride cast: ", dump_file);
+ print_gimple_stmt (dump_file, cast_stmt, 0, 0);
+ }
fputs ("Inserting initializer: ", dump_file);
print_gimple_stmt (dump_file, init_stmt, 0, 0);
}
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 26e9322dcff..0a3dc72ea21 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3. If not see
#include "builtins.h"
#include "selftest.h"
#include "gimple-pretty-print.h"
+#include "asan.h"
/* All the tuples have their operand vector (if present) at the very bottom
@@ -2629,6 +2630,8 @@ nonfreeing_call_p (gimple *call)
{
case IFN_ABNORMAL_DISPATCHER:
return true;
+ case IFN_ASAN_MARK:
+ return tree_to_uhwi (gimple_call_arg (call, 0)) == ASAN_MARK_UNCLOBBER;
default:
if (gimple_call_flags (call) & ECF_LEAF)
return true;
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index 1531582be11..d392450ddf5 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -59,6 +59,11 @@ along with GCC; see the file COPYING3. If not see
#include "gimple-walk.h"
#include "langhooks-def.h" /* FIXME: for lhd_set_decl_assembler_name */
#include "builtins.h"
+#include "asan.h"
+#include "dbgcnt.h"
+
+/* Hash set of poisoned variables in a bind expr. */
+static hash_set<tree> *asan_poisoned_variables = NULL;
enum gimplify_omp_var_data
{
@@ -151,6 +156,7 @@ struct gimplify_ctx
tree return_temp;
vec<tree> case_labels;
+ hash_set<tree> *live_switch_vars;
/* The formal temporary table. Should this be persistent? */
hash_table<gimplify_hasher> *temp_htab;
@@ -1088,6 +1094,121 @@ build_stack_save_restore (gcall **save, gcall **restore)
1, tmp_var);
}
+/* Generate IFN_ASAN_MARK call that poisons shadow of a for DECL variable. */
+
+static tree
+build_asan_poison_call_expr (tree decl)
+{
+ /* Do not poison variables that have size equal to zero. */
+ tree unit_size = DECL_SIZE_UNIT (decl);
+ if (zerop (unit_size))
+ return NULL_TREE;
+
+ tree base = build_fold_addr_expr (decl);
+
+ return build_call_expr_internal_loc (UNKNOWN_LOCATION, IFN_ASAN_MARK,
+ void_type_node, 3,
+ build_int_cst (integer_type_node,
+ ASAN_MARK_CLOBBER),
+ base, unit_size);
+}
+
+/* Generate IFN_ASAN_MARK call that would poison or unpoison, depending
+ on POISON flag, shadow memory of a DECL variable. The call will be
+ put on location identified by IT iterator, where BEFORE flag drives
+ position where the stmt will be put. */
+
+static void
+asan_poison_variable (tree decl, bool poison, gimple_stmt_iterator *it,
+ bool before)
+{
+ /* When within an OMP context, do not emit ASAN_MARK internal fns. */
+ if (gimplify_omp_ctxp)
+ return;
+
+ tree unit_size = DECL_SIZE_UNIT (decl);
+ tree base = build_fold_addr_expr (decl);
+
+ /* Do not poison variables that have size equal to zero. */
+ if (zerop (unit_size))
+ return;
+
+ /* It's necessary to have all stack variables aligned to ASAN granularity
+ bytes. */
+ if (DECL_ALIGN_UNIT (decl) <= ASAN_SHADOW_GRANULARITY)
+ SET_DECL_ALIGN (decl, BITS_PER_UNIT * ASAN_SHADOW_GRANULARITY);
+
+ HOST_WIDE_INT flags = poison ? ASAN_MARK_CLOBBER : ASAN_MARK_UNCLOBBER;
+
+ gimple *g
+ = gimple_build_call_internal (IFN_ASAN_MARK, 3,
+ build_int_cst (integer_type_node, flags),
+ base, unit_size);
+
+ if (before)
+ gsi_insert_before (it, g, GSI_NEW_STMT);
+ else
+ gsi_insert_after (it, g, GSI_NEW_STMT);
+}
+
+/* Generate IFN_ASAN_MARK internal call that depending on POISON flag
+ either poisons or unpoisons a DECL. Created statement is appended
+ to SEQ_P gimple sequence. */
+
+static void
+asan_poison_variable (tree decl, bool poison, gimple_seq *seq_p)
+{
+ gimple_stmt_iterator it = gsi_last (*seq_p);
+ bool before = false;
+
+ if (gsi_end_p (it))
+ before = true;
+
+ asan_poison_variable (decl, poison, &it, before);
+}
+
+/* Sort pair of VAR_DECLs A and B by DECL_UID. */
+
+static int
+sort_by_decl_uid (const void *a, const void *b)
+{
+ const tree *t1 = (const tree *)a;
+ const tree *t2 = (const tree *)b;
+
+ int uid1 = DECL_UID (*t1);
+ int uid2 = DECL_UID (*t2);
+
+ if (uid1 < uid2)
+ return -1;
+ else if (uid1 > uid2)
+ return 1;
+ else
+ return 0;
+}
+
+/* Generate IFN_ASAN_MARK internal call for all VARIABLES
+ depending on POISON flag. Created statement is appended
+ to SEQ_P gimple sequence. */
+
+static void
+asan_poison_variables (hash_set<tree> *variables, bool poison, gimple_seq *seq_p)
+{
+ unsigned c = variables->elements ();
+ if (c == 0)
+ return;
+
+ auto_vec<tree> sorted_variables (c);
+
+ for (hash_set<tree>::iterator it = variables->begin ();
+ it != variables->end (); ++it)
+ sorted_variables.safe_push (*it);
+
+ sorted_variables.qsort (sort_by_decl_uid);
+
+ for (unsigned i = 0; i < sorted_variables.length (); i++)
+ asan_poison_variable (sorted_variables[i], poison, seq_p);
+}
+
/* Gimplify a BIND_EXPR. Just voidify and recurse. */
static enum gimplify_status
@@ -1231,6 +1352,17 @@ gimplify_bind_expr (tree *expr_p, gimple_seq *pre_p)
}
}
}
+
+ if (asan_poisoned_variables != NULL
+ && asan_poisoned_variables->contains (t))
+ {
+ asan_poisoned_variables->remove (t);
+ asan_poison_variable (t, true, &cleanup);
+ }
+
+ if (gimplify_ctxp->live_switch_vars != NULL
+ && gimplify_ctxp->live_switch_vars->contains (t))
+ gimplify_ctxp->live_switch_vars->remove (t);
}
if (ret_clauses)
@@ -1475,13 +1607,31 @@ gimplify_decl_expr (tree *stmt_p, gimple_seq *seq_p)
if (VAR_P (decl) && !DECL_EXTERNAL (decl))
{
tree init = DECL_INITIAL (decl);
+ bool is_vla = false;
if (TREE_CODE (DECL_SIZE_UNIT (decl)) != INTEGER_CST
|| (!TREE_STATIC (decl)
&& flag_stack_check == GENERIC_STACK_CHECK
&& compare_tree_int (DECL_SIZE_UNIT (decl),
STACK_CHECK_MAX_VAR_SIZE) > 0))
- gimplify_vla_decl (decl, seq_p);
+ {
+ gimplify_vla_decl (decl, seq_p);
+ is_vla = true;
+ }
+
+ if (asan_sanitize_use_after_scope ()
+ && !asan_no_sanitize_address_p ()
+ && !is_vla
+ && TREE_ADDRESSABLE (decl)
+ && !TREE_STATIC (decl)
+ && !DECL_HAS_VALUE_EXPR_P (decl)
+ && dbg_cnt (asan_use_after_scope))
+ {
+ asan_poisoned_variables->add (decl);
+ asan_poison_variable (decl, false, seq_p);
+ if (!DECL_ARTIFICIAL (decl) && gimplify_ctxp->live_switch_vars)
+ gimplify_ctxp->live_switch_vars->add (decl);
+ }
/* Some front ends do not explicitly declare all anonymous
artificial variables. We compensate here by declaring the
@@ -1591,6 +1741,13 @@ warn_switch_unreachable_r (gimple_stmt_iterator *gsi_p, bool *handled_ops_p,
/* Walk the sub-statements. */
*handled_ops_p = false;
break;
+ case GIMPLE_CALL:
+ if (gimple_call_internal_p (stmt, IFN_ASAN_MARK))
+ {
+ *handled_ops_p = false;
+ break;
+ }
+ /* Fall through. */
default:
/* Save the first "real" statement (not a decl/lexical scope/...). */
wi->info = stmt;
@@ -1802,6 +1959,8 @@ collect_fallthrough_labels (gimple_stmt_iterator *gsi_p,
if (find_label_entry (labels, label))
prev = gsi_stmt (*gsi_p);
}
+ else if (gimple_call_internal_p (gsi_stmt (*gsi_p), IFN_ASAN_MARK))
+ ;
else
prev = gsi_stmt (*gsi_p);
gsi_next (gsi_p);
@@ -2082,6 +2241,7 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
{
vec<tree> labels;
vec<tree> saved_labels;
+ hash_set<tree> *saved_live_switch_vars;
tree default_case = NULL_TREE;
gswitch *switch_stmt;
@@ -2093,6 +2253,8 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
labels. Save all the things from the switch body to append after. */
saved_labels = gimplify_ctxp->case_labels;
gimplify_ctxp->case_labels.create (8);
+ saved_live_switch_vars = gimplify_ctxp->live_switch_vars;
+ gimplify_ctxp->live_switch_vars = new hash_set<tree> (4);
bool old_in_switch_expr = gimplify_ctxp->in_switch_expr;
gimplify_ctxp->in_switch_expr = true;
@@ -2107,6 +2269,9 @@ gimplify_switch_expr (tree *expr_p, gimple_seq *pre_p)
labels = gimplify_ctxp->case_labels;
gimplify_ctxp->case_labels = saved_labels;
+ gcc_assert (gimplify_ctxp->live_switch_vars->elements () == 0);
+ delete gimplify_ctxp->live_switch_vars;
+ gimplify_ctxp->live_switch_vars = saved_live_switch_vars;
preprocess_case_label_vec_for_gimple (labels, index_type,
&default_case);
@@ -6164,6 +6329,9 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
tree init = TARGET_EXPR_INITIAL (targ);
enum gimplify_status ret;
+ bool unpoison_empty_seq = false;
+ gimple_stmt_iterator unpoison_it;
+
if (init)
{
tree cleanup = NULL_TREE;
@@ -6177,7 +6345,14 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
gimplify_vla_decl (temp, pre_p);
}
else
- gimple_add_tmp_var (temp);
+ {
+ /* Save location where we need to place unpoisoning. It's possible
+ that a variable will be converted to needs_to_live_in_memory. */
+ unpoison_it = gsi_last (*pre_p);
+ unpoison_empty_seq = gsi_end_p (unpoison_it);
+
+ gimple_add_tmp_var (temp);
+ }
/* If TARGET_EXPR_INITIAL is void, then the mere evaluation of the
expression is supposed to initialize the slot. */
@@ -6213,20 +6388,35 @@ gimplify_target_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
/* Add a clobber for the temporary going out of scope, like
gimplify_bind_expr. */
if (gimplify_ctxp->in_cleanup_point_expr
- && needs_to_live_in_memory (temp)
- && flag_stack_reuse == SR_ALL)
- {
- tree clobber = build_constructor (TREE_TYPE (temp),
- NULL);
- TREE_THIS_VOLATILE (clobber) = true;
- clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
- if (cleanup)
- cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup,
- clobber);
- else
- cleanup = clobber;
- }
+ && needs_to_live_in_memory (temp))
+ {
+ if (flag_stack_reuse == SR_ALL)
+ {
+ tree clobber = build_constructor (TREE_TYPE (temp),
+ NULL);
+ TREE_THIS_VOLATILE (clobber) = true;
+ clobber = build2 (MODIFY_EXPR, TREE_TYPE (temp), temp, clobber);
+ if (cleanup)
+ cleanup = build2 (COMPOUND_EXPR, void_type_node, cleanup,
+ clobber);
+ else
+ cleanup = clobber;
+ }
+ if (asan_sanitize_use_after_scope ()
+ && dbg_cnt (asan_use_after_scope))
+ {
+ tree asan_cleanup = build_asan_poison_call_expr (temp);
+ if (asan_cleanup)
+ {
+ if (unpoison_empty_seq)
+ unpoison_it = gsi_start (*pre_p);
+ asan_poison_variable (temp, false, &unpoison_it,
+ unpoison_empty_seq);
+ gimple_push_cleanup (temp, asan_cleanup, false, pre_p);
+ }
+ }
+ }
if (cleanup)
gimple_push_cleanup (temp, cleanup, false, pre_p);
@@ -10824,6 +11014,7 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
location_t saved_location;
enum gimplify_status ret;
gimple_stmt_iterator pre_last_gsi, post_last_gsi;
+ tree label;
save_expr = *expr_p;
if (save_expr == NULL_TREE)
@@ -11239,10 +11430,24 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
case LABEL_EXPR:
ret = gimplify_label_expr (expr_p, pre_p);
+ label = LABEL_EXPR_LABEL (*expr_p);
+ gcc_assert (decl_function_context (label) == current_function_decl);
+
+ /* If the label is used in a goto statement, or address of the label
+ is taken, we need to unpoison all variables that were seen so far.
+ Doing so would prevent us from reporting a false positives. */
+ if (asan_sanitize_use_after_scope ()
+ && asan_used_labels != NULL
+ && asan_used_labels->contains (label))
+ asan_poison_variables (asan_poisoned_variables, false, pre_p);
break;
case CASE_LABEL_EXPR:
ret = gimplify_case_label_expr (expr_p, pre_p);
+
+ if (gimplify_ctxp->live_switch_vars)
+ asan_poison_variables (gimplify_ctxp->live_switch_vars, false,
+ pre_p);
break;
case RETURN_EXPR:
@@ -12336,7 +12541,10 @@ gimplify_function_tree (tree fndecl)
&& !needs_to_live_in_memory (ret))
DECL_GIMPLE_REG_P (ret) = 1;
+ asan_poisoned_variables = new hash_set<tree> ();
bind = gimplify_body (fndecl, true);
+ delete asan_poisoned_variables;
+ asan_poisoned_variables = NULL;
/* The tree body of the function is no longer needed, replace it
with the new GIMPLE body. */
diff --git a/gcc/go/gofrontend/MERGE b/gcc/go/gofrontend/MERGE
index fcc2f9f9af9..9049bc37476 100644
--- a/gcc/go/gofrontend/MERGE
+++ b/gcc/go/gofrontend/MERGE
@@ -1,4 +1,4 @@
-6d9929a1641b180e724c2fdcdd55f6a254f1dec0
+afe0456d25e3c6c0d91a8fd4c0fdfdbaa35cc251
The first line of this file holds the git revision number of the last
merge done from the gofrontend repository.
diff --git a/gcc/go/gofrontend/escape.cc b/gcc/go/gofrontend/escape.cc
index ba55ea314c3..bcea63d5a6e 100644
--- a/gcc/go/gofrontend/escape.cc
+++ b/gcc/go/gofrontend/escape.cc
@@ -284,20 +284,19 @@ Node::op_format() const
op << "panic";
break;
- case Runtime::APPEND:
+ case Runtime::GROWSLICE:
op << "append";
break;
- case Runtime::COPY:
+ case Runtime::SLICECOPY:
+ case Runtime::SLICESTRINGCOPY:
+ case Runtime::TYPEDSLICECOPY:
op << "copy";
break;
case Runtime::MAKECHAN:
case Runtime::MAKEMAP:
- case Runtime::MAKESLICE1:
- case Runtime::MAKESLICE2:
- case Runtime::MAKESLICE1BIG:
- case Runtime::MAKESLICE2BIG:
+ case Runtime::MAKESLICE:
op << "make";
break;
@@ -419,10 +418,7 @@ Node::is_big(Escape_context* context) const
Func_expression* fn = call->fn()->func_expression();
if (fn != NULL
&& fn->is_runtime_function()
- && (fn->runtime_code() == Runtime::MAKESLICE1
- || fn->runtime_code() == Runtime::MAKESLICE2
- || fn->runtime_code() == Runtime::MAKESLICE1BIG
- || fn->runtime_code() == Runtime::MAKESLICE2BIG))
+ && fn->runtime_code() == Runtime::MAKESLICE)
{
// Second argument is length.
Expression_list::iterator p = call->args()->begin();
@@ -1201,13 +1197,25 @@ Escape_analysis_assign::expression(Expression** pexpr)
}
break;
- case Runtime::APPEND:
+ case Runtime::GROWSLICE:
{
- // Unlike gc/esc.go, a call to append has already had its
- // varargs lowered into a slice of arguments.
- // The content of the appended slice leaks.
- Node* appended = Node::make_node(call->args()->back());
- this->assign_deref(this->context_->sink(), appended);
+ // The contents being appended leak.
+ if (call->is_varargs())
+ {
+ Node* appended = Node::make_node(call->args()->back());
+ this->assign_deref(this->context_->sink(), appended);
+ }
+ else
+ {
+ for (Expression_list::const_iterator pa =
+ call->args()->begin();
+ pa != call->args()->end();
+ ++pa)
+ {
+ Node* arg = Node::make_node(*pa);
+ this->assign(this->context_->sink(), arg);
+ }
+ }
if (debug_level > 2)
go_error_at((*pexpr)->location(),
@@ -1219,7 +1227,9 @@ Escape_analysis_assign::expression(Expression** pexpr)
}
break;
- case Runtime::COPY:
+ case Runtime::SLICECOPY:
+ case Runtime::SLICESTRINGCOPY:
+ case Runtime::TYPEDSLICECOPY:
{
// Lose track of the copied content.
Node* copied = Node::make_node(call->args()->back());
@@ -1229,10 +1239,7 @@ Escape_analysis_assign::expression(Expression** pexpr)
case Runtime::MAKECHAN:
case Runtime::MAKEMAP:
- case Runtime::MAKESLICE1:
- case Runtime::MAKESLICE2:
- case Runtime::MAKESLICE1BIG:
- case Runtime::MAKESLICE2BIG:
+ case Runtime::MAKESLICE:
case Runtime::SLICEBYTETOSTRING:
case Runtime::SLICERUNETOSTRING:
case Runtime::STRINGTOSLICEBYTE:
@@ -1829,7 +1836,7 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
{
switch (fe->runtime_code())
{
- case Runtime::APPEND:
+ case Runtime::GROWSLICE:
{
// Append returns the first argument.
// The subsequent arguments are already leaked because
@@ -1841,10 +1848,7 @@ Escape_analysis_assign::assign(Node* dst, Node* src)
case Runtime::MAKECHAN:
case Runtime::MAKEMAP:
- case Runtime::MAKESLICE1:
- case Runtime::MAKESLICE2:
- case Runtime::MAKESLICE1BIG:
- case Runtime::MAKESLICE2BIG:
+ case Runtime::MAKESLICE:
// DST = make(...).
case Runtime::SLICEBYTETOSTRING:
// DST = string([]byte{...}).
@@ -2608,7 +2612,7 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
{
switch (func->runtime_code())
{
- case Runtime::APPEND:
+ case Runtime::GROWSLICE:
{
// Propagate escape information to appendee.
Expression* appendee = call->args()->front();
@@ -2618,10 +2622,7 @@ Escape_analysis_flood::flood(Level level, Node* dst, Node* src,
case Runtime::MAKECHAN:
case Runtime::MAKEMAP:
- case Runtime::MAKESLICE1:
- case Runtime::MAKESLICE2:
- case Runtime::MAKESLICE1BIG:
- case Runtime::MAKESLICE2BIG:
+ case Runtime::MAKESLICE:
case Runtime::SLICEBYTETOSTRING:
case Runtime::SLICERUNETOSTRING:
case Runtime::STRINGTOSLICEBYTE:
diff --git a/gcc/go/gofrontend/expressions.cc b/gcc/go/gofrontend/expressions.cc
index 241dc36e5e1..69f4e016ba4 100644
--- a/gcc/go/gofrontend/expressions.cc
+++ b/gcc/go/gofrontend/expressions.cc
@@ -6951,7 +6951,9 @@ class Builtin_call_expression : public Call_expression
complex_type(Type*);
Expression*
- lower_make();
+ lower_make(Statement_inserter*);
+
+ Expression* flatten_append(Gogo*, Named_object*, Statement_inserter*);
bool
check_int_value(Expression*, bool is_length);
@@ -7052,7 +7054,7 @@ Builtin_call_expression::do_set_recover_arg(Expression* arg)
// specific expressions. We also convert to a constant if we can.
Expression*
-Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
+Builtin_call_expression::do_lower(Gogo*, Named_object* function,
Statement_inserter* inserter, int)
{
if (this->is_error_expression())
@@ -7130,7 +7132,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
break;
case BUILTIN_MAKE:
- return this->lower_make();
+ return this->lower_make(inserter);
case BUILTIN_RECOVER:
if (function != NULL)
@@ -7144,30 +7146,6 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
}
break;
- case BUILTIN_APPEND:
- {
- // Lower the varargs.
- const Expression_list* args = this->args();
- if (args == NULL || args->empty())
- return this;
- Type* slice_type = args->front()->type();
- if (!slice_type->is_slice_type())
- {
- if (slice_type->is_nil_type())
- go_error_at(args->front()->location(), "use of untyped nil");
- else
- go_error_at(args->front()->location(),
- "argument 1 must be a slice");
- this->set_is_error();
- return this;
- }
- Type* element_type = slice_type->array_type()->element_type();
- this->lower_varargs(gogo, function, inserter,
- Type::make_array_type(element_type, NULL),
- 2, SLICE_STORAGE_DOES_NOT_ESCAPE);
- }
- break;
-
case BUILTIN_DELETE:
{
// Lower to a runtime function call.
@@ -7215,7 +7193,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
pa != this->args()->end();
++pa)
{
- if (!(*pa)->is_variable())
+ if (!(*pa)->is_variable() && !(*pa)->is_constant())
{
Temporary_statement* temp =
Statement::make_temporary(NULL, *pa, loc);
@@ -7233,7 +7211,7 @@ Builtin_call_expression::do_lower(Gogo* gogo, Named_object* function,
// append into temporary expressions.
Expression*
-Builtin_call_expression::do_flatten(Gogo*, Named_object*,
+Builtin_call_expression::do_flatten(Gogo* gogo, Named_object* function,
Statement_inserter* inserter)
{
Location loc = this->location();
@@ -7244,6 +7222,8 @@ Builtin_call_expression::do_flatten(Gogo*, Named_object*,
break;
case BUILTIN_APPEND:
+ return this->flatten_append(gogo, function, inserter);
+
case BUILTIN_COPY:
{
Type* at = this->args()->front()->type();
@@ -7285,16 +7265,19 @@ Builtin_call_expression::do_flatten(Gogo*, Named_object*,
case BUILTIN_LEN:
case BUILTIN_CAP:
- Expression_list::iterator pa = this->args()->begin();
- if (!(*pa)->is_variable()
- && ((*pa)->type()->map_type() != NULL
- || (*pa)->type()->channel_type() != NULL))
- {
- Temporary_statement* temp =
- Statement::make_temporary(NULL, *pa, loc);
- inserter->insert(temp);
- *pa = Expression::make_temporary_reference(temp, loc);
- }
+ {
+ Expression_list::iterator pa = this->args()->begin();
+ if (!(*pa)->is_variable()
+ && ((*pa)->type()->map_type() != NULL
+ || (*pa)->type()->channel_type() != NULL))
+ {
+ Temporary_statement* temp =
+ Statement::make_temporary(NULL, *pa, loc);
+ inserter->insert(temp);
+ *pa = Expression::make_temporary_reference(temp, loc);
+ }
+ }
+ break;
}
return this;
@@ -7303,7 +7286,7 @@ Builtin_call_expression::do_flatten(Gogo*, Named_object*,
// Lower a make expression.
Expression*
-Builtin_call_expression::lower_make()
+Builtin_call_expression::lower_make(Statement_inserter* inserter)
{
Location loc = this->location();
@@ -7340,10 +7323,6 @@ Builtin_call_expression::lower_make()
return Expression::make_error(this->location());
}
- bool have_big_args = false;
- Type* uintptr_type = Type::lookup_integer_type("uintptr");
- int uintptr_bits = uintptr_type->integer_type()->bits();
-
Type_context int_context(Type::lookup_integer_type("int"), false);
++parg;
@@ -7363,9 +7342,6 @@ Builtin_call_expression::lower_make()
len_arg->determine_type(&int_context);
if (!this->check_int_value(len_arg, true))
return Expression::make_error(this->location());
- if (len_arg->type()->integer_type() != NULL
- && len_arg->type()->integer_type()->bits() > uintptr_bits)
- have_big_args = true;
++parg;
}
@@ -7391,9 +7367,6 @@ Builtin_call_expression::lower_make()
return Expression::make_error(this->location());
}
- if (cap_arg->type()->integer_type() != NULL
- && cap_arg->type()->integer_type()->bits() > uintptr_bits)
- have_big_args = true;
++parg;
}
@@ -7404,34 +7377,236 @@ Builtin_call_expression::lower_make()
}
Location type_loc = first_arg->location();
- Expression* type_arg = Expression::make_type_descriptor(type, type_loc);
Expression* call;
if (is_slice)
{
+ Type* et = type->array_type()->element_type();
+ Expression* type_arg = Expression::make_type_descriptor(et, type_loc);
if (cap_arg == NULL)
- call = Runtime::make_call((have_big_args
- ? Runtime::MAKESLICE1BIG
- : Runtime::MAKESLICE1),
- loc, 2, type_arg, len_arg);
- else
- call = Runtime::make_call((have_big_args
- ? Runtime::MAKESLICE2BIG
- : Runtime::MAKESLICE2),
- loc, 3, type_arg, len_arg, cap_arg);
+ {
+ Temporary_statement* temp = Statement::make_temporary(NULL,
+ len_arg,
+ loc);
+ inserter->insert(temp);
+ len_arg = Expression::make_temporary_reference(temp, loc);
+ cap_arg = Expression::make_temporary_reference(temp, loc);
+ }
+ call = Runtime::make_call(Runtime::MAKESLICE, loc, 3, type_arg,
+ len_arg, cap_arg);
}
else if (is_map)
- call = Runtime::make_call(Runtime::MAKEMAP, loc, 4, type_arg, len_arg,
- Expression::make_nil(loc),
- Expression::make_nil(loc));
+ {
+ Expression* type_arg = Expression::make_type_descriptor(type, type_loc);
+ call = Runtime::make_call(Runtime::MAKEMAP, loc, 4, type_arg, len_arg,
+ Expression::make_nil(loc),
+ Expression::make_nil(loc));
+ }
else if (is_chan)
- call = Runtime::make_call(Runtime::MAKECHAN, loc, 2, type_arg, len_arg);
+ {
+ Expression* type_arg = Expression::make_type_descriptor(type, type_loc);
+ call = Runtime::make_call(Runtime::MAKECHAN, loc, 2, type_arg, len_arg);
+ }
else
go_unreachable();
return Expression::make_unsafe_cast(type, call, loc);
}
+// Flatten a call to the predeclared append function. We do this in
+// the flatten phase, not the lowering phase, so that we run after
+// type checking and after order_evaluations.
+
+Expression*
+Builtin_call_expression::flatten_append(Gogo* gogo, Named_object* function,
+ Statement_inserter* inserter)
+{
+ if (this->is_error_expression())
+ return this;
+
+ Location loc = this->location();
+
+ const Expression_list* args = this->args();
+ go_assert(args != NULL && !args->empty());
+
+ Type* slice_type = args->front()->type();
+ go_assert(slice_type->is_slice_type());
+ Type* element_type = slice_type->array_type()->element_type();
+
+ if (args->size() == 1)
+ {
+ // append(s) evaluates to s.
+ return args->front();
+ }
+
+ Type* int_type = Type::lookup_integer_type("int");
+ Type* uint_type = Type::lookup_integer_type("uint");
+
+ // Implementing
+ // append(s1, s2...)
+ // or
+ // append(s1, a1, a2, a3, ...)
+
+ // s1tmp := s1
+ Temporary_statement* s1tmp = Statement::make_temporary(NULL, args->front(),
+ loc);
+ inserter->insert(s1tmp);
+
+ // l1tmp := len(s1tmp)
+ Named_object* lenfn = gogo->lookup_global("len");
+ Expression* lenref = Expression::make_func_reference(lenfn, NULL, loc);
+ Expression_list* call_args = new Expression_list();
+ call_args->push_back(Expression::make_temporary_reference(s1tmp, loc));
+ Expression* len = Expression::make_call(lenref, call_args, false, loc);
+ gogo->lower_expression(function, inserter, &len);
+ gogo->flatten_expression(function, inserter, &len);
+ Temporary_statement* l1tmp = Statement::make_temporary(int_type, len, loc);
+ inserter->insert(l1tmp);
+
+ Temporary_statement* s2tmp = NULL;
+ Temporary_statement* l2tmp = NULL;
+ Expression_list* add = NULL;
+ Expression* len2;
+ if (this->is_varargs())
+ {
+ go_assert(args->size() == 2);
+
+ // s2tmp := s2
+ s2tmp = Statement::make_temporary(NULL, args->back(), loc);
+ inserter->insert(s2tmp);
+
+ // l2tmp := len(s2tmp)
+ lenref = Expression::make_func_reference(lenfn, NULL, loc);
+ call_args = new Expression_list();
+ call_args->push_back(Expression::make_temporary_reference(s2tmp, loc));
+ len = Expression::make_call(lenref, call_args, false, loc);
+ gogo->lower_expression(function, inserter, &len);
+ gogo->flatten_expression(function, inserter, &len);
+ l2tmp = Statement::make_temporary(int_type, len, loc);
+ inserter->insert(l2tmp);
+
+ // len2 = l2tmp
+ len2 = Expression::make_temporary_reference(l2tmp, loc);
+ }
+ else
+ {
+ // We have to ensure that all the arguments are in variables
+ // now, because otherwise if one of them is an index expression
+ // into the current slice we could overwrite it before we fetch
+ // it.
+ add = new Expression_list();
+ Expression_list::const_iterator pa = args->begin();
+ for (++pa; pa != args->end(); ++pa)
+ {
+ if ((*pa)->is_variable())
+ add->push_back(*pa);
+ else
+ {
+ Temporary_statement* tmp = Statement::make_temporary(NULL, *pa,
+ loc);
+ inserter->insert(tmp);
+ add->push_back(Expression::make_temporary_reference(tmp, loc));
+ }
+ }
+
+ // len2 = len(add)
+ len2 = Expression::make_integer_ul(add->size(), int_type, loc);
+ }
+
+ // ntmp := l1tmp + len2
+ Expression* ref = Expression::make_temporary_reference(l1tmp, loc);
+ Expression* sum = Expression::make_binary(OPERATOR_PLUS, ref, len2, loc);
+ gogo->lower_expression(function, inserter, &sum);
+ gogo->flatten_expression(function, inserter, &sum);
+ Temporary_statement* ntmp = Statement::make_temporary(int_type, sum, loc);
+ inserter->insert(ntmp);
+
+ // s1tmp = uint(ntmp) > uint(cap(s1tmp)) ?
+ // growslice(type, s1tmp, ntmp) :
+ // s1tmp[:ntmp]
+ // Using uint here means that if the computation of ntmp overflowed,
+ // we will call growslice which will panic.
+
+ Expression* left = Expression::make_temporary_reference(ntmp, loc);
+ left = Expression::make_cast(uint_type, left, loc);
+
+ Named_object* capfn = gogo->lookup_global("cap");
+ Expression* capref = Expression::make_func_reference(capfn, NULL, loc);
+ call_args = new Expression_list();
+ call_args->push_back(Expression::make_temporary_reference(s1tmp, loc));
+ Expression* right = Expression::make_call(capref, call_args, false, loc);
+ right = Expression::make_cast(uint_type, right, loc);
+
+ Expression* cond = Expression::make_binary(OPERATOR_GT, left, right, loc);
+
+ Expression* a1 = Expression::make_type_descriptor(element_type, loc);
+ Expression* a2 = Expression::make_temporary_reference(s1tmp, loc);
+ Expression* a3 = Expression::make_temporary_reference(ntmp, loc);
+ Expression* call = Runtime::make_call(Runtime::GROWSLICE, loc, 3,
+ a1, a2, a3);
+ call = Expression::make_unsafe_cast(slice_type, call, loc);
+
+ ref = Expression::make_temporary_reference(s1tmp, loc);
+ Expression* zero = Expression::make_integer_ul(0, int_type, loc);
+ Expression* ref2 = Expression::make_temporary_reference(ntmp, loc);
+ // FIXME: Mark this index as not requiring bounds checks.
+ ref = Expression::make_index(ref, zero, ref2, NULL, loc);
+
+ Expression* rhs = Expression::make_conditional(cond, call, ref, loc);
+
+ gogo->lower_expression(function, inserter, &rhs);
+ gogo->flatten_expression(function, inserter, &rhs);
+
+ Expression* lhs = Expression::make_temporary_reference(s1tmp, loc);
+ Statement* assign = Statement::make_assignment(lhs, rhs, loc);
+ inserter->insert(assign);
+
+ if (this->is_varargs())
+ {
+ // copy(s1tmp[l1tmp:], s2tmp)
+ a1 = Expression::make_temporary_reference(s1tmp, loc);
+ ref = Expression::make_temporary_reference(l1tmp, loc);
+ Expression* nil = Expression::make_nil(loc);
+ // FIXME: Mark this index as not requiring bounds checks.
+ a1 = Expression::make_index(a1, ref, nil, NULL, loc);
+
+ a2 = Expression::make_temporary_reference(s2tmp, loc);
+
+ Named_object* copyfn = gogo->lookup_global("copy");
+ Expression* copyref = Expression::make_func_reference(copyfn, NULL, loc);
+ call_args = new Expression_list();
+ call_args->push_back(a1);
+ call_args->push_back(a2);
+ call = Expression::make_call(copyref, call_args, false, loc);
+ gogo->lower_expression(function, inserter, &call);
+ gogo->flatten_expression(function, inserter, &call);
+ inserter->insert(Statement::make_statement(call, false));
+ }
+ else
+ {
+ // For each argument:
+ // s1tmp[l1tmp+i] = a
+ unsigned long i = 0;
+ for (Expression_list::const_iterator pa = add->begin();
+ pa != add->end();
+ ++pa, ++i)
+ {
+ ref = Expression::make_temporary_reference(s1tmp, loc);
+ ref2 = Expression::make_temporary_reference(l1tmp, loc);
+ Expression* off = Expression::make_integer_ul(i, int_type, loc);
+ ref2 = Expression::make_binary(OPERATOR_PLUS, ref2, off, loc);
+ // FIXME: Mark this index as not requiring bounds checks.
+ lhs = Expression::make_index(ref, ref2, NULL, NULL, loc);
+ gogo->lower_expression(function, inserter, &lhs);
+ gogo->flatten_expression(function, inserter, &lhs);
+ assign = Statement::make_assignment(lhs, *pa, loc);
+ inserter->insert(assign);
+ }
+ }
+
+ return Expression::make_temporary_reference(s1tmp, loc);
+}
+
// Return whether an expression has an integer value. Report an error
// if not. This is used when handling calls to the predeclared make
// function.
@@ -8011,6 +8186,7 @@ Builtin_call_expression::do_determine_type(const Type_context* context)
bool is_print;
Type* arg_type = NULL;
+ Type* trailing_arg_types = NULL;
switch (this->code_)
{
case BUILTIN_PRINT:
@@ -8047,6 +8223,16 @@ Builtin_call_expression::do_determine_type(const Type_context* context)
}
break;
+ case BUILTIN_APPEND:
+ if (!this->is_varargs()
+ && args != NULL
+ && !args->empty()
+ && args->front()->type()->is_slice_type())
+ trailing_arg_types =
+ args->front()->type()->array_type()->element_type();
+ is_print = false;
+ break;
+
default:
is_print = false;
break;
@@ -8103,6 +8289,12 @@ Builtin_call_expression::do_determine_type(const Type_context* context)
}
(*pa)->determine_type(&subcontext);
+
+ if (trailing_arg_types != NULL)
+ {
+ arg_type = trailing_arg_types;
+ trailing_arg_types = NULL;
+ }
}
}
}
@@ -8309,54 +8501,102 @@ Builtin_call_expression::do_check_types(Gogo*)
case BUILTIN_APPEND:
{
const Expression_list* args = this->args();
- if (args == NULL || args->size() < 2)
+ if (args == NULL || args->empty())
{
this->report_error(_("not enough arguments"));
break;
}
- if (args->size() > 2)
- {
- this->report_error(_("too many arguments"));
- break;
- }
- if (args->front()->type()->is_error()
- || args->back()->type()->is_error())
+
+ Type* slice_type = args->front()->type();
+ if (!slice_type->is_slice_type())
{
+ if (slice_type->is_error_type())
+ break;
+ if (slice_type->is_nil_type())
+ go_error_at(args->front()->location(), "use of untyped nil");
+ else
+ go_error_at(args->front()->location(),
+ "argument 1 must be a slice");
this->set_is_error();
break;
}
- Array_type* at = args->front()->type()->array_type();
- Type* e = at->element_type();
-
- // The language permits appending a string to a []byte, as a
- // special case.
- if (args->back()->type()->is_string_type())
+ Type* element_type = slice_type->array_type()->element_type();
+ if (this->is_varargs())
{
- if (e->integer_type() != NULL && e->integer_type()->is_byte())
- break;
- }
+ if (!args->back()->type()->is_slice_type()
+ && !args->back()->type()->is_string_type())
+ {
+ go_error_at(args->back()->location(),
+ "invalid use of %<...%> with non-slice/non-string");
+ this->set_is_error();
+ break;
+ }
- // The language says that the second argument must be
- // assignable to a slice of the element type of the first
- // argument. We already know the first argument is a slice
- // type.
- Type* arg2_type = Type::make_array_type(e, NULL);
- std::string reason;
- if (!Type::are_assignable(arg2_type, args->back()->type(), &reason))
- {
- if (reason.empty())
- this->report_error(_("argument 2 has invalid type"));
+ if (args->size() < 2)
+ {
+ this->report_error(_("not enough arguments"));
+ break;
+ }
+ if (args->size() > 2)
+ {
+ this->report_error(_("too many arguments"));
+ break;
+ }
+
+ if (args->back()->type()->is_string_type()
+ && element_type->integer_type() != NULL
+ && element_type->integer_type()->is_byte())
+ {
+ // Permit append(s1, s2...) when s1 is a slice of
+ // bytes and s2 is a string type.
+ }
else
{
- go_error_at(this->location(),
- "argument 2 has invalid type (%s)",
- reason.c_str());
- this->set_is_error();
+ // We have to test for assignment compatibility to a
+ // slice of the element type, which is not necessarily
+ // the same as the type of the first argument: the
+ // first argument might have a named type.
+ Type* check_type = Type::make_array_type(element_type, NULL);
+ std::string reason;
+ if (!Type::are_assignable(check_type, args->back()->type(),
+ &reason))
+ {
+ if (reason.empty())
+ go_error_at(args->back()->location(),
+ "argument 2 has invalid type");
+ else
+ go_error_at(args->back()->location(),
+ "argument 2 has invalid type (%s)",
+ reason.c_str());
+ this->set_is_error();
+ break;
+ }
+ }
+ }
+ else
+ {
+ Expression_list::const_iterator pa = args->begin();
+ int i = 2;
+ for (++pa; pa != args->end(); ++pa, ++i)
+ {
+ std::string reason;
+ if (!Type::are_assignable(element_type, (*pa)->type(),
+ &reason))
+ {
+ if (reason.empty())
+ go_error_at((*pa)->location(),
+ "argument %d has incompatible type", i);
+ else
+ go_error_at((*pa)->location(),
+ "argument %d has incompatible type (%s)",
+ i, reason.c_str());
+ this->set_is_error();
+ }
}
}
- break;
}
+ break;
case BUILTIN_REAL:
case BUILTIN_IMAG:
@@ -8719,97 +8959,39 @@ Builtin_call_expression::do_get_backend(Translate_context* context)
Type* arg1_type = arg1->type();
Array_type* at = arg1_type->array_type();
go_assert(arg1->is_variable());
- Expression* arg1_val = at->get_value_pointer(gogo, arg1);
- Expression* arg1_len = at->get_length(gogo, arg1);
+
+ Expression* call;
Type* arg2_type = arg2->type();
go_assert(arg2->is_variable());
- Expression* arg2_val;
- Expression* arg2_len;
- if (arg2_type->is_slice_type())
- {
- at = arg2_type->array_type();
- arg2_val = at->get_value_pointer(gogo, arg2);
- arg2_len = at->get_length(gogo, arg2);
- }
+ if (arg2_type->is_string_type())
+ call = Runtime::make_call(Runtime::SLICESTRINGCOPY, location,
+ 2, arg1, arg2);
else
{
- go_assert(arg2->is_variable());
- arg2_val = Expression::make_string_info(arg2, STRING_INFO_DATA,
- location);
- arg2_len = Expression::make_string_info(arg2, STRING_INFO_LENGTH,
- location);
+ Type* et = at->element_type();
+ if (et->has_pointer())
+ {
+ Expression* td = Expression::make_type_descriptor(et,
+ location);
+ call = Runtime::make_call(Runtime::TYPEDSLICECOPY, location,
+ 3, td, arg1, arg2);
+ }
+ else
+ {
+ Expression* sz = Expression::make_type_info(et,
+ TYPE_INFO_SIZE);
+ call = Runtime::make_call(Runtime::SLICECOPY, location, 3,
+ arg1, arg2, sz);
+ }
}
- Expression* cond =
- Expression::make_binary(OPERATOR_LT, arg1_len, arg2_len, location);
- Expression* length =
- Expression::make_conditional(cond, arg1_len, arg2_len, location);
-
- Type* element_type = at->element_type();
- int64_t element_size;
- bool ok = element_type->backend_type_size(gogo, &element_size);
- if (!ok)
- {
- go_assert(saw_errors());
- return gogo->backend()->error_expression();
- }
- Expression* size_expr = Expression::make_integer_int64(element_size,
- length->type(),
- location);
- Expression* bytecount =
- Expression::make_binary(OPERATOR_MULT, size_expr, length, location);
- Expression* copy = Runtime::make_call(Runtime::COPY, location, 3,
- arg1_val, arg2_val, bytecount);
-
- Expression* compound = Expression::make_compound(copy, length, location);
- return compound->get_backend(context);
+ return call->get_backend(context);
}
case BUILTIN_APPEND:
- {
- const Expression_list* args = this->args();
- go_assert(args != NULL && args->size() == 2);
- Expression* arg1 = args->front();
- Expression* arg2 = args->back();
-
- Array_type* at = arg1->type()->array_type();
- Type* element_type = at->element_type()->forwarded();
-
- go_assert(arg2->is_variable());
- Expression* arg2_val;
- Expression* arg2_len;
- int64_t size;
- if (arg2->type()->is_string_type()
- && element_type->integer_type() != NULL
- && element_type->integer_type()->is_byte())
- {
- arg2_val = Expression::make_string_info(arg2, STRING_INFO_DATA,
- location);
- arg2_len = Expression::make_string_info(arg2, STRING_INFO_LENGTH,
- location);
- size = 1;
- }
- else
- {
- arg2_val = at->get_value_pointer(gogo, arg2);
- arg2_len = at->get_length(gogo, arg2);
- bool ok = element_type->backend_type_size(gogo, &size);
- if (!ok)
- {
- go_assert(saw_errors());
- return gogo->backend()->error_expression();
- }
- }
- Expression* element_size =
- Expression::make_integer_int64(size, NULL, location);
-
- Expression* append = Runtime::make_call(Runtime::APPEND, location, 4,
- arg1, arg2_val, arg2_len,
- element_size);
- append = Expression::make_unsafe_cast(arg1->type(), append, location);
- return append->get_backend(context);
- }
+ // Handled in Builtin_call_expression::flatten_append.
+ go_unreachable();
case BUILTIN_REAL:
case BUILTIN_IMAG:
@@ -12020,12 +12202,10 @@ Expression::make_allocation(Type* type, Location location)
return new Allocation_expression(type, location);
}
-// Class Struct_construction_expression.
-
-// Traversal.
+// Class Ordered_value_list.
int
-Struct_construction_expression::do_traverse(Traverse* traverse)
+Ordered_value_list::traverse_vals(Traverse* traverse)
{
if (this->vals_ != NULL)
{
@@ -12036,8 +12216,8 @@ Struct_construction_expression::do_traverse(Traverse* traverse)
}
else
{
- for (std::vector<int>::const_iterator p =
- this->traverse_order_->begin();
+ for (std::vector<unsigned long>::const_iterator p =
+ this->traverse_order_->begin();
p != this->traverse_order_->end();
++p)
{
@@ -12047,6 +12227,18 @@ Struct_construction_expression::do_traverse(Traverse* traverse)
}
}
}
+ return TRAVERSE_CONTINUE;
+}
+
+// Class Struct_construction_expression.
+
+// Traversal.
+
+int
+Struct_construction_expression::do_traverse(Traverse* traverse)
+{
+ if (this->traverse_vals(traverse) == TRAVERSE_EXIT)
+ return TRAVERSE_EXIT;
if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
return TRAVERSE_CONTINUE;
@@ -12057,10 +12249,10 @@ Struct_construction_expression::do_traverse(Traverse* traverse)
bool
Struct_construction_expression::is_constant_struct() const
{
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return true;
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::const_iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv)
{
if (*pv != NULL
@@ -12088,10 +12280,10 @@ Struct_construction_expression::is_constant_struct() const
bool
Struct_construction_expression::do_is_immutable() const
{
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return true;
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::const_iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv)
{
if (*pv != NULL && !(*pv)->is_immutable())
@@ -12105,15 +12297,15 @@ Struct_construction_expression::do_is_immutable() const
void
Struct_construction_expression::do_determine_type(const Type_context*)
{
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return;
const Struct_field_list* fields = this->type_->struct_type()->fields();
- Expression_list::const_iterator pv = this->vals_->begin();
+ Expression_list::const_iterator pv = this->vals()->begin();
for (Struct_field_list::const_iterator pf = fields->begin();
pf != fields->end();
++pf, ++pv)
{
- if (pv == this->vals_->end())
+ if (pv == this->vals()->end())
return;
if (*pv != NULL)
{
@@ -12123,7 +12315,7 @@ Struct_construction_expression::do_determine_type(const Type_context*)
}
// Extra values are an error we will report elsewhere; we still want
// to determine the type to avoid knockon errors.
- for (; pv != this->vals_->end(); ++pv)
+ for (; pv != this->vals()->end(); ++pv)
(*pv)->determine_type_no_context();
}
@@ -12132,24 +12324,24 @@ Struct_construction_expression::do_determine_type(const Type_context*)
void
Struct_construction_expression::do_check_types(Gogo*)
{
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return;
Struct_type* st = this->type_->struct_type();
- if (this->vals_->size() > st->field_count())
+ if (this->vals()->size() > st->field_count())
{
this->report_error(_("too many expressions for struct"));
return;
}
const Struct_field_list* fields = st->fields();
- Expression_list::const_iterator pv = this->vals_->begin();
+ Expression_list::const_iterator pv = this->vals()->begin();
int i = 0;
for (Struct_field_list::const_iterator pf = fields->begin();
pf != fields->end();
++pf, ++pv, ++i)
{
- if (pv == this->vals_->end())
+ if (pv == this->vals()->end())
{
this->report_error(_("too few expressions for struct"));
break;
@@ -12173,7 +12365,7 @@ Struct_construction_expression::do_check_types(Gogo*)
this->set_is_error();
}
}
- go_assert(pv == this->vals_->end());
+ go_assert(pv == this->vals()->end());
}
// Flatten a struct construction expression. Store the values into
@@ -12183,7 +12375,7 @@ Expression*
Struct_construction_expression::do_flatten(Gogo*, Named_object*,
Statement_inserter* inserter)
{
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return this;
// If this is a constant struct, we don't need temporaries.
@@ -12191,8 +12383,8 @@ Struct_construction_expression::do_flatten(Gogo*, Named_object*,
return this;
Location loc = this->location();
- for (Expression_list::iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv)
{
if (*pv != NULL)
@@ -12222,18 +12414,18 @@ Struct_construction_expression::do_get_backend(Translate_context* context)
Gogo* gogo = context->gogo();
Btype* btype = this->type_->get_backend(gogo);
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return gogo->backend()->zero_expression(btype);
const Struct_field_list* fields = this->type_->struct_type()->fields();
- Expression_list::const_iterator pv = this->vals_->begin();
+ Expression_list::const_iterator pv = this->vals()->begin();
std::vector<Bexpression*> init;
for (Struct_field_list::const_iterator pf = fields->begin();
pf != fields->end();
++pf)
{
Btype* fbtype = pf->type()->get_backend(gogo);
- if (pv == this->vals_->end())
+ if (pv == this->vals()->end())
init.push_back(gogo->backend()->zero_expression(fbtype));
else if (*pv == NULL)
{
@@ -12259,8 +12451,8 @@ Struct_construction_expression::do_export(Export* exp) const
{
exp->write_c_string("convert(");
exp->write_type(this->type_);
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::const_iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv)
{
exp->write_c_string(", ");
@@ -12278,7 +12470,7 @@ Struct_construction_expression::do_dump_expression(
{
ast_dump_context->dump_type(this->type_);
ast_dump_context->ostream() << "{";
- ast_dump_context->dump_expression_list(this->vals_);
+ ast_dump_context->dump_expression_list(this->vals());
ast_dump_context->ostream() << "}";
}
@@ -12299,8 +12491,7 @@ Expression::make_struct_composite_literal(Type* type, Expression_list* vals,
int
Array_construction_expression::do_traverse(Traverse* traverse)
{
- if (this->vals_ != NULL
- && this->vals_->traverse(traverse) == TRAVERSE_EXIT)
+ if (this->traverse_vals(traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
if (Type::traverse(this->type_, traverse) == TRAVERSE_EXIT)
return TRAVERSE_EXIT;
@@ -12312,15 +12503,15 @@ Array_construction_expression::do_traverse(Traverse* traverse)
bool
Array_construction_expression::is_constant_array() const
{
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return true;
// There are no constant constructors for interfaces.
if (this->type_->array_type()->element_type()->interface_type() != NULL)
return false;
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::const_iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv)
{
if (*pv != NULL
@@ -12337,10 +12528,10 @@ Array_construction_expression::is_constant_array() const
bool
Array_construction_expression::do_is_immutable() const
{
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return true;
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::const_iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv)
{
if (*pv != NULL && !(*pv)->is_immutable())
@@ -12354,11 +12545,11 @@ Array_construction_expression::do_is_immutable() const
void
Array_construction_expression::do_determine_type(const Type_context*)
{
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return;
Type_context subcontext(this->type_->array_type()->element_type(), false);
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::const_iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv)
{
if (*pv != NULL)
@@ -12371,14 +12562,14 @@ Array_construction_expression::do_determine_type(const Type_context*)
void
Array_construction_expression::do_check_types(Gogo*)
{
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return;
Array_type* at = this->type_->array_type();
int i = 0;
Type* element_type = at->element_type();
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::const_iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv, ++i)
{
if (*pv != NULL
@@ -12399,7 +12590,7 @@ Expression*
Array_construction_expression::do_flatten(Gogo*, Named_object*,
Statement_inserter* inserter)
{
- if (this->vals_ == NULL)
+ if (this->vals() == NULL)
return this;
// If this is a constant array, we don't need temporaries.
@@ -12407,8 +12598,8 @@ Array_construction_expression::do_flatten(Gogo*, Named_object*,
return this;
Location loc = this->location();
- for (Expression_list::iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv)
{
if (*pv != NULL)
@@ -12441,14 +12632,14 @@ Array_construction_expression::get_constructor(Translate_context* context,
std::vector<unsigned long> indexes;
std::vector<Bexpression*> vals;
Gogo* gogo = context->gogo();
- if (this->vals_ != NULL)
+ if (this->vals() != NULL)
{
size_t i = 0;
std::vector<unsigned long>::const_iterator pi;
if (this->indexes_ != NULL)
pi = this->indexes_->begin();
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::const_iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv, ++i)
{
if (this->indexes_ != NULL)
@@ -12488,13 +12679,13 @@ Array_construction_expression::do_export(Export* exp) const
{
exp->write_c_string("convert(");
exp->write_type(this->type_);
- if (this->vals_ != NULL)
+ if (this->vals() != NULL)
{
std::vector<unsigned long>::const_iterator pi;
if (this->indexes_ != NULL)
pi = this->indexes_->begin();
- for (Expression_list::const_iterator pv = this->vals_->begin();
- pv != this->vals_->end();
+ for (Expression_list::const_iterator pv = this->vals()->begin();
+ pv != this->vals()->end();
++pv)
{
exp->write_c_string(", ");
@@ -12535,10 +12726,10 @@ Array_construction_expression::do_dump_expression(
this->dump_slice_storage_expression(ast_dump_context);
ast_dump_context->ostream() << "{" ;
if (this->indexes_ == NULL)
- ast_dump_context->dump_expression_list(this->vals_);
+ ast_dump_context->dump_expression_list(this->vals());
else
{
- Expression_list::const_iterator pv = this->vals_->begin();
+ Expression_list::const_iterator pv = this->vals()->begin();
for (std::vector<unsigned long>::const_iterator pi =
this->indexes_->begin();
pi != this->indexes_->end();
@@ -13167,7 +13358,7 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
size_t field_count = st->field_count();
std::vector<Expression*> vals(field_count);
- std::vector<int>* traverse_order = new(std::vector<int>);
+ std::vector<unsigned long>* traverse_order = new(std::vector<unsigned long>);
Expression_list::const_iterator p = this->vals_->begin();
Expression* external_expr = NULL;
const Named_object* external_no = NULL;
@@ -13299,7 +13490,7 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
type->named_type()->message_name().c_str());
vals[index] = val;
- traverse_order->push_back(index);
+ traverse_order->push_back(static_cast<unsigned long>(index));
}
if (!this->all_are_names_)
@@ -13330,15 +13521,16 @@ Composite_literal_expression::lower_struct(Gogo* gogo, Type* type)
return ret;
}
-// Used to sort an index/value array.
+// Index/value/traversal-order triple.
-class Index_value_compare
-{
- public:
- bool
- operator()(const std::pair<unsigned long, Expression*>& a,
- const std::pair<unsigned long, Expression*>& b)
- { return a.first < b.first; }
+struct IVT_triple {
+ unsigned long index;
+ unsigned long traversal_order;
+ Expression* expr;
+ IVT_triple(unsigned long i, unsigned long to, Expression *e)
+ : index(i), traversal_order(to), expr(e) { }
+ bool operator<(const IVT_triple& other) const
+ { return this->index < other.index; }
};
// Lower an array composite literal.
@@ -13442,35 +13634,45 @@ Composite_literal_expression::lower_array(Type* type)
indexes = NULL;
}
+ std::vector<unsigned long>* traverse_order = NULL;
if (indexes_out_of_order)
{
- typedef std::vector<std::pair<unsigned long, Expression*> > V;
+ typedef std::vector<IVT_triple> V;
V v;
v.reserve(indexes->size());
std::vector<unsigned long>::const_iterator pi = indexes->begin();
+ unsigned long torder = 0;
for (Expression_list::const_iterator pe = vals->begin();
pe != vals->end();
- ++pe, ++pi)
- v.push_back(std::make_pair(*pi, *pe));
+ ++pe, ++pi, ++torder)
+ v.push_back(IVT_triple(*pi, torder, *pe));
- std::sort(v.begin(), v.end(), Index_value_compare());
+ std::sort(v.begin(), v.end());
delete indexes;
delete vals;
+
indexes = new std::vector<unsigned long>();
indexes->reserve(v.size());
vals = new Expression_list();
vals->reserve(v.size());
+ traverse_order = new std::vector<unsigned long>();
+ traverse_order->reserve(v.size());
for (V::const_iterator p = v.begin(); p != v.end(); ++p)
{
- indexes->push_back(p->first);
- vals->push_back(p->second);
+ indexes->push_back(p->index);
+ vals->push_back(p->expr);
+ traverse_order->push_back(p->traversal_order);
}
}
- return this->make_array(type, indexes, vals);
+ Expression* ret = this->make_array(type, indexes, vals);
+ Array_construction_expression* ace = ret->array_literal();
+ if (ace != NULL && traverse_order != NULL)
+ ace->set_traverse_order(traverse_order);
+ return ret;
}
// Actually build the array composite literal. This handles
diff --git a/gcc/go/gofrontend/expressions.h b/gcc/go/gofrontend/expressions.h
index 0d00f458c38..a02fd19feb3 100644
--- a/gcc/go/gofrontend/expressions.h
+++ b/gcc/go/gofrontend/expressions.h
@@ -3232,31 +3232,64 @@ class Composite_literal_expression : public Parser_expression
std::vector<bool> key_path_;
};
-// Construct a struct.
+// Helper/mixin class for struct and array construction expressions;
+// encapsulates a list of values plus an optional traversal order
+// recording the order in which the values should be visited.
-class Struct_construction_expression : public Expression
+class Ordered_value_list
{
public:
- Struct_construction_expression(Type* type, Expression_list* vals,
- Location location)
- : Expression(EXPRESSION_STRUCT_CONSTRUCTION, location),
- type_(type), vals_(vals), traverse_order_(NULL)
+ Ordered_value_list(Expression_list* vals)
+ : vals_(vals), traverse_order_(NULL)
{ }
+ Expression_list*
+ vals() const
+ { return this->vals_; }
+
+ int
+ traverse_vals(Traverse* traverse);
+
+ // Get the traversal order (may be NULL)
+ std::vector<unsigned long>*
+ traverse_order()
+ { return traverse_order_; }
+
// Set the traversal order, used to ensure that we implement the
// order of evaluation rules. Takes ownership of the argument.
void
- set_traverse_order(std::vector<int>* traverse_order)
+ set_traverse_order(std::vector<unsigned long>* traverse_order)
{ this->traverse_order_ = traverse_order; }
- // Return whether this is a constant initializer.
+ private:
+ // The list of values, in order of the fields in the struct or in
+ // order of indices in an array. A NULL value of vals_ means that
+ // all fields/slots should be zero-initialized; a single NULL entry
+ // in the list means that the corresponding field or array slot
+ // should be zero-initialized.
+ Expression_list* vals_;
+ // If not NULL, the order in which to traverse vals_. This is used
+ // so that we implement the order of evaluation rules correctly.
+ std::vector<unsigned long>* traverse_order_;
+};
+
+// Construct a struct.
+
+class Struct_construction_expression : public Expression,
+ public Ordered_value_list
+{
+ public:
+ Struct_construction_expression(Type* type, Expression_list* vals,
+ Location location)
+ : Expression(EXPRESSION_STRUCT_CONSTRUCTION, location),
+ Ordered_value_list(vals),
+ type_(type)
+ { }
+
+ // Return whether this is a constant initializer.
bool
is_constant_struct() const;
- Expression_list*
- vals() const
- { return this->vals_; }
-
protected:
int
do_traverse(Traverse* traverse);
@@ -3279,12 +3312,12 @@ class Struct_construction_expression : public Expression
{
Struct_construction_expression* ret =
new Struct_construction_expression(this->type_,
- (this->vals_ == NULL
+ (this->vals() == NULL
? NULL
- : this->vals_->copy()),
+ : this->vals()->copy()),
this->location());
- if (this->traverse_order_ != NULL)
- ret->set_traverse_order(this->traverse_order_);
+ if (this->traverse_order() != NULL)
+ ret->set_traverse_order(this->traverse_order());
return ret;
}
@@ -3303,19 +3336,14 @@ class Struct_construction_expression : public Expression
private:
// The type of the struct to construct.
Type* type_;
- // The list of values, in order of the fields in the struct. A NULL
- // entry means that the field should be zero-initialized.
- Expression_list* vals_;
- // If not NULL, the order in which to traverse vals_. This is used
- // so that we implement the order of evaluation rules correctly.
- std::vector<int>* traverse_order_;
};
// Construct an array. This class is not used directly; instead we
// use the child classes, Fixed_array_construction_expression and
// Slice_construction_expression.
-class Array_construction_expression : public Expression
+class Array_construction_expression : public Expression,
+ public Ordered_value_list
{
protected:
Array_construction_expression(Expression_classification classification,
@@ -3323,7 +3351,8 @@ class Array_construction_expression : public Expression
const std::vector<unsigned long>* indexes,
Expression_list* vals, Location location)
: Expression(classification, location),
- type_(type), indexes_(indexes), vals_(vals)
+ Ordered_value_list(vals),
+ type_(type), indexes_(indexes)
{ go_assert(indexes == NULL || indexes->size() == vals->size()); }
public:
@@ -3334,12 +3363,7 @@ class Array_construction_expression : public Expression
// Return the number of elements.
size_t
element_count() const
- { return this->vals_ == NULL ? 0 : this->vals_->size(); }
-
- // The list of values.
- Expression_list*
- vals() const
- { return this->vals_; }
+ { return this->vals() == NULL ? 0 : this->vals()->size(); }
protected:
virtual int
@@ -3385,8 +3409,6 @@ protected:
// The list of indexes into the array, one for each value. This may
// be NULL, in which case the indexes start at zero and increment.
const std::vector<unsigned long>* indexes_;
- // The list of values. This may be NULL if there are no values.
- Expression_list* vals_;
};
// Construct a fixed array.
diff --git a/gcc/go/gofrontend/runtime.cc b/gcc/go/gofrontend/runtime.cc
index 4072920b9d2..77c48ecbaaf 100644
--- a/gcc/go/gofrontend/runtime.cc
+++ b/gcc/go/gofrontend/runtime.cc
@@ -425,9 +425,9 @@ Runtime::name_to_code(const std::string& name)
else if (name == "close")
code = Runtime::CLOSE;
else if (name == "copy")
- code = Runtime::COPY;
+ code = Runtime::SLICECOPY;
else if (name == "append")
- code = Runtime::APPEND;
+ code = Runtime::GROWSLICE;
else if (name == "delete")
code = Runtime::MAPDELETE;
else
diff --git a/gcc/go/gofrontend/runtime.def b/gcc/go/gofrontend/runtime.def
index 3051624b66c..5d3ce67725d 100644
--- a/gcc/go/gofrontend/runtime.def
+++ b/gcc/go/gofrontend/runtime.def
@@ -87,12 +87,7 @@ DEF_GO_RUNTIME(COMPLEX128_DIV, "__go_complex128_div",
P2(COMPLEX128, COMPLEX128), R1(COMPLEX128))
// Make a slice.
-DEF_GO_RUNTIME(MAKESLICE1, "__go_make_slice1", P2(TYPE, UINTPTR), R1(SLICE))
-DEF_GO_RUNTIME(MAKESLICE2, "__go_make_slice2", P3(TYPE, UINTPTR, UINTPTR),
- R1(SLICE))
-DEF_GO_RUNTIME(MAKESLICE1BIG, "__go_make_slice1_big", P2(TYPE, UINT64),
- R1(SLICE))
-DEF_GO_RUNTIME(MAKESLICE2BIG, "__go_make_slice2_big", P3(TYPE, UINT64, UINT64),
+DEF_GO_RUNTIME(MAKESLICE, "runtime.makeslice", P3(TYPE, INT64, INT64),
R1(SLICE))
@@ -211,11 +206,20 @@ DEF_GO_RUNTIME(CLOSE, "runtime.closechan", P1(CHAN), R0())
// Copy.
-DEF_GO_RUNTIME(COPY, "__go_copy", P3(POINTER, POINTER, UINTPTR), R0())
+DEF_GO_RUNTIME(SLICECOPY, "runtime.slicecopy", P3(SLICE, SLICE, UINTPTR),
+ R1(INT))
-// Append.
-DEF_GO_RUNTIME(APPEND, "__go_append", P4(SLICE, POINTER, UINTPTR, UINTPTR),
- R1(SLICE))
+// Copy from string.
+DEF_GO_RUNTIME(SLICESTRINGCOPY, "runtime.slicestringcopy", P2(SLICE, STRING),
+ R1(INT))
+
+// Copy of value containing pointers.
+DEF_GO_RUNTIME(TYPEDSLICECOPY, "runtime.typedslicecopy",
+ P3(TYPE, SLICE, SLICE), R1(INT))
+
+
+// Grow a slice for append.
+DEF_GO_RUNTIME(GROWSLICE, "runtime.growslice", P3(TYPE, SLICE, INT), R1(SLICE))
// Register roots (global variables) for the garbage collector.
diff --git a/gcc/incpath.c b/gcc/incpath.c
index ea40f4a9323..952d5c4727d 100644
--- a/gcc/incpath.c
+++ b/gcc/incpath.c
@@ -253,8 +253,9 @@ remove_duplicates (cpp_reader *pfile, struct cpp_dir *head,
if (stat (cur->name, &st))
{
- /* Dirs that don't exist are silently ignored, unless verbose. */
- if (errno != ENOENT)
+ /* Dirs that don't exist or have denied permissions are
+ silently ignored, unless verbose. */
+ if ((errno != ENOENT) && (errno != EPERM))
cpp_errno (pfile, CPP_DL_ERROR, cur->name);
else
{
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 111dfa7be4c..fd1cd8b6445 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -363,6 +363,15 @@ expand_ASAN_CHECK (internal_fn, gcall *)
gcc_unreachable ();
}
+/* This should get expanded in the sanopt pass. */
+
+static void
+expand_ASAN_MARK (internal_fn, gcall *)
+{
+ gcc_unreachable ();
+}
+
+
/* This should get expanded in the tsan pass. */
static void
@@ -973,56 +982,68 @@ expand_addsub_overflow (location_t loc, tree_code code, tree lhs,
delete_insns_since (last);
}
- rtx_code_label *sub_check = gen_label_rtx ();
- int pos_neg = 3;
-
/* Compute the operation. On RTL level, the addition is always
unsigned. */
res = expand_binop (mode, code == PLUS_EXPR ? add_optab : sub_optab,
op0, op1, NULL_RTX, false, OPTAB_LIB_WIDEN);
- /* If we can prove one of the arguments (for MINUS_EXPR only
+ /* If we can prove that one of the arguments (for MINUS_EXPR only
the second operand, as subtraction is not commutative) is always
non-negative or always negative, we can do just one comparison
- and conditional jump instead of 2 at runtime, 3 present in the
- emitted code. If one of the arguments is CONST_INT, all we
- need is to make sure it is op1, then the first
- do_compare_rtx_and_jump will be just folded. Otherwise try
- to use range info if available. */
- if (code == PLUS_EXPR && CONST_INT_P (op0))
- std::swap (op0, op1);
- else if (CONST_INT_P (op1))
- ;
- else if (code == PLUS_EXPR && TREE_CODE (arg0) == SSA_NAME)
+ and conditional jump. */
+ int pos_neg = get_range_pos_neg (arg1);
+ if (code == PLUS_EXPR)
{
- pos_neg = get_range_pos_neg (arg0);
- if (pos_neg != 3)
- std::swap (op0, op1);
+ int pos_neg0 = get_range_pos_neg (arg0);
+ if (pos_neg0 != 3 && pos_neg == 3)
+ {
+ std::swap (op0, op1);
+ pos_neg = pos_neg0;
+ }
}
- if (pos_neg == 3 && !CONST_INT_P (op1) && TREE_CODE (arg1) == SSA_NAME)
- pos_neg = get_range_pos_neg (arg1);
- /* If the op1 is negative, we have to use a different check. */
+ /* Addition overflows if and only if the two operands have the same sign,
+ and the result has the opposite sign. Subtraction overflows if and
+ only if the two operands have opposite sign, and the subtrahend has
+ the same sign as the result. Here 0 is counted as positive. */
if (pos_neg == 3)
- do_compare_rtx_and_jump (op1, const0_rtx, LT, false, mode, NULL_RTX,
- NULL, sub_check, PROB_EVEN);
+ {
+ /* Compute op0 ^ op1 (operands have opposite sign). */
+ rtx op_xor = expand_binop (mode, xor_optab, op0, op1, NULL_RTX, false,
+ OPTAB_LIB_WIDEN);
- /* Compare the result of the operation with one of the operands. */
- if (pos_neg & 1)
- do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? GE : LE,
- false, mode, NULL_RTX, NULL, done_label,
- PROB_VERY_LIKELY);
+ /* Compute res ^ op1 (result and 2nd operand have opposite sign). */
+ rtx res_xor = expand_binop (mode, xor_optab, res, op1, NULL_RTX, false,
+ OPTAB_LIB_WIDEN);
- /* If we get here, we have to print the error. */
- if (pos_neg == 3)
- {
- emit_jump (do_error);
- emit_label (sub_check);
+ rtx tem;
+ if (code == PLUS_EXPR)
+ {
+ /* Compute (res ^ op1) & ~(op0 ^ op1). */
+ tem = expand_unop (mode, one_cmpl_optab, op_xor, NULL_RTX, false);
+ tem = expand_binop (mode, and_optab, res_xor, tem, NULL_RTX, false,
+ OPTAB_LIB_WIDEN);
+ }
+ else
+ {
+ /* Compute (op0 ^ op1) & ~(res ^ op1). */
+ tem = expand_unop (mode, one_cmpl_optab, res_xor, NULL_RTX, false);
+ tem = expand_binop (mode, and_optab, op_xor, tem, NULL_RTX, false,
+ OPTAB_LIB_WIDEN);
+ }
+
+ /* No overflow if the result has bit sign cleared. */
+ do_compare_rtx_and_jump (tem, const0_rtx, GE, false, mode, NULL_RTX,
+ NULL, done_label, PROB_VERY_LIKELY);
}
- /* We have k = a + b for b < 0 here. k <= a must hold. */
- if (pos_neg & 2)
- do_compare_rtx_and_jump (res, op0, code == PLUS_EXPR ? LE : GE,
+ /* Compare the result of the operation with the first operand.
+ No overflow for addition if second operand is positive and result
+ is larger or second operand is negative and result is smaller.
+ Likewise for subtraction with sign of second operand flipped. */
+ else
+ do_compare_rtx_and_jump (res, op0,
+ (pos_neg == 1) ^ (code == MINUS_EXPR) ? GE : LE,
false, mode, NULL_RTX, NULL, done_label,
PROB_VERY_LIKELY);
}
@@ -1950,12 +1971,11 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
return;
}
- /* For sub-word operations, if target doesn't have them, start
- with precres widening right away, otherwise do it only
- if the most simple cases can't be used. */
- if (WORD_REGISTER_OPERATIONS
- && orig_precres == precres
- && precres < BITS_PER_WORD)
+ /* For operations with low precision, if target doesn't have them, start
+ with precres widening right away, otherwise do it only if the most
+ simple cases can't be used. */
+ const int min_precision = targetm.min_arithmetic_precision ();
+ if (orig_precres == precres && precres < min_precision)
;
else if ((uns0_p && uns1_p && unsr_p && prec0 <= precres
&& prec1 <= precres)
@@ -1990,7 +2010,7 @@ expand_arith_overflow (enum tree_code code, gimple *stmt)
/* For sub-word operations, retry with a wider type first. */
if (orig_precres == precres && precop <= BITS_PER_WORD)
{
- int p = WORD_REGISTER_OPERATIONS ? BITS_PER_WORD : precop;
+ int p = MAX (min_precision, precop);
enum machine_mode m = smallest_mode_for_size (p, MODE_INT);
tree optype = build_nonstandard_integer_type (GET_MODE_PRECISION (m),
uns0_p && uns1_p
@@ -2346,6 +2366,53 @@ expand_LAUNDER (internal_fn, gcall *call)
expand_assignment (lhs, gimple_call_arg (call, 0), false);
}
+/* Expand DIVMOD() using:
+ a) optab handler for udivmod/sdivmod if it is available.
+ b) If optab_handler doesn't exist, generate call to
+ target-specific divmod libfunc. */
+
+static void
+expand_DIVMOD (internal_fn, gcall *call_stmt)
+{
+ tree lhs = gimple_call_lhs (call_stmt);
+ tree arg0 = gimple_call_arg (call_stmt, 0);
+ tree arg1 = gimple_call_arg (call_stmt, 1);
+
+ gcc_assert (TREE_CODE (TREE_TYPE (lhs)) == COMPLEX_TYPE);
+ tree type = TREE_TYPE (TREE_TYPE (lhs));
+ machine_mode mode = TYPE_MODE (type);
+ bool unsignedp = TYPE_UNSIGNED (type);
+ optab tab = (unsignedp) ? udivmod_optab : sdivmod_optab;
+
+ rtx op0 = expand_normal (arg0);
+ rtx op1 = expand_normal (arg1);
+ rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
+
+ rtx quotient, remainder, libfunc;
+
+ /* Check if optab_handler exists for divmod_optab for given mode. */
+ if (optab_handler (tab, mode) != CODE_FOR_nothing)
+ {
+ quotient = gen_reg_rtx (mode);
+ remainder = gen_reg_rtx (mode);
+ expand_twoval_binop (tab, op0, op1, quotient, remainder, unsignedp);
+ }
+
+ /* Generate call to divmod libfunc if it exists. */
+ else if ((libfunc = optab_libfunc (tab, mode)) != NULL_RTX)
+ targetm.expand_divmod_libfunc (libfunc, mode, op0, op1,
+ &quotient, &remainder);
+
+ else
+ gcc_unreachable ();
+
+ /* Wrap the return value (quotient, remainder) within COMPLEX_EXPR. */
+ expand_expr (build2 (COMPLEX_EXPR, TREE_TYPE (lhs),
+ make_tree (TREE_TYPE (arg0), quotient),
+ make_tree (TREE_TYPE (arg1), remainder)),
+ target, VOIDmode, EXPAND_NORMAL);
+}
+
/* Expand a call to FN using the operands in STMT. FN has a single
output operand and NARGS input operands. */
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 1a128b66a76..77ce63a6408 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -165,6 +165,7 @@ DEF_INTERNAL_FN (UBSAN_OBJECT_SIZE, ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN, NULL)
DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (ASAN_CHECK, ECF_TM_PURE | ECF_LEAF | ECF_NOTHROW, ".R...")
+DEF_INTERNAL_FN (ASAN_MARK, ECF_LEAF | ECF_NOTHROW, ".R..")
DEF_INTERNAL_FN (ADD_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (SUB_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
DEF_INTERNAL_FN (MUL_OVERFLOW, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL)
@@ -208,6 +209,9 @@ DEF_INTERNAL_FN (FALLTHROUGH, ECF_LEAF | ECF_NOTHROW, NULL)
/* To implement __builtin_launder. */
DEF_INTERNAL_FN (LAUNDER, ECF_LEAF | ECF_NOTHROW | ECF_NOVOPS, NULL)
+/* Divmod function. */
+DEF_INTERNAL_FN (DIVMOD, ECF_CONST | ECF_LEAF, NULL)
+
#undef DEF_INTERNAL_INT_FN
#undef DEF_INTERNAL_FLT_FN
#undef DEF_INTERNAL_OPTAB_FN
diff --git a/gcc/ipa-comdats.c b/gcc/ipa-comdats.c
index 6e0f7622366..321bc0fc788 100644
--- a/gcc/ipa-comdats.c
+++ b/gcc/ipa-comdats.c
@@ -416,7 +416,7 @@ public:
bool
pass_ipa_comdats::gate (function *)
{
- return optimize;
+ return HAVE_COMDAT_GROUP && optimize;
}
} // anon namespace
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 1dc5cb6749a..0f34682753e 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -1070,12 +1070,6 @@ ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision,
return set_to_bottom ();
}
- else if (code == NOP_EXPR)
- {
- adjusted_value = other.m_value;
- adjusted_mask = other.m_mask;
- }
-
else
return set_to_bottom ();
@@ -1225,13 +1219,19 @@ ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input)
return NULL_TREE;
if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
- == tcc_comparison)
- restype = boolean_type_node;
+ == tcc_unary)
+ res = fold_unary (ipa_get_jf_pass_through_operation (jfunc),
+ TREE_TYPE (input), input);
else
- restype = TREE_TYPE (input);
- res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
- input, ipa_get_jf_pass_through_operand (jfunc));
-
+ {
+ if (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
+ == tcc_comparison)
+ restype = boolean_type_node;
+ else
+ restype = TREE_TYPE (input);
+ res = fold_binary (ipa_get_jf_pass_through_operation (jfunc), restype,
+ input, ipa_get_jf_pass_through_operand (jfunc));
+ }
if (res && !is_gimple_ip_invariant (res))
return NULL_TREE;
@@ -1840,12 +1840,14 @@ propagate_bits_accross_jump_function (cgraph_edge *cs, int idx, ipa_jump_func *j
}
/* Propagate value range across jump function JFUNC that is associated with
- edge CS and update DEST_PLATS accordingly. */
+ edge CS with param of callee of PARAM_TYPE and update DEST_PLATS
+ accordingly. */
static bool
propagate_vr_accross_jump_function (cgraph_edge *cs,
ipa_jump_func *jfunc,
- struct ipcp_param_lattices *dest_plats)
+ struct ipcp_param_lattices *dest_plats,
+ tree param_type)
{
struct ipcp_param_lattices *src_lats;
ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range;
@@ -1853,6 +1855,11 @@ propagate_vr_accross_jump_function (cgraph_edge *cs,
if (dest_lat->bottom_p ())
return false;
+ if (!param_type
+ || (!INTEGRAL_TYPE_P (param_type)
+ && !POINTER_TYPE_P (param_type)))
+ return dest_lat->set_to_bottom ();
+
if (jfunc->type == IPA_JF_PASS_THROUGH)
{
struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller);
@@ -1863,6 +1870,25 @@ propagate_vr_accross_jump_function (cgraph_edge *cs,
if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR)
return dest_lat->meet_with (src_lats->m_value_range);
+ else if (param_type
+ && (TREE_CODE_CLASS (ipa_get_jf_pass_through_operation (jfunc))
+ == tcc_unary))
+ {
+ value_range vr;
+ memset (&vr, 0, sizeof (vr));
+ tree operand_type = ipa_get_type (caller_info, src_idx);
+ enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc);
+
+ if (src_lats->m_value_range.bottom_p ())
+ return false;
+
+ extract_range_from_unary_expr (&vr,
+ operation,
+ param_type,
+ &src_lats->m_value_range.m_vr,
+ operand_type);
+ return dest_lat->meet_with (&vr);
+ }
}
else if (jfunc->type == IPA_JF_CONST)
{
@@ -1871,6 +1897,7 @@ propagate_vr_accross_jump_function (cgraph_edge *cs,
{
if (TREE_OVERFLOW_P (val))
val = drop_tree_overflow (val);
+ val = fold_convert (param_type, val);
jfunc->vr_known = true;
jfunc->m_vr.type = VR_RANGE;
jfunc->m_vr.min = val;
@@ -2220,6 +2247,7 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
{
struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i);
struct ipcp_param_lattices *dest_plats;
+ tree param_type = ipa_get_callee_param_type (cs, i);
dest_plats = ipa_get_parm_lattices (callee_info, i);
if (availability == AVAIL_INTERPOSABLE)
@@ -2236,7 +2264,8 @@ propagate_constants_accross_call (struct cgraph_edge *cs)
dest_plats);
if (opt_for_fn (callee->decl, flag_ipa_vrp))
ret |= propagate_vr_accross_jump_function (cs,
- jump_func, dest_plats);
+ jump_func, dest_plats,
+ param_type);
else
ret |= dest_plats->m_value_range.set_to_bottom ();
}
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index 16298703fa6..8312c5a9f6b 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -446,6 +446,18 @@ ipa_set_jf_simple_pass_through (struct ipa_jump_func *jfunc, int formal_id,
jfunc->value.pass_through.agg_preserved = agg_preserved;
}
+/* Set JFUNC to be an unary pass through jump function. */
+
+static void
+ipa_set_jf_unary_pass_through (struct ipa_jump_func *jfunc, int formal_id,
+ enum tree_code operation)
+{
+ jfunc->type = IPA_JF_PASS_THROUGH;
+ jfunc->value.pass_through.operand = NULL_TREE;
+ jfunc->value.pass_through.formal_id = formal_id;
+ jfunc->value.pass_through.operation = operation;
+ jfunc->value.pass_through.agg_preserved = false;
+}
/* Set JFUNC to be an arithmetic pass through jump function. */
static void
@@ -849,21 +861,19 @@ parm_preserved_before_stmt_p (struct ipa_func_body_info *fbi, int index,
return !modified;
}
-/* If STMT is an assignment that loads a value from an parameter declaration,
- return the index of the parameter in ipa_node_params which has not been
- modified. Otherwise return -1. */
+/* Main worker for load_from_unmodified_param and load_from_param.
+ If STMT is an assignment that loads a value from an parameter declaration,
+ return the index of the parameter in ipa_node_params. Otherwise return -1. */
static int
-load_from_unmodified_param (struct ipa_func_body_info *fbi,
- vec<ipa_param_descriptor> descriptors,
- gimple *stmt)
+load_from_param_1 (struct ipa_func_body_info *fbi,
+ vec<ipa_param_descriptor> descriptors,
+ gimple *stmt)
{
int index;
tree op1;
- if (!gimple_assign_single_p (stmt))
- return -1;
-
+ gcc_checking_assert (is_gimple_assign (stmt));
op1 = gimple_assign_rhs1 (stmt);
if (TREE_CODE (op1) != PARM_DECL)
return -1;
@@ -876,6 +886,40 @@ load_from_unmodified_param (struct ipa_func_body_info *fbi,
return index;
}
+/* If STMT is an assignment that loads a value from an parameter declaration,
+ return the index of the parameter in ipa_node_params which has not been
+ modified. Otherwise return -1. */
+
+static int
+load_from_unmodified_param (struct ipa_func_body_info *fbi,
+ vec<ipa_param_descriptor> descriptors,
+ gimple *stmt)
+{
+ if (!gimple_assign_single_p (stmt))
+ return -1;
+
+ return load_from_param_1 (fbi, descriptors, stmt);
+}
+
+/* If STMT is an assignment that loads a value from an parameter declaration,
+ return the index of the parameter in ipa_node_params. Otherwise return -1. */
+
+static int
+load_from_param (struct ipa_func_body_info *fbi,
+ vec<ipa_param_descriptor> descriptors,
+ gimple *stmt)
+{
+ if (!is_gimple_assign (stmt))
+ return -1;
+
+ enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
+ if ((get_gimple_rhs_class (rhs_code) != GIMPLE_SINGLE_RHS)
+ && (get_gimple_rhs_class (rhs_code) != GIMPLE_UNARY_RHS))
+ return -1;
+
+ return load_from_param_1 (fbi, descriptors, stmt);
+}
+
/* Return true if memory reference REF (which must be a load through parameter
with INDEX) loads data that are known to be unmodified in this function
before reaching statement STMT. */
@@ -1109,6 +1153,7 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi,
tree op1, tc_ssa, base, ssa;
bool reverse;
int index;
+ gimple *stmt2 = stmt;
op1 = gimple_assign_rhs1 (stmt);
@@ -1117,13 +1162,16 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi,
if (SSA_NAME_IS_DEFAULT_DEF (op1))
index = ipa_get_param_decl_index (info, SSA_NAME_VAR (op1));
else
- index = load_from_unmodified_param (fbi, info->descriptors,
- SSA_NAME_DEF_STMT (op1));
+ {
+ index = load_from_param (fbi, info->descriptors,
+ SSA_NAME_DEF_STMT (op1));
+ stmt2 = SSA_NAME_DEF_STMT (op1);
+ }
tc_ssa = op1;
}
else
{
- index = load_from_unmodified_param (fbi, info->descriptors, stmt);
+ index = load_from_param (fbi, info->descriptors, stmt);
tc_ssa = gimple_assign_lhs (stmt);
}
@@ -1147,6 +1195,13 @@ compute_complex_assign_jump_func (struct ipa_func_body_info *fbi,
bool agg_p = parm_ref_data_pass_through_p (fbi, index, call, tc_ssa);
ipa_set_jf_simple_pass_through (jfunc, index, agg_p);
}
+ else if (is_gimple_assign (stmt2)
+ && (gimple_expr_code (stmt2) != NOP_EXPR)
+ && (TREE_CODE_CLASS (gimple_expr_code (stmt2)) == tcc_unary))
+ {
+ ipa_set_jf_unary_pass_through (jfunc, index,
+ gimple_assign_rhs_code (stmt2));
+ }
return;
}
@@ -1595,7 +1650,10 @@ determine_locally_known_aggregate_parts (gcall *call, tree arg,
}
}
-static tree
+/* Return the Ith param type of callee associated with call graph
+ edge E. */
+
+tree
ipa_get_callee_param_type (struct cgraph_edge *e, int i)
{
int n;
@@ -4663,6 +4721,11 @@ ipa_write_jump_function (struct output_block *ob,
bp_pack_value (&bp, jump_func->value.pass_through.agg_preserved, 1);
streamer_write_bitpack (&bp);
}
+ else if (TREE_CODE_CLASS (jump_func->value.pass_through.operation)
+ == tcc_unary)
+ {
+ streamer_write_uhwi (ob, jump_func->value.pass_through.formal_id);
+ }
else
{
stream_write_tree (ob, jump_func->value.pass_through.operand, true);
@@ -4742,6 +4805,11 @@ ipa_read_jump_function (struct lto_input_block *ib,
bool agg_preserved = bp_unpack_value (&bp, 1);
ipa_set_jf_simple_pass_through (jump_func, formal_id, agg_preserved);
}
+ else if (TREE_CODE_CLASS (operation) == tcc_unary)
+ {
+ int formal_id = streamer_read_uhwi (ib);
+ ipa_set_jf_unary_pass_through (jump_func, formal_id, operation);
+ }
else
{
tree operand = stream_read_tree (ib, data_in);
diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h
index 4eeae882f5f..0e75cf48c1a 100644
--- a/gcc/ipa-prop.h
+++ b/gcc/ipa-prop.h
@@ -818,6 +818,7 @@ ipa_parm_adjustment *ipa_get_adjustment_candidate (tree **, bool *,
ipa_parm_adjustment_vec,
bool);
void ipa_release_body_info (struct ipa_func_body_info *);
+tree ipa_get_callee_param_type (struct cgraph_edge *e, int i);
/* From tree-sra.c: */
tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, bool, tree,
diff --git a/gcc/ira.c b/gcc/ira.c
index cd640fce589..f453ea9e604 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -792,78 +792,85 @@ setup_pressure_classes (void)
HARD_REG_SET temp_hard_regset2;
bool insert_p;
- n = 0;
- for (cl = 0; cl < N_REG_CLASSES; cl++)
- {
- if (ira_class_hard_regs_num[cl] == 0)
- continue;
- if (ira_class_hard_regs_num[cl] != 1
- /* A register class without subclasses may contain a few
- hard registers and movement between them is costly
- (e.g. SPARC FPCC registers). We still should consider it
- as a candidate for a pressure class. */
- && alloc_reg_class_subclasses[cl][0] < cl)
+ if (targetm.compute_pressure_classes)
+ n = targetm.compute_pressure_classes (pressure_classes);
+ else
+ {
+ n = 0;
+ for (cl = 0; cl < N_REG_CLASSES; cl++)
{
- /* Check that the moves between any hard registers of the
- current class are not more expensive for a legal mode
- than load/store of the hard registers of the current
- class. Such class is a potential candidate to be a
- register pressure class. */
- for (m = 0; m < NUM_MACHINE_MODES; m++)
+ if (ira_class_hard_regs_num[cl] == 0)
+ continue;
+ if (ira_class_hard_regs_num[cl] != 1
+ /* A register class without subclasses may contain a few
+ hard registers and movement between them is costly
+ (e.g. SPARC FPCC registers). We still should consider it
+ as a candidate for a pressure class. */
+ && alloc_reg_class_subclasses[cl][0] < cl)
{
- COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
- AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
- AND_COMPL_HARD_REG_SET (temp_hard_regset,
- ira_prohibited_class_mode_regs[cl][m]);
- if (hard_reg_set_empty_p (temp_hard_regset))
+ /* Check that the moves between any hard registers of the
+ current class are not more expensive for a legal mode
+ than load/store of the hard registers of the current
+ class. Such class is a potential candidate to be a
+ register pressure class. */
+ for (m = 0; m < NUM_MACHINE_MODES; m++)
+ {
+ COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset,
+ ira_prohibited_class_mode_regs[cl][m]);
+ if (hard_reg_set_empty_p (temp_hard_regset))
+ continue;
+ ira_init_register_move_cost_if_necessary ((machine_mode) m);
+ cost = ira_register_move_cost[m][cl][cl];
+ if (cost <= ira_max_memory_move_cost[m][cl][1]
+ || cost <= ira_max_memory_move_cost[m][cl][0])
+ break;
+ }
+ if (m >= NUM_MACHINE_MODES)
continue;
- ira_init_register_move_cost_if_necessary ((machine_mode) m);
- cost = ira_register_move_cost[m][cl][cl];
- if (cost <= ira_max_memory_move_cost[m][cl][1]
- || cost <= ira_max_memory_move_cost[m][cl][0])
- break;
}
- if (m >= NUM_MACHINE_MODES)
- continue;
- }
- curr = 0;
- insert_p = true;
- COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
- AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
- /* Remove so far added pressure classes which are subset of the
- current candidate class. Prefer GENERAL_REGS as a pressure
- register class to another class containing the same
- allocatable hard registers. We do this because machine
- dependent cost hooks might give wrong costs for the latter
- class but always give the right cost for the former class
- (GENERAL_REGS). */
- for (i = 0; i < n; i++)
- {
- cl2 = pressure_classes[i];
- COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl2]);
- AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
- if (hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2)
- && (! hard_reg_set_equal_p (temp_hard_regset, temp_hard_regset2)
- || cl2 == (int) GENERAL_REGS))
+ curr = 0;
+ insert_p = true;
+ COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+ /* Remove so far added pressure classes which are subset of the
+ current candidate class. Prefer GENERAL_REGS as a pressure
+ register class to another class containing the same
+ allocatable hard registers. We do this because machine
+ dependent cost hooks might give wrong costs for the latter
+ class but always give the right cost for the former class
+ (GENERAL_REGS). */
+ for (i = 0; i < n; i++)
{
+ cl2 = pressure_classes[i];
+ COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl2]);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
+ if (hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2)
+ && (! hard_reg_set_equal_p (temp_hard_regset,
+ temp_hard_regset2)
+ || cl2 == (int) GENERAL_REGS))
+ {
+ pressure_classes[curr++] = (enum reg_class) cl2;
+ insert_p = false;
+ continue;
+ }
+ if (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset)
+ && (! hard_reg_set_equal_p (temp_hard_regset2,
+ temp_hard_regset)
+ || cl == (int) GENERAL_REGS))
+ continue;
+ if (hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset))
+ insert_p = false;
pressure_classes[curr++] = (enum reg_class) cl2;
- insert_p = false;
- continue;
}
- if (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset)
- && (! hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset)
- || cl == (int) GENERAL_REGS))
- continue;
- if (hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset))
- insert_p = false;
- pressure_classes[curr++] = (enum reg_class) cl2;
+ /* If the current candidate is a subset of a so far added
+ pressure class, don't add it to the list of the pressure
+ classes. */
+ if (insert_p)
+ pressure_classes[curr++] = (enum reg_class) cl;
+ n = curr;
}
- /* If the current candidate is a subset of a so far added
- pressure class, don't add it to the list of the pressure
- classes. */
- if (insert_p)
- pressure_classes[curr++] = (enum reg_class) cl;
- n = curr;
}
#ifdef ENABLE_IRA_CHECKING
{
diff --git a/gcc/jump.c b/gcc/jump.c
index fafef05f5b2..b6828133cb3 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -62,7 +62,7 @@ static void init_label_info (rtx_insn *);
static void mark_all_labels (rtx_insn *);
static void mark_jump_label_1 (rtx, rtx_insn *, bool, bool);
static void mark_jump_label_asm (rtx, rtx_insn *);
-static void redirect_exp_1 (rtx *, rtx, rtx, rtx);
+static void redirect_exp_1 (rtx *, rtx, rtx, rtx_insn *);
static int invert_exp_1 (rtx, rtx_insn *);
/* Worker for rebuild_jump_labels and rebuild_jump_labels_chain. */
@@ -1457,7 +1457,7 @@ redirect_target (rtx x)
NLABEL as a return. Accrue modifications into the change group. */
static void
-redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx insn)
+redirect_exp_1 (rtx *loc, rtx olabel, rtx nlabel, rtx_insn *insn)
{
rtx x = *loc;
RTX_CODE code = GET_CODE (x);
diff --git a/gcc/langhooks-def.h b/gcc/langhooks-def.h
index e49382bfb56..5c330f034b2 100644
--- a/gcc/langhooks-def.h
+++ b/gcc/langhooks-def.h
@@ -84,6 +84,7 @@ extern bool lhd_omp_mappable_type (tree);
extern const char *lhd_get_substring_location (const substring_loc &,
location_t *out_loc);
extern int lhd_decl_dwarf_attribute (const_tree, int);
+extern int lhd_type_dwarf_attribute (const_tree, int);
#define LANG_HOOKS_NAME "GNU unknown"
#define LANG_HOOKS_IDENTIFIER_SIZE sizeof (struct lang_identifier)
@@ -186,6 +187,7 @@ extern tree lhd_make_node (enum tree_code);
#define LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE lhd_enum_underlying_base_type
#define LANG_HOOKS_GET_DEBUG_TYPE NULL
#define LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO NULL
+#define LANG_HOOKS_TYPE_DWARF_ATTRIBUTE lhd_type_dwarf_attribute
#define LANG_HOOKS_FOR_TYPES_INITIALIZER { \
LANG_HOOKS_MAKE_TYPE, \
@@ -208,7 +210,8 @@ extern tree lhd_make_node (enum tree_code);
LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE, \
LANG_HOOKS_ENUM_UNDERLYING_BASE_TYPE, \
LANG_HOOKS_GET_DEBUG_TYPE, \
- LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO \
+ LANG_HOOKS_GET_FIXED_POINT_TYPE_INFO, \
+ LANG_HOOKS_TYPE_DWARF_ATTRIBUTE \
}
/* Declaration hooks. */
diff --git a/gcc/langhooks.c b/gcc/langhooks.c
index 370990ef43b..6483dc1c6d6 100644
--- a/gcc/langhooks.c
+++ b/gcc/langhooks.c
@@ -702,6 +702,15 @@ lhd_decl_dwarf_attribute (const_tree, int)
return -1;
}
+/* Default implementation of LANG_HOOKS_TYPE_DWARF_ATTRIBUTE. Don't add
+ any attributes. */
+
+int
+lhd_type_dwarf_attribute (const_tree, int)
+{
+ return -1;
+}
+
/* Returns true if the current lang_hooks represents the GNU C frontend. */
bool
diff --git a/gcc/langhooks.h b/gcc/langhooks.h
index 8116b170f7b..150227c88d0 100644
--- a/gcc/langhooks.h
+++ b/gcc/langhooks.h
@@ -120,7 +120,7 @@ struct lang_hooks_for_types
/* Return TRUE if TYPE1 and TYPE2 are identical for type hashing purposes.
Called only after doing all language independent checks.
At present, this function is only called when both TYPE1 and TYPE2 are
- FUNCTION_TYPEs. */
+ FUNCTION_TYPE or METHOD_TYPE. */
bool (*type_hash_eq) (const_tree, const_tree);
/* Return TRUE if TYPE uses a hidden descriptor and fills in information
@@ -162,6 +162,10 @@ struct lang_hooks_for_types
for the debugger about scale factor, etc. */
bool (*get_fixed_point_type_info) (const_tree,
struct fixed_point_type_info *);
+
+ /* Returns -1 if dwarf ATTR shouldn't be added for TYPE, or the attribute
+ value otherwise. */
+ int (*type_dwarf_attribute) (const_tree, int);
};
/* Language hooks related to decls and the symbol table. */
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 551103fcf46..f617241ef0f 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -598,13 +598,17 @@ find_exits (struct loop *loop, basic_block *body,
FOR_EACH_EDGE (e, ei, body[i]->succs)
{
- if (flow_bb_inside_loop_p (loop, e->dest))
- continue;
-
- bitmap_set_bit (may_exit, i);
- bitmap_set_bit (has_exit, i);
- outermost_exit = find_common_loop (outermost_exit,
- e->dest->loop_father);
+ if (! flow_bb_inside_loop_p (loop, e->dest))
+ {
+ bitmap_set_bit (may_exit, i);
+ bitmap_set_bit (has_exit, i);
+ outermost_exit = find_common_loop (outermost_exit,
+ e->dest->loop_father);
+ }
+ /* If we enter a subloop that might never terminate treat
+ it like a possible exit. */
+ if (flow_loop_nested_p (loop, e->dest->loop_father))
+ bitmap_set_bit (may_exit, i);
}
continue;
}
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 4ce7ac76358..e350a13dc61 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,9 @@
+2016-10-31 Richard Biener <rguenther@suse.de>
+
+ PR lto/78129
+ * lto.c (do_whole_program_analysis): Bail out after errors
+ from WPA analysis.
+
2016-09-21 Kugan Vivekanandarajah <kuganv@linaro.org>
* lto-partition.c: Include tree-vrp.h.
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 7256ff9547b..c1567ca2ca3 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -3092,6 +3092,10 @@ do_whole_program_analysis (void)
execute_ipa_pass_list (g->get_passes ()->all_regular_ipa_passes);
+ /* When WPA analysis raises errors, do not bother to output anything. */
+ if (seen_error ())
+ return;
+
if (symtab->dump_file)
{
fprintf (symtab->dump_file, "Optimized ");
diff --git a/gcc/match.pd b/gcc/match.pd
index 48f73514a3f..29ddcd82a18 100644
--- a/gcc/match.pd
+++ b/gcc/match.pd
@@ -519,6 +519,18 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
(if (TYPE_UNSIGNED (type))
(bit_and @0 (bit_not (lshift { build_all_ones_cst (type); } @1)))))
+/* PR35691: Transform
+ (x == 0 & y == 0) -> (x | typeof(x)(y)) == 0.
+ (x != 0 | y != 0) -> (x | typeof(x)(y)) != 0. */
+(for bitop (bit_and bit_ior)
+ cmp (eq ne)
+ (simplify
+ (bitop (cmp @0 integer_zerop@2) (cmp @1 integer_zerop))
+ (if (INTEGRAL_TYPE_P (TREE_TYPE (@0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (@1))
+ && TYPE_PRECISION (TREE_TYPE (@0)) == TYPE_PRECISION (TREE_TYPE (@1)))
+ (cmp (bit_ior @0 (convert @1)) @2))))
+
/* Fold (A & ~B) - (A & B) into (A ^ B) - B. */
(simplify
(minus (bit_and:cs @0 (bit_not @1)) (bit_and:cs @0 @1))
diff --git a/gcc/optabs.c b/gcc/optabs.c
index a4d7a5e8e46..7a1f02533bc 100644
--- a/gcc/optabs.c
+++ b/gcc/optabs.c
@@ -1712,8 +1712,9 @@ expand_binop (machine_mode mode, optab binoptab, rtx op0, rtx op1,
{
if (optab_handler (mov_optab, mode) != CODE_FOR_nothing)
{
- temp = emit_move_insn (target ? target : product, product);
- set_dst_reg_note (temp,
+ rtx_insn *move = emit_move_insn (target ? target : product,
+ product);
+ set_dst_reg_note (move,
REG_EQUAL,
gen_rtx_fmt_ee (MULT, mode,
copy_rtx (op0),
diff --git a/gcc/opts.c b/gcc/opts.c
index d381cb5227c..2f230cea315 100644
--- a/gcc/opts.c
+++ b/gcc/opts.c
@@ -979,6 +979,25 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set,
opts->x_flag_aggressive_loop_optimizations = 0;
opts->x_flag_strict_overflow = 0;
}
+
+ /* Enable -fsanitize-address-use-after-scope if address sanitizer is
+ enabled. */
+ if (opts->x_flag_sanitize
+ && !opts_set->x_flag_sanitize_address_use_after_scope)
+ opts->x_flag_sanitize_address_use_after_scope = true;
+
+ /* Force -fstack-reuse=none in case -fsanitize-address-use-after-scope
+ is enabled. */
+ if (opts->x_flag_sanitize_address_use_after_scope)
+ {
+ if (opts->x_flag_stack_reuse != SR_NONE
+ && opts_set->x_flag_stack_reuse != SR_NONE)
+ error_at (loc,
+ "-fsanitize-address-use-after-scope requires "
+ "-fstack-reuse=none option");
+
+ opts->x_flag_stack_reuse = SR_NONE;
+ }
}
#define LEFT_COLUMN 27
@@ -1452,8 +1471,8 @@ const struct sanitizer_opts_s sanitizer_opts[] =
{
#define SANITIZER_OPT(name, flags, recover) \
{ #name, flags, sizeof #name - 1, recover }
- SANITIZER_OPT (address, SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS, true),
- SANITIZER_OPT (kernel-address, SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS,
+ SANITIZER_OPT (address, (SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS), true),
+ SANITIZER_OPT (kernel-address, (SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS),
true),
SANITIZER_OPT (thread, SANITIZE_THREAD, false),
SANITIZER_OPT (leak, SANITIZE_LEAK, false),
@@ -1781,6 +1800,10 @@ common_handle_option (struct gcc_options *opts,
/* Deferred. */
break;
+ case OPT_fsanitize_address_use_after_scope:
+ opts->x_flag_sanitize_address_use_after_scope = value;
+ break;
+
case OPT_fsanitize_recover:
if (value)
opts->x_flag_sanitize_recover
diff --git a/gcc/params.def b/gcc/params.def
index ab3eb3d3b42..89f70936d2e 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -1168,6 +1168,12 @@ DEFPARAM (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD,
"in function becomes greater or equal to this number.",
7000, 0, INT_MAX)
+DEFPARAM (PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD,
+ "use-after-scope-direct-emission-threshold",
+ "Use direct poisoning/unpoisoning intructions for variables "
+ "smaller or equal to this number.",
+ 256, 0, INT_MAX)
+
DEFPARAM (PARAM_UNINIT_CONTROL_DEP_ATTEMPTS,
"uninit-control-dep-attempts",
"Maximum number of nested calls to search for control dependencies "
diff --git a/gcc/params.h b/gcc/params.h
index 97c8d565055..0a2905ce1ff 100644
--- a/gcc/params.h
+++ b/gcc/params.h
@@ -244,5 +244,7 @@ extern void init_param_values (int *params);
PARAM_VALUE (PARAM_ASAN_USE_AFTER_RETURN)
#define ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD \
PARAM_VALUE (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD)
+#define ASAN_PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD \
+ ((unsigned) PARAM_VALUE (PARAM_USE_AFTER_SCOPE_DIRECT_EMISSION_THRESHOLD))
#endif /* ! GCC_PARAMS_H */
diff --git a/gcc/po/ChangeLog b/gcc/po/ChangeLog
index f85cc0db0e4..c6c7a3effcb 100644
--- a/gcc/po/ChangeLog
+++ b/gcc/po/ChangeLog
@@ -1,3 +1,15 @@
+2016-11-07 Joseph Myers <joseph@codesourcery.com>
+
+ * es.po: Update.
+
+2016-11-05 Joseph Myers <joseph@codesourcery.com>
+
+ * es.po: Update.
+
+2016-11-01 Joseph Myers <joseph@codesourcery.com>
+
+ * es.po: Update.
+
2016-10-10 Joseph Myers <joseph@codesourcery.com>
* sv.po: Update.
diff --git a/gcc/po/es.po b/gcc/po/es.po
index 5049cc3c407..346cd9130fc 100644
--- a/gcc/po/es.po
+++ b/gcc/po/es.po
@@ -1,22 +1,44 @@
# Mensajes en español para gcc-4.7.2.
-# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Free Software Foundation, Inc.
+# Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2016 Free Software Foundation, Inc.
# This file is distributed under the same license as the gcc package.
# Cristian Othón Martínez Vera <cfuga@cfuga.mx>, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
+# Antonio Ceballos Roa <aceballos@gmail.com>, 2016
#
# Agradezco a Juan Cuquejo Mira por sus comentarios sobre esta traducción
#
+# Glosario
+#
+# asan - asan
+# bug - error
+# callback - callback
+# cse - TBD
+# demangled - mutilado
+# hardware - hardware
+# hotness - calentura
+# insns - TBD
+# instruction - instrucción
+# iv optimization - optimización iv
+# omp (OpenMP) - omp
+# OS - S.O.
+# report - informe TODO
+# scheduler - planificador
+# SSA - SSA
+# statement - sentencia
+# ubsan - ubsan
+#
msgid ""
msgstr ""
-"Project-Id-Version: gcc 4.7.2\n"
+"Project-Id-Version: gcc 6.2.0\n"
"Report-Msgid-Bugs-To: http://gcc.gnu.org/bugs.html\n"
"POT-Creation-Date: 2016-08-19 21:03+0000\n"
-"PO-Revision-Date: 2012-09-24 13:50-0500\n"
-"Last-Translator: Cristian Othón Martínez Vera <cfuga@cfuga.mx>\n"
-"Language-Team: Spanish <es@li.org>\n"
+"PO-Revision-Date: 2016-11-06 21:49+0100\n"
+"Last-Translator: Antonio Ceballos <aceballos@gmail.com>\n"
+"Language-Team: Spanish <es@tp.org.es>\n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"X-Bugs: Report translation errors to the Language-Team address.\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#: cfgrtl.c:2656
@@ -120,24 +142,18 @@ msgid "compilation terminated due to -fmax-errors=%u.\n"
msgstr "compilación terminada debido a -fmax-errors=%u.\n"
#: diagnostic.c:481
-#, fuzzy, c-format
-#| msgid ""
-#| "Please submit a full bug report,\n"
-#| "with preprocessed source if appropriate.\n"
-#| "See %s for instructions.\n"
+#, c-format
msgid ""
"Please submit a full bug report,\n"
"with preprocessed source if appropriate.\n"
msgstr ""
-"Por favor envíe un reporte completo de bichos,\n"
+"Por favor, envíe un informe completo de errores,\n"
"con el código preprocesado si es apropiado.\n"
-"Vea %s para más instrucciones.\n"
#: diagnostic.c:487
-#, fuzzy, c-format
-#| msgid "Use fp double instructions"
+#, c-format
msgid "See %s for instructions.\n"
-msgstr "Usa instrucciones fp double"
+msgstr "Véase %s para instrucciones.\n"
#: diagnostic.c:496
#, c-format
@@ -285,19 +301,19 @@ msgstr "Opciones:\n"
#, fuzzy
#| msgid " -pass-exit-codes Exit with highest error code from a phase\n"
msgid " -pass-exit-codes Exit with highest error code from a phase.\n"
-msgstr " -pass-exit-codes Sale con el código de error más alto de una fase\n"
+msgstr " -pass-exit-codes Sale con el código de error más alto de una fase.\n"
#: gcc.c:3385
#, fuzzy
#| msgid " --help Display this information\n"
msgid " --help Display this information.\n"
-msgstr " --help Muestra esta información\n"
+msgstr " --help Muestra esta información.\n"
#: gcc.c:3386
#, fuzzy
#| msgid " --target-help Display target specific command line options\n"
msgid " --target-help Display target specific command line options.\n"
-msgstr " --target-help Muestra opciones de línea de órdenes específicas del objetivo\n"
+msgstr " --target-help Muestra opciones de línea de órdenes específicas del objetivo.\n"
#: gcc.c:3387
#, fuzzy
@@ -627,12 +643,12 @@ msgstr "controlador gcc versión %s %sejecutando gcc versión %s\n"
#: gcc.c:6683 gcc.c:6895
#, c-format
msgid "The bug is not reproducible, so it is likely a hardware or OS problem.\n"
-msgstr ""
+msgstr "El error no es repetible, por lo que probablemente sea un problema de hardware o de S.O.\n"
#: gcc.c:6819
#, c-format
msgid "Preprocessed source stored into %s file, please attach this to your bugreport.\n"
-msgstr ""
+msgstr "Fuente preprocesada almacenada en el fichero %s; por favor, adjúntelo a su informe de errores.\n"
#: gcc.c:7761
#, c-format
@@ -656,7 +672,7 @@ msgid ""
"For bug reporting instructions, please see:\n"
msgstr ""
"\n"
-"Para instrucciones de reporte de bichos, por favor vea:\n"
+"Para instrucciones de informe de errores, por favor vea:\n"
#: gcc.c:7899 gcov-tool.c:525
#, c-format
@@ -723,111 +739,106 @@ msgstr ""
#: gcov-tool.c:166
#, c-format
msgid " merge [options] <dir1> <dir2> Merge coverage file contents\n"
-msgstr ""
+msgstr " merge [opciones] <dir1> <dir2> Mezcla el contenido del fichero de cobertura\n"
#: gcov-tool.c:167 gcov-tool.c:261 gcov-tool.c:417
-#, fuzzy, c-format
-#| msgid " -v, --version Print version number, then exit\n"
+#, c-format
msgid " -v, --verbose Verbose mode\n"
-msgstr " -v, --version Muestra el número de versión, y finaliza\n"
+msgstr " -v, --verbose Modo expresivo\n"
#: gcov-tool.c:168 gcov-tool.c:262
-#, fuzzy, c-format
-#| msgid " -n, --no-output Do not create an output file\n"
+#, c-format
msgid " -o, --output <dir> Output directory\n"
-msgstr " -n, --no-output No crea un fichero de salida\n"
+msgstr " -o, --output <dir> Directorio de salida\n"
#: gcov-tool.c:169
#, c-format
msgid " -w, --weight <w1,w2> Set weights (float point values)\n"
-msgstr ""
+msgstr " -w, --weight <p1,p2> Establece los pesos (valores de coma flotante)\n"
#: gcov-tool.c:185
#, c-format
msgid "Merge subcomand usage:"
-msgstr ""
+msgstr "Modo de empleo de la suborden de mezcla:"
#: gcov-tool.c:260
#, c-format
msgid " rewrite [options] <dir> Rewrite coverage file contents\n"
-msgstr ""
+msgstr " rewrite [opciones] <dir> Reescribe el contenido del fichero de cobertura\n"
#: gcov-tool.c:263
#, c-format
msgid " -s, --scale <float or simple-frac> Scale the profile counters\n"
-msgstr ""
+msgstr " -s, --scale <float o frac-simple> Escala los contadores de perfil\n"
#: gcov-tool.c:264
#, c-format
msgid " -n, --normalize <long long> Normalize the profile\n"
-msgstr ""
+msgstr " -n, --normalize <long long> Normaliza el perfil\n"
#: gcov-tool.c:281
#, c-format
msgid "Rewrite subcommand usage:"
-msgstr ""
+msgstr "Modo de empleo de la suborden de reescritura:"
#: gcov-tool.c:326
#, c-format
msgid "scaling cannot co-exist with normalization, skipping\n"
-msgstr ""
+msgstr "escalado y normalización no pueden coexistir; se omite\n"
#: gcov-tool.c:339 gcov-tool.c:349
#, c-format
msgid "incorrect format in scaling, using 1/1\n"
-msgstr ""
+msgstr "formato de escalado incorrecto; se utiliza 1/1\n"
#: gcov-tool.c:359
#, c-format
msgid "normalization cannot co-exist with scaling\n"
-msgstr ""
+msgstr "normalización y escalado no pueden coexistir\n"
#: gcov-tool.c:416
#, c-format
msgid " overlap [options] <dir1> <dir2> Compute the overlap of two profiles\n"
-msgstr ""
+msgstr " overlap [opciones] <dir1> <dir2> Calcula el solapamiento de dos perfiles\n"
#: gcov-tool.c:418
-#, fuzzy, c-format
-#| msgid " -h, --help Print this help, then exit\n"
+#, c-format
msgid " -h, --hotonly Only print info for hot objects/functions\n"
-msgstr " -h, --help Muestra esta información, y finaliza\n"
+msgstr " -h, --hotonly Solo imprime información sobre objetos y funciones calientes\n"
#: gcov-tool.c:419
-#, fuzzy, c-format
-#| msgid " -p Enable function profiling\n"
+#, c-format
msgid " -f, --function Print function level info\n"
-msgstr " -p Activar el análisis de perfil de funciones\n"
+msgstr " -f, --function Imprime información sobre el nivel de funciones\n"
#: gcov-tool.c:420
-#, fuzzy, c-format
-#| msgid " -h, --help Print this help, then exit\n"
+#, c-format
msgid " -F, --fullname Print full filename\n"
-msgstr " -h, --help Muestra esta información, y finaliza\n"
+msgstr " -F, --fullname Imprime el nombre de fichero completo\n"
#: gcov-tool.c:421
-#, fuzzy, c-format
-#| msgid " -h, --help Print this help, then exit\n"
+#, c-format
msgid " -o, --object Print object level info\n"
-msgstr " -h, --help Muestra esta información, y finaliza\n"
+msgstr " -o, --object Imprime información sobre el nivel de objetos\n"
#: gcov-tool.c:422
#, c-format
msgid " -t <float>, --hot_threshold <float> Set the threshold for hotness\n"
-msgstr ""
+msgstr " -t <float>, --hot_threshold <float> Establece el umbral de calentura\n"
#: gcov-tool.c:442
#, c-format
msgid "Overlap subcomand usage:"
-msgstr ""
+msgstr "Modo de empleo de la suborden de solapamiento:"
#: gcov-tool.c:508
-#, fuzzy, c-format
-#| msgid "Usage: %s [OPTIONS]... CLASSNAMEmain [OUTFILE]\n"
+#, c-format
msgid ""
"Usage: %s [OPTION]... SUB_COMMAND [OPTION]...\n"
"\n"
-msgstr "Modo de empleo: %s [OPCIONES]... NOMBRECLASEmain [FICHERO-SALIDA]\n"
+msgstr ""
+"Modo de empleo: %s [OPCIÓN]... SUB_ORDEN [OPCIÓN]...\n"
+"\n"
#: gcov-tool.c:509
#, c-format
@@ -835,6 +846,8 @@ msgid ""
"Offline tool to handle gcda counts\n"
"\n"
msgstr ""
+"Herramienta «offline» para manejar contadores de gcda\n"
+"\n"
#: gcov-tool.c:510
#, fuzzy, c-format
@@ -856,7 +869,7 @@ msgid ""
"%s.\n"
msgstr ""
"\n"
-"Para instrucciones de reporte de bichos, por favor vea:\n"
+"Para instrucciones de informe de errores, por favor vea:\n"
"%s.\n"
#: gcov-tool.c:526
@@ -936,7 +949,7 @@ msgstr " -f, --function-summaries Muestra sumarios para cada función\n"
#: gcov.c:481
#, c-format
msgid " -i, --intermediate-format Output .gcov file in intermediate text format\n"
-msgstr ""
+msgstr " -t, --intermediate-format Fichero de salida .gcov en formato de texto intermedio\n"
#: gcov.c:482
#, c-format
@@ -950,7 +963,7 @@ msgstr ""
#: gcov.c:484
#, c-format
msgid " -m, --demangled-names Output demangled function names\n"
-msgstr ""
+msgstr " -m, --demangled-names Nombres de función mutilados de salida\n"
#: gcov.c:485
#, c-format
@@ -1327,30 +1340,27 @@ msgstr "no se pueden generar recargas para:"
#. What to print when a switch has no documentation.
#: opts.c:184
-#, fuzzy
-#| msgid "This switch lacks documentation"
msgid "This option lacks documentation."
-msgstr "Esta opción carece de documentación"
+msgstr "Esta opción carece de documentación."
#: opts.c:185
msgid "Uses of this option are diagnosed."
-msgstr ""
+msgstr "Los usos de esta opción están diagnosticados."
#: opts.c:1061
#, c-format
msgid "default %d minimum %d maximum %d"
-msgstr ""
+msgstr "predeterminado %d mínimo %d máximo %d"
#: opts.c:1128
#, c-format
msgid "Same as %s. Use the latter option instead."
-msgstr ""
+msgstr "Igual que %s. Utilice, en cambio, la última opción."
#: opts.c:1136
-#, fuzzy, c-format
-#| msgid "(%s %s %s %s %s"
+#, c-format
msgid "%s Same as %s."
-msgstr "(%s %s %s %s %s"
+msgstr "%s Igual que %s."
#: opts.c:1207
msgid "[default]"
@@ -1435,7 +1445,7 @@ msgstr "Plugins"
#: plugin.c:828
#, c-format
msgid "*** WARNING *** there are active plugins, do not report this as a bug unless you can reproduce it without enabling any plugins.\n"
-msgstr "*** AVISO *** hay plugins activos, no reporte esto como un bicho a menos que pueda reproducirlo sin activar ningún plugin.\n"
+msgstr "*** AVISO *** hay plugins activos, no informe esto como un error a menos que pueda reproducirlo sin activar ningún plugin.\n"
#. It's the compiler's fault.
#: reload1.c:6113
@@ -1636,10 +1646,8 @@ msgid "callee refers to comdat-local symbols"
msgstr ""
#: cif-code.def:125
-#, fuzzy
-#| msgid "optimization level attribute mismatch"
msgid "function attribute mismatch"
-msgstr "no coincide el atributo de nivel de optimización"
+msgstr "no coincide el atributo de función"
#: cif-code.def:129
#, fuzzy
@@ -1648,10 +1656,8 @@ msgid "caller function contains cilk spawn"
msgstr "función inválida en la declaración call"
#: cif-code.def:133
-#, fuzzy
-#| msgid "Unreachable statement"
msgid "unreachable"
-msgstr "Declaración inalcanzable"
+msgstr "inalcanzable"
#. The remainder are real diagnostic types.
#: diagnostic.def:33
@@ -1701,10 +1707,9 @@ msgid "permerror: "
msgstr "errorperm: "
#: params.def:49
-#, fuzzy, no-c-format
-#| msgid "Maximal estimated outcome of branch considered predictable"
+#, no-c-format
msgid "Maximal estimated outcome of branch considered predictable."
-msgstr "Salida estimada maximal de la ramificación considerada predecible"
+msgstr "Salida estimada máxima de la ramificación considerada predecible."
#: params.def:54
#, no-c-format
@@ -1712,695 +1717,592 @@ msgid "The minimal estimated speedup allowing inliner to ignore inline-insns-sin
msgstr ""
#: params.def:71
-#, fuzzy, no-c-format
-#| msgid "The maximum number of instructions in a single function eligible for inlining"
+#, no-c-format
msgid "The maximum number of instructions in a single function eligible for inlining."
-msgstr "El número máximo de instrucciones en una sola función elegible para inclusión en línea"
+msgstr "El número máximo de instrucciones en una sola función elegible para inclusión en línea."
#: params.def:83
-#, fuzzy, no-c-format
-#| msgid "The maximum number of instructions when automatically inlining"
+#, no-c-format
msgid "The maximum number of instructions when automatically inlining."
-msgstr "El número máximo de instrucciones cuando se hace inclusión en línea automáticamente"
+msgstr "El número máximo de instrucciones cuando se hace inclusión en línea automáticamente."
#: params.def:88
-#, fuzzy, no-c-format
-#| msgid "The maximum number of instructions inline function can grow to via recursive inlining"
+#, no-c-format
msgid "The maximum number of instructions inline function can grow to via recursive inlining."
-msgstr "El número máximo de instrucciones que una función incluída en línea puede crecer a través de inclusión en línea recursiva"
+msgstr "El número máximo de instrucciones que una función incluida en línea puede crecer a través de inclusión en línea recursiva."
#: params.def:93
-#, fuzzy, no-c-format
-#| msgid "The maximum number of instructions non-inline function can grow to via recursive inlining"
+#, no-c-format
msgid "The maximum number of instructions non-inline function can grow to via recursive inlining."
-msgstr "El número máximo de instrucciones que una función que no se incluye en línea puede crecer a través de inclusión en línea recursiva"
+msgstr "El número máximo de instrucciones que una función que no se incluye en línea puede crecer a través de inclusión en línea recursiva."
#: params.def:98
-#, fuzzy, no-c-format
-#| msgid "The maximum depth of recursive inlining for inline functions"
+#, no-c-format
msgid "The maximum depth of recursive inlining for inline functions."
-msgstr "La máxima profundidad para la inclusión en línea recursiva para funciones incluídas en línea"
+msgstr "La máxima profundidad para la inclusión en línea recursiva para funciones incluídas en línea."
#: params.def:103
-#, fuzzy, no-c-format
-#| msgid "The maximum depth of recursive inlining for non-inline functions"
+#, no-c-format
msgid "The maximum depth of recursive inlining for non-inline functions."
-msgstr "La máxima profundidad para la inclusión en línea recursiva para funciones que no son incluídas en línea"
+msgstr "La máxima profundidad para la inclusión en línea recursiva para funciones que no son incluídas en línea."
#: params.def:108
-#, fuzzy, no-c-format
-#| msgid "Inline recursively only when the probability of call being executed exceeds the parameter"
+#, no-c-format
msgid "Inline recursively only when the probability of call being executed exceeds the parameter."
-msgstr "Incluir en línea recursivamente sólo cuando la probabilidad de que la llamada se ejecute exceda el parámetro"
+msgstr "Incluir en línea recursivamente solo cuando la probabilidad de que la llamada se ejecute exceda el parámetro."
#: params.def:116
-#, fuzzy, no-c-format
-#| msgid "The maximum number of nested indirect inlining performed by early inliner"
+#, no-c-format
msgid "The maximum number of nested indirect inlining performed by early inliner."
-msgstr "El número máximo de inclusiones de instrucciones en línea anidadas realizado por el inlineador temprano"
+msgstr "El número máximo de inclusiones de instrucciones en línea anidadas realizado por el inlineador temprano."
#: params.def:122
-#, fuzzy, no-c-format
-#| msgid "Probability that COMDAT function will be shared with different compilation unit"
+#, no-c-format
msgid "Probability that COMDAT function will be shared with different compilation unit."
-msgstr "Probabilidad de que la función COMDAT se comparta con diferentes unidades de compilación"
+msgstr "Probabilidad de que la función COMDAT se comparta con diferentes unidades de compilación."
#: params.def:128
-#, fuzzy, no-c-format
-#| msgid "Maximum probability of the entry BB of split region (in percent relative to entry BB of the function) to make partial inlining happen"
+#, no-c-format
msgid "Maximum probability of the entry BB of split region (in percent relative to entry BB of the function) to make partial inlining happen."
-msgstr "Probabilidad máxima de la entrada BB de la región de división (en porcentaje relativo a la entrada BB de la función) para que suceda la inclusión en línea parcial"
+msgstr "Probabilidad máxima de la entrada BB de la región de división (en porcentaje relativo a la entrada BB de la función) para que suceda la inclusión en línea parcial."
#: params.def:135
-#, fuzzy, no-c-format
-#| msgid "If -fvariable-expansion-in-unroller is used, the maximum number of times that an individual variable will be expanded during loop unrolling"
+#, no-c-format
msgid "If -fvariable-expansion-in-unroller is used, the maximum number of times that an individual variable will be expanded during loop unrolling."
-msgstr "Si se usa -fvariable-expansion-in-unroller, el número máximo de veces que una variable individual se expandirá durante el desenrollo de bucles"
+msgstr "Si se usa -fvariable-expansion-in-unroller, el número máximo de veces que una variable individual se expandirá durante el desenrollo de bucles."
#: params.def:141
-#, fuzzy, no-c-format
-#| msgid "If -ftree-vectorize is used, the minimal loop bound of a loop to be considered for vectorization"
+#, no-c-format
msgid "If -ftree-vectorize is used, the minimal loop bound of a loop to be considered for vectorization."
-msgstr "Si se usa -ftree-vectorize, el límite de bucle minimal de un bucle para considerarse en la vectorización"
+msgstr "Si se usa -ftree-vectorize, el límite de bucle mínimo de un bucle para considerarse en la vectorización."
#: params.def:152
-#, fuzzy, no-c-format
-#| msgid "The maximum number of instructions to consider to fill a delay slot"
+#, no-c-format
msgid "The maximum number of instructions to consider to fill a delay slot."
-msgstr "El número máximo de instrucciones para considerar el llenado de una ranura de retraso"
+msgstr "El número máximo de instrucciones para considerar el llenado de una ranura de retraso."
#: params.def:163
-#, fuzzy, no-c-format
-#| msgid "The maximum number of instructions to consider to find accurate live register information"
+#, no-c-format
msgid "The maximum number of instructions to consider to find accurate live register information."
-msgstr "El número máximo de instruccions para considerar la búsqueda de información de registros en vivo exacta"
+msgstr "El número máximo de instrucciones para considerar la búsqueda de información de registros en vivo exacta."
#: params.def:173
-#, fuzzy, no-c-format
-#| msgid "The maximum length of scheduling's pending operations list"
+#, no-c-format
msgid "The maximum length of scheduling's pending operations list."
-msgstr "La longitud máxima de la lista de operaciones pendientes del calendarizador"
+msgstr "La longitud máxima de la lista de operaciones pendientes del planificador."
#: params.def:180
#, fuzzy, no-c-format
#| msgid "The maximum number of backtrack attempts the scheduler should make when modulo scheduling a loop"
msgid "The maximum number of backtrack attempts the scheduler should make when modulo scheduling a loop."
-msgstr "El número máximo de intentos hacia atrás que debe hacer el calendarizador cuando calendarice un bucle módulo"
+msgstr "El número máximo de intentos hacia atrás que debe hacer el planificador cuando planifique un bucle módulo"
#: params.def:185
-#, fuzzy, no-c-format
-#| msgid "The size of function body to be considered large"
+#, no-c-format
msgid "The size of function body to be considered large."
-msgstr "El tamaño del cuerpo de la función a considerar grande"
+msgstr "El tamaño del cuerpo de la función que será considerado grande."
#: params.def:189
-#, fuzzy, no-c-format
-#| msgid "Maximal growth due to inlining of large function (in percent)"
+#, no-c-format
msgid "Maximal growth due to inlining of large function (in percent)."
-msgstr "Crecimiento de código maximal causado por la inclusión en línea de una función grande (en porcentaje)"
+msgstr "Máximo crecimiento causado por la inclusión en línea de una función grande (en porcentaje)."
#: params.def:193
-#, fuzzy, no-c-format
-#| msgid "The size of translation unit to be considered large"
+#, no-c-format
msgid "The size of translation unit to be considered large."
-msgstr "El tamaño de la unidad de traducción a considerar grande"
+msgstr "El tamaño de la unidad de traducción que será considerado grande."
#: params.def:197
-#, fuzzy, no-c-format
-#| msgid "How much can given compilation unit grow because of the inlining (in percent)"
+#, no-c-format
msgid "How much can given compilation unit grow because of the inlining (in percent)."
-msgstr "Cuánto puede crecer la unidad de compilación dada a causa de la inclusión en línea (en porcentaje)"
+msgstr "Cuánto puede crecer la unidad de compilación dada a causa de la inclusión en línea (en porcentaje)."
#: params.def:201
-#, fuzzy, no-c-format
-#| msgid "How much can given compilation unit grow because of the interprocedural constant propagation (in percent)"
+#, no-c-format
msgid "How much can given compilation unit grow because of the interprocedural constant propagation (in percent)."
-msgstr "Cuánto puede crecer la unidad de compilación dada a causa de la propagación constante interprocedural (en porcentaje)"
+msgstr "Cuánto puede crecer la unidad de compilación dada a causa de la propagación constante interprocedural (en porcentaje)."
#: params.def:205
-#, fuzzy, no-c-format
-#| msgid "Maximal estimated growth of function body caused by early inlining of single call"
+#, no-c-format
msgid "Maximal estimated growth of function body caused by early inlining of single call."
-msgstr "El crecimiento estimado maximal del cuerpo de la función causado por la inclusión en línea temprano de una sola llamada"
+msgstr "Máximo crecimiento estimado del cuerpo de la función causado por la inclusión temprana en línea de una sola llamada."
#: params.def:209
-#, fuzzy, no-c-format
-#| msgid "The size of stack frame to be considered large"
+#, no-c-format
msgid "The size of stack frame to be considered large."
-msgstr "El tamaño del marco de la pila a considerar grande"
+msgstr "El tamaño del marco de la pila que será considerado grande."
#: params.def:213
-#, fuzzy, no-c-format
-#| msgid "Maximal stack frame growth due to inlining (in percent)"
+#, no-c-format
msgid "Maximal stack frame growth due to inlining (in percent)."
-msgstr "Crecimiento de marco de pila maximal causado por la inclusión en línea (en porcentaje)"
+msgstr "Máximo crecimiento de marco de pila causado por la inclusión en línea (en porcentaje)."
#: params.def:220
-#, fuzzy, no-c-format
-#| msgid "The maximum amount of memory to be allocated by GCSE"
+#, no-c-format
msgid "The maximum amount of memory to be allocated by GCSE."
-msgstr "La cantidad máxima de memoria a ser asignada por GCSE"
+msgstr "La cantidad máxima de memoria a ser asignada por GCSE."
#: params.def:227
-#, fuzzy, no-c-format
-#| msgid "The maximum ratio of insertions to deletions of expressions in GCSE"
+#, no-c-format
msgid "The maximum ratio of insertions to deletions of expressions in GCSE."
-msgstr "La tasa máxima de inserciones para borrados de expresiones en GCSE"
+msgstr "La tasa máxima de inserciones para borrados de expresiones en GCSE."
#: params.def:238
-#, fuzzy, no-c-format
-#| msgid "The threshold ratio for performing partial redundancy elimination after reload"
+#, no-c-format
msgid "The threshold ratio for performing partial redundancy elimination after reload."
-msgstr "La tasa de intervalo para realizar la eliminación parcial de redundancia después de la recarga"
+msgstr "La tasa de intervalo para realizar la eliminación parcial de redundancia después de la recarga."
#: params.def:245
-#, fuzzy, no-c-format
-#| msgid "The threshold ratio of critical edges execution count that permit performing redundancy elimination after reload"
+#, no-c-format
msgid "The threshold ratio of critical edges execution count that permit performing redundancy elimination after reload."
-msgstr "La tasa de intervalo para la cuenta de ejecución de bordes críticos que permitan la eliminación de redundancia después de la recarga"
+msgstr "La tasa de intervalo para la cuenta de ejecución de bordes críticos que permitan la eliminación de redundancia después de la recarga."
#: params.def:253
-#, fuzzy, no-c-format
-#| msgid "Scaling factor in calculation of maximum distance an expression can be moved by GCSE optimizations"
+#, no-c-format
msgid "Scaling factor in calculation of maximum distance an expression can be moved by GCSE optimizations."
-msgstr "Factor de escala en el cálculo de la distancia máxima a la cual se puede mover una expresión por optimizaciones GCSE"
+msgstr "Factor de escala en el cálculo de la distancia máxima a la cual se puede mover una expresión por optimizaciones GCSE."
#: params.def:259
-#, fuzzy, no-c-format
-#| msgid "Cost at which GCSE optimizations will not constraint the distance an expression can travel"
+#, no-c-format
msgid "Cost at which GCSE optimizations will not constraint the distance an expression can travel."
-msgstr "Costo al cual las optimizaciones GCSE no restringirán la distancia que puede viajar una expresión"
+msgstr "Costo al cual las optimizaciones GCSE no restringirán la distancia que puede viajar una expresión."
#: params.def:267
-#, fuzzy, no-c-format
-#| msgid "Maximum depth of search in the dominator tree for expressions to hoist"
+#, no-c-format
msgid "Maximum depth of search in the dominator tree for expressions to hoist."
-msgstr "Profundidad máxima de la búsqueda en el árbol dominador por expresiones para levantar"
+msgstr "Profundidad máxima de la búsqueda en el árbol dominador por expresiones para levantar."
#: params.def:275
#, no-c-format
msgid "Maximum depth of sqrt chains to use when synthesizing exponentiation by a real constant."
-msgstr ""
+msgstr "Máxima profundidad de cadenas sqrt que se utilizará cuando se sintetice la exponenciación mediante una constante real."
#: params.def:287
-#, fuzzy, no-c-format
-#| msgid "The maximum number of instructions to consider to unroll in a loop"
+#, no-c-format
msgid "The maximum number of instructions to consider to unroll in a loop."
-msgstr "El número máximo de instrucciones para considerar el desenrollo en un bucle"
+msgstr "El número máximo de instrucciones para considerar el desenrollo en un bucle."
#: params.def:293
-#, fuzzy, no-c-format
-#| msgid "The maximum number of instructions to consider to unroll in a loop on average"
+#, no-c-format
msgid "The maximum number of instructions to consider to unroll in a loop on average."
-msgstr "El número máximo de instrucciones para considerar el desenrollo en un bucle en promedio"
+msgstr "El número máximo de instrucciones para considerar el desenrollo en un bucle en promedio."
#: params.def:298
-#, fuzzy, no-c-format
-#| msgid "The maximum number of unrollings of a single loop"
+#, no-c-format
msgid "The maximum number of unrollings of a single loop."
-msgstr "El número máximo de desenrollos de un solo bucle"
+msgstr "El número máximo de desenrollos de un solo bucle."
#: params.def:303
-#, fuzzy, no-c-format
-#| msgid "The maximum number of insns of a peeled loop"
+#, no-c-format
msgid "The maximum number of insns of a peeled loop."
-msgstr "El número máximo de insns en un bucle pelado"
+msgstr "El número máximo de insns en un bucle pelado."
#: params.def:308
-#, fuzzy, no-c-format
-#| msgid "The maximum number of peelings of a single loop"
+#, no-c-format
msgid "The maximum number of peelings of a single loop."
-msgstr "El número máximo de pelados en un solo bucle"
+msgstr "El número máximo de pelados en un solo bucle."
#: params.def:313
-#, fuzzy, no-c-format
-#| msgid "The maximum number of iterations through CFG to extend regions"
+#, no-c-format
msgid "The maximum number of branches on the path through the peeled sequence."
-msgstr "El número máximo de iteraciones a través de CFG para extender regiones"
+msgstr "El número máximo de ramificaciones en la ruta hacia una secuencia pelada."
#: params.def:318
-#, fuzzy, no-c-format
-#| msgid "The maximum number of insns of a completely peeled loop"
+#, no-c-format
msgid "The maximum number of insns of a completely peeled loop."
-msgstr "El número máximo de insns en un bucle completamente pelado"
+msgstr "El número máximo de insns en un bucle completamente pelado."
#: params.def:323
-#, fuzzy, no-c-format
-#| msgid "The maximum number of peelings of a single loop that is peeled completely"
+#, no-c-format
msgid "The maximum number of peelings of a single loop that is peeled completely."
-msgstr "El número máximo de pelados en un solo bucle que está completamente pelado"
+msgstr "El número máximo de pelados en un solo bucle que está completamente pelado."
#: params.def:328
-#, fuzzy, no-c-format
-#| msgid "The maximum number of insns of a peeled loop that rolls only once"
+#, no-c-format
msgid "The maximum number of insns of a peeled loop that rolls only once."
-msgstr "El número máximo de insns en un bucle pelado que se enrolla solamente una vez"
+msgstr "El número máximo de insns en un bucle pelado que se enrolla solamente una vez."
#: params.def:333
-#, fuzzy, no-c-format
-#| msgid "The maximum depth of a loop nest we completely peel"
+#, no-c-format
msgid "The maximum depth of a loop nest we completely peel."
-msgstr "La profundidad máxima de un bucle anidado que nosotros pelamos completamente"
+msgstr "La profundidad máxima de un bucle anidado que nosotros pelamos completamente."
#: params.def:339
-#, fuzzy, no-c-format
-#| msgid "The maximum number of insns of an unswitched loop"
+#, no-c-format
msgid "The maximum number of insns of an unswitched loop."
-msgstr "El número máximo de insns en un bucle sin switch"
+msgstr "El número máximo de insns en un bucle sin switch."
#: params.def:344
-#, fuzzy, no-c-format
-#| msgid "The maximum number of unswitchings in a single loop"
+#, no-c-format
msgid "The maximum number of unswitchings in a single loop."
-msgstr "El número máximo de eliminación de opciones en un solo bucle"
+msgstr "El número máximo de eliminación de opciones en un solo bucle."
#: params.def:351
-#, fuzzy, no-c-format
-#| msgid "Bound on the number of iterations the brute force # of iterations analysis algorithm evaluates"
+#, no-c-format
msgid "Bound on the number of iterations the brute force # of iterations analysis algorithm evaluates."
-msgstr "Límite en el número de iteraciones que evalúa el algoritmo de análisis de # de iteraciones de fuerza bruta"
+msgstr "Límite en el número de iteraciones que evalúa el algoritmo de análisis de número de iteraciones de fuerza bruta."
#: params.def:357
-#, fuzzy, no-c-format
-#| msgid "Bound on the cost of an expression to compute the number of iterations"
+#, no-c-format
msgid "Bound on the cost of an expression to compute the number of iterations."
-msgstr "Límite en el costo de una expresión para computar el número de iteraciones"
+msgstr "Límite en el coste de una expresión para calcular el número de iteraciones."
#: params.def:363
-#, fuzzy, no-c-format
-#| msgid "A factor for tuning the upper bound that swing modulo scheduler uses for scheduling a loop"
+#, no-c-format
msgid "A factor for tuning the upper bound that swing modulo scheduler uses for scheduling a loop."
-msgstr "Un factor para ajustar el límite superior que el calendarizador de cambio de módulo utiliza para calendarizar un bucle"
+msgstr "Factor para ajustar el límite superior que el planificador de cambio de módulo utiliza para planificar un bucle."
#: params.def:368
#, no-c-format
msgid "The minimum value of stage count that swing modulo scheduler will generate."
-msgstr "El valor mínimo de la cuenta de etapa que el calendarizador módulo swing generará."
+msgstr "El valor mínimo de la cuenta de etapa que el planificador módulo swing generará."
#: params.def:372
-#, fuzzy, no-c-format
-#| msgid "The number of cycles the swing modulo scheduler considers when checking conflicts using DFA"
+#, no-c-format
msgid "The number of cycles the swing modulo scheduler considers when checking conflicts using DFA."
-msgstr "El número de ciclos que el calendarizador de cambio de módulo considera al revisar conflictos utilizando DFA"
+msgstr "El número de ciclos que el planificador de cambio de módulo considera al revisar conflictos utilizando DFA."
#: params.def:376
-#, fuzzy, no-c-format
-#| msgid "A threshold on the average loop count considered by the swing modulo scheduler"
+#, no-c-format
msgid "A threshold on the average loop count considered by the swing modulo scheduler."
-msgstr "Un intervalo en la cuenta promedio de bucles considerado por el calendarizador de cambio de módulo"
+msgstr "Umbral en el número promedio de bucles considerado por el planificador de cambio de módulo."
#: params.def:381
#, no-c-format
msgid "A basic block profile count is considered hot if it contributes to the given permillage of the entire profiled execution."
-msgstr ""
+msgstr "El número de perfiles de bloque básicos se considera caliente si contribuye al pormillaje dado de la ejecución perfilada completa."
#: params.def:386
-#, fuzzy, no-c-format
-#| msgid "Select fraction of the maximal frequency of executions of basic block in function given basic block needs to have to be considered hot"
+#, no-c-format
msgid "Select fraction of the maximal frequency of executions of basic block in function given basic block needs to have to be considered hot."
-msgstr "La selección de fracción de la frecuencia maximal de ejecuciones de bloque básico en el bloque básico de función dado que necesita para ser considerado caliente"
+msgstr "La selección de fracción de la frecuencia máxima de ejecuciones de bloque básico en la función dada que el bloque básico necesita para ser considerado caliente."
#: params.def:391
#, no-c-format
msgid "The minimum fraction of profile runs a given basic block execution count must be not to be considered unlikely."
-msgstr ""
+msgstr "Fracción mínima de ejecuciones de perfil que el número de ejecuciones de un bloque básico dado no debe alcanzar para ser considerado improbable."
#: params.def:396
-#, fuzzy, no-c-format
-#| msgid "Select fraction of the maximal frequency of executions of basic block in function given basic block get alignment"
+#, no-c-format
msgid "Select fraction of the maximal frequency of executions of basic block in function given basic block get alignment."
-msgstr "La selección de fracción de la frecuencia maximal de ejecuciones de bloque básico en el bloque básico de función para alinear"
+msgstr "Selección de fracción de la frecuencia máxima de ejecuciones de bloque básico en la función dada para la que el bloque básico consigue alinear."
#: params.def:401
-#, fuzzy, no-c-format
-#| msgid "Loops iterating at least selected number of iterations will get loop alignement."
+#, no-c-format
msgid "Loops iterating at least selected number of iterations will get loop alignement.."
msgstr "Iterar ciclos por lo menos el número seleccionado de iteraciones que logrará alineación de bucles."
#: params.def:417
-#, fuzzy, no-c-format
-#| msgid "The maximum number of loop iterations we predict statically"
+#, no-c-format
msgid "The maximum number of loop iterations we predict statically."
-msgstr "El número máximo de iteraciones de bucle que se predicen estáticamente"
+msgstr "El número máximo de iteraciones de bucle que se predicen estáticamente."
#: params.def:430
#, no-c-format
msgid "Set the estimated probability in percentage for builtin expect. The default value is 90% probability."
-msgstr ""
+msgstr "Establece la probabilidad estimada en porcentaje de la expectativa incorporada. El valor predeterminado es 90% de probabilidad."
#: params.def:434
-#, fuzzy, no-c-format
-#| msgid "The percentage of function, weighted by execution frequency, that must be covered by trace formation. Used when profile feedback is available"
+#, no-c-format
msgid "The percentage of function, weighted by execution frequency, that must be covered by trace formation. Used when profile feedback is available."
-msgstr "El porcentaje de la función, evaluado por la frecuencia de ejecución, que debe ser cubierto por la información de rastreo. Se utiliza cuando está disponible la retroalimentación del análisis de perfil"
+msgstr "El porcentaje de la función, ponderado por la frecuencia de ejecución, que debe ser cubierto por la información de rastreo. Se utiliza cuando está disponible la retroalimentación del análisis de perfil."
#: params.def:438
-#, fuzzy, no-c-format
-#| msgid "The percentage of function, weighted by execution frequency, that must be covered by trace formation. Used when profile feedback is not available"
+#, no-c-format
msgid "The percentage of function, weighted by execution frequency, that must be covered by trace formation. Used when profile feedback is not available."
-msgstr "El porcentaje de la función, evaluado por la frecuencia de ejecución, que debe ser cubierto por la información de rastreo. Se utiliza cuando la retroalimentación de análisis de perfil no está disponible"
+msgstr "El porcentaje de la función, ponderado por la frecuencia de ejecución, que debe ser cubierto por la información de rastreo. Se utiliza cuando la retroalimentación de análisis de perfil no está disponible."
#: params.def:442
-#, fuzzy, no-c-format
-#| msgid "Maximal code growth caused by tail duplication (in percent)"
+#, no-c-format
msgid "Maximal code growth caused by tail duplication (in percent)."
-msgstr "Crecimiento de código maximal causado por duplicación de colas (en porcentaje)"
+msgstr "Máximo crecimiento de código causado por duplicación de colas (en porcentaje)."
#: params.def:446
-#, fuzzy, no-c-format
-#| msgid "Stop reverse growth if the reverse probability of best edge is less than this threshold (in percent)"
+#, no-c-format
msgid "Stop reverse growth if the reverse probability of best edge is less than this threshold (in percent)."
-msgstr "Detener el crecimiento inverso si la probabilidad reversa del mejor borde es menor a este intervalo (en porcentaje)"
+msgstr "Detener el crecimiento inverso si la probabilidad inversa del mejor borde es menor que este umbral (en porcentaje)."
#: params.def:450
-#, fuzzy, no-c-format
-#| msgid "Stop forward growth if the probability of best edge is less than this threshold (in percent). Used when profile feedback is available"
+#, no-c-format
msgid "Stop forward growth if the probability of best edge is less than this threshold (in percent). Used when profile feedback is available."
-msgstr "Detener el crecimiento hacia adelante si la probabilidad del mejor borde es menor que este intervalo (en porcentaje). Se utiliza cuando la retroalimentación de análisis de perfil está disponible"
+msgstr "Detener el crecimiento hacia adelante si la probabilidad del mejor borde es menor que este umbral (en porcentaje). Se utiliza cuando la retroalimentación de análisis de perfil está disponible."
#: params.def:454
-#, fuzzy, no-c-format
-#| msgid "Stop forward growth if the probability of best edge is less than this threshold (in percent). Used when profile feedback is not available"
+#, no-c-format
msgid "Stop forward growth if the probability of best edge is less than this threshold (in percent). Used when profile feedback is not available."
-msgstr "Detener el crecimiento hacia adelante si la probabilidad del mejor borde es menor a este intervalo (en porcentaje). Se utiliza cuando la retroalimentación de análisis de perfil no está disponible"
+msgstr "Detener el crecimiento hacia adelante si la probabilidad del mejor borde es menor que este umbral (en porcentaje). Se utiliza cuando la retroalimentación de análisis de perfil no está disponible."
#: params.def:460
-#, fuzzy, no-c-format
-#| msgid "The maximum number of incoming edges to consider for crossjumping"
+#, no-c-format
msgid "The maximum number of incoming edges to consider for crossjumping."
-msgstr "El número máximo de bordes de entrada para considerar el salto cruzado"
+msgstr "El número máximo de bordes entrantes para considerar el salto cruzado."
#: params.def:466
-#, fuzzy, no-c-format
-#| msgid "The minimum number of matching instructions to consider for crossjumping"
+#, no-c-format
msgid "The minimum number of matching instructions to consider for crossjumping."
-msgstr "El número máximo de instrucciones coincidentes para considerar el salto cruzado"
+msgstr "El número máximo de instrucciones coincidentes para considerar el salto cruzado."
#: params.def:472
-#, fuzzy, no-c-format
-#| msgid "The maximum expansion factor when copying basic blocks"
+#, no-c-format
msgid "The maximum expansion factor when copying basic blocks."
-msgstr "El factor de expansión máximo al copiar bloques básicos"
+msgstr "El factor de expansión máximo al copiar bloques básicos."
# 'desfactorizar' no me gusta. ¿Alguna sugerencia? - cfuga
#: params.def:478
-#, fuzzy, no-c-format
-#| msgid "The maximum number of insns to duplicate when unfactoring computed gotos"
+#, no-c-format
msgid "The maximum number of insns to duplicate when unfactoring computed gotos."
-msgstr "El número máximo de insns a duplicar al desfactorizar gotos calculados"
+msgstr "El número máximo de insns a duplicar al desfactorizar gotos calculados."
#: params.def:484
-#, fuzzy, no-c-format
-#| msgid "The maximum length of path considered in cse"
+#, no-c-format
msgid "The maximum length of path considered in cse."
-msgstr "La longitud máxima de la ruta considerada en cse"
+msgstr "La longitud máxima de la ruta considerada en cse."
#: params.def:488
-#, fuzzy, no-c-format
-#| msgid "The maximum instructions CSE process before flushing"
+#, no-c-format
msgid "The maximum instructions CSE process before flushing."
-msgstr "El número máximo de instrucciones que CSE procesa antes de descargar"
+msgstr "El número máximo de instrucciones que CSE procesa antes de descargar."
#: params.def:495
-#, fuzzy, no-c-format
-#| msgid "The minimum cost of an expensive expression in the loop invariant motion"
+#, no-c-format
msgid "The minimum cost of an expensive expression in the loop invariant motion."
-msgstr "El costo mínimo de una expresión costosa en el movimiento invariante del bucle"
+msgstr "El coste mínimo de una expresión costosa en el movimiento invariante del bucle."
#: params.def:504
-#, fuzzy, no-c-format
-#| msgid "Bound on number of candidates below that all candidates are considered in iv optimizations"
+#, no-c-format
msgid "Bound on number of candidates below that all candidates are considered in iv optimizations."
-msgstr "Límite en el número de candidatos bajo el cual todos los candidatos se consideran en optimizaciones iv"
+msgstr "Límite en el número de candidatos bajo el cual todos los candidatos se consideran en optimizaciones iv."
#: params.def:512
-#, fuzzy, no-c-format
-#| msgid "Bound on number of iv uses in loop optimized in iv optimizations"
+#, no-c-format
msgid "Bound on number of iv uses in loop optimized in iv optimizations."
-msgstr "Límite en el número de usos de iv en bucles optimizados en optimizaciones iv"
+msgstr "Límite en el número de usos de iv en bucles optimizados en optimizaciones iv."
#: params.def:520
-#, fuzzy, no-c-format
-#| msgid "If number of candidates in the set is smaller, we always try to remove unused ivs during its optimization"
+#, no-c-format
msgid "If number of candidates in the set is smaller, we always try to remove unused ivs during its optimization."
-msgstr "Si el número de candidatos en el conjunto es menor, siempre se tratará de eliminar ivs sin usar durante su optimización"
+msgstr "Si el número de candidatos en el conjunto es menor, siempre se tratará de eliminar los ivs sin usar durante su optimización."
#: params.def:525
-#, fuzzy, no-c-format
-#| msgid "Bound on size of expressions used in the scalar evolutions analyzer"
+#, no-c-format
msgid "Bound on size of expressions used in the scalar evolutions analyzer."
-msgstr "Límite en el tamaño de expresiones usadas en el analizador escalar de evoluciones"
+msgstr "Límite en el tamaño de expresiones usadas en el analizador escalar de evoluciones."
#: params.def:530
-#, fuzzy, no-c-format
-#| msgid "Bound on the complexity of the expressions in the scalar evolutions analyzer"
+#, no-c-format
msgid "Bound on the complexity of the expressions in the scalar evolutions analyzer."
-msgstr "Límite en la complejidad de expresiones en el analizador escalar de evoluciones"
+msgstr "Límite en la complejidad de expresiones en el analizador escalar de evoluciones."
#: params.def:535
-#, fuzzy, no-c-format
-#| msgid "Bound on number of runtime checks inserted by the vectorizer's loop versioning for alignment check"
+#, no-c-format
msgid "Bound on number of runtime checks inserted by the vectorizer's loop versioning for alignment check."
-msgstr "Límite en el número de revisiones de tiempo de ejecución insertadas por las versiones de bucle del vectorizador para revisión de alineación"
+msgstr "Límite en el número de revisiones de tiempo de ejecución insertadas por las versiones de bucle del vectorizador para revisión de alineación."
#: params.def:540
-#, fuzzy, no-c-format
-#| msgid "Bound on number of runtime checks inserted by the vectorizer's loop versioning for alias check"
+#, no-c-format
msgid "Bound on number of runtime checks inserted by the vectorizer's loop versioning for alias check."
-msgstr "Límite en el número de revisiones de tiempo de ejecución insertadas por las versiones de bucle del vectorizador para revisión de alias"
+msgstr "Límite en el número de revisiones de tiempo de ejecución insertadas por las versiones de bucle del vectorizador para revisión de alias."
#: params.def:545
#, no-c-format
msgid "Max number of loop peels to enhancement alignment of data references in a loop."
-msgstr ""
+msgstr "Número máximo de pelados de bucle para alineación de mejora de las referencias de datos en un bucle."
#: params.def:550
-#, fuzzy, no-c-format
-#| msgid "The maximum memory locations recorded by cselib"
+#, no-c-format
msgid "The maximum memory locations recorded by cselib."
-msgstr "El número máximo de ubicaciones grabadas por cselib"
+msgstr "El número máximo de ubicaciones grabadas por cselib."
#: params.def:563
-#, fuzzy, no-c-format
-#| msgid "Minimum heap expansion to trigger garbage collection, as a percentage of the total size of the heap"
+#, no-c-format
msgid "Minimum heap expansion to trigger garbage collection, as a percentage of the total size of the heap."
-msgstr "Expansión mínima de la pila para iniciar la recolección de basura, como un porcentaje del tamaño total de la pila"
+msgstr "Expansión mínima de la pila para iniciar la recolección de basura, como un porcentaje del tamaño total de la pila."
#: params.def:568
-#, fuzzy, no-c-format
-#| msgid "Minimum heap size before we start collecting garbage, in kilobytes"
+#, no-c-format
msgid "Minimum heap size before we start collecting garbage, in kilobytes."
-msgstr "Tamaño mínimo de la pila antes de comenzar a recolectar basura, en kilobytes"
+msgstr "Tamaño mínimo de la pila antes de comenzar a recolectar basura, en kilobytes."
#: params.def:576
-#, fuzzy, no-c-format
-#| msgid "The maximum number of instructions to search backward when looking for equivalent reload"
+#, no-c-format
msgid "The maximum number of instructions to search backward when looking for equivalent reload."
-msgstr "El número máximo de instrucciones para buscar hacia atrás al buscar por una recarga equivalente"
+msgstr "El número máximo de instrucciones para buscar hacia atrás al buscar por una recarga equivalente."
#: params.def:581
-#, fuzzy, no-c-format
-#| msgid "Target block's relative execution frequency (as a percentage) required to sink a statement"
+#, no-c-format
msgid "Target block's relative execution frequency (as a percentage) required to sink a statement."
-msgstr "Frecuencia de ejecución relativa al bloque objetivo (como un porcentaje) requerida para hundir una declaración"
+msgstr "Frecuencia de ejecución relativa al bloque objetivo (como un porcentaje) requerida para hundir una declaración."
#: params.def:586 params.def:596
-#, fuzzy, no-c-format
-#| msgid "The maximum number of blocks in a region to be considered for interblock scheduling"
+#, no-c-format
msgid "The maximum number of blocks in a region to be considered for interblock scheduling."
-msgstr "El número máximo de bloques en una región para ser considerada para interbloqueo"
+msgstr "El número máximo de bloques en una región para ser considerada para planificación de interbloqueo."
#: params.def:591 params.def:601
-#, fuzzy, no-c-format
-#| msgid "The maximum number of insns in a region to be considered for interblock scheduling"
+#, no-c-format
msgid "The maximum number of insns in a region to be considered for interblock scheduling."
-msgstr "El número máximo de insns en una región para ser consideradas para calendarización de interbloqueo"
+msgstr "El número máximo de insns en una región para ser consideradas para planificación de interbloqueo"
#: params.def:606
-#, fuzzy, no-c-format
-#| msgid "The minimum probability of reaching a source block for interblock speculative scheduling"
+#, no-c-format
msgid "The minimum probability of reaching a source block for interblock speculative scheduling."
-msgstr "La probabilidad mínima de alcanzar un bloque fuente para la calendarización especulativa entre bloques"
+msgstr "La probabilidad mínima de alcanzar un bloque fuente para la planificación especulativa entre bloques."
#: params.def:611
-#, fuzzy, no-c-format
-#| msgid "The maximum number of iterations through CFG to extend regions"
+#, no-c-format
msgid "The maximum number of iterations through CFG to extend regions."
-msgstr "El número máximo de iteraciones a través de CFG para extender regiones"
+msgstr "El número máximo de iteraciones a través de CFG para extender regiones."
#: params.def:616
-#, fuzzy, no-c-format
-#| msgid "The maximum conflict delay for an insn to be considered for speculative motion"
+#, no-c-format
msgid "The maximum conflict delay for an insn to be considered for speculative motion."
-msgstr "El retraso de conflicto máximo para una insn para ser considerada para movimiento especulativo"
+msgstr "El retraso máximo de conflicto para que una insn sea considerada para movimiento especulativo."
#: params.def:621
#, no-c-format
msgid "The minimal probability of speculation success (in percents), so that speculative insn will be scheduled."
msgstr "La probabilidad mínima de éxito de especulación (en porcentaje), para que esa insn especulativa se calendarize."
+# TODO Mejorar traducción de 'across it'.
#: params.def:626
#, no-c-format
msgid "The minimum probability an edge must have for the scheduler to save its state across it."
-msgstr ""
+msgstr "Probabilidad mínima que debe tener un borde para que el planificador guarde su estado a través de él."
#: params.def:631
-#, fuzzy, no-c-format
-#| msgid "The maximum size of the lookahead window of selective scheduling"
+#, no-c-format
msgid "The maximum size of the lookahead window of selective scheduling."
-msgstr "El tamaño máximo de la ventana de búsqueda hacia adelante de la calendarización selectiva"
+msgstr "El tamaño máximo de la ventana de búsqueda hacia adelante de la planificación selectiva."
#: params.def:636
-#, fuzzy, no-c-format
-#| msgid "Maximum number of times that an insn could be scheduled"
+#, no-c-format
msgid "Maximum number of times that an insn could be scheduled."
-msgstr "El número máximo de veces que se puede calendarizar una insns"
+msgstr "El número máximo de veces que se puede planificar una insns."
#: params.def:641
-#, fuzzy, no-c-format
-#| msgid "Maximum number of instructions in the ready list that are considered eligible for renaming"
+#, no-c-format
msgid "Maximum number of instructions in the ready list that are considered eligible for renaming."
-msgstr "El número máximo de instrucciones en la lista ready que se consideran elegibles para renombrado"
+msgstr "El número máximo de instrucciones en la lista ready que se consideran elegibles para renombrado."
#: params.def:646
-#, fuzzy, no-c-format
-#| msgid "Minimal distance between possibly conflicting store and load"
+#, no-c-format
msgid "Minimal distance between possibly conflicting store and load."
-msgstr "La distancia mínima entre store y load en posible conflicto"
+msgstr "La distancia mínima entre store y load en posible conflicto."
#: params.def:651
#, no-c-format
msgid "Hardware autoprefetcher scheduler model control flag. Number of lookahead cycles the model looks into; at '0' only enable instruction sorting heuristic. Disabled by default."
-msgstr ""
+msgstr "Indicador de control del modelo de planificador de prebuscador automático hardware. Número de ciclos hacia delante que el modelo examina: con '0' solo se activa la heurística de ordenación de instrucciones. Desactivado de forma predeterminada."
#: params.def:656
-#, fuzzy, no-c-format
-#| msgid "The maximum number of RTL nodes that can be recorded as combiner's last value"
+#, no-c-format
msgid "The maximum number of RTL nodes that can be recorded as combiner's last value."
-msgstr "El número máximo de nodos RTL que se pueden grabar como el último valor del combinador"
+msgstr "El número máximo de nodos RTL que se pueden grabar como el último valor del combinador."
#: params.def:661
-#, fuzzy, no-c-format
-#| msgid "The maximum number of incoming edges to consider for crossjumping"
+#, no-c-format
msgid "The maximum number of insns combine tries to combine."
-msgstr "El número máximo de bordes de entrada para considerar el salto cruzado"
+msgstr "El número máximo de intentos de combinar insns para combinar."
#: params.def:670
-#, fuzzy, no-c-format
-#| msgid "The upper bound for sharing integer constants"
+#, no-c-format
msgid "The upper bound for sharing integer constants."
-msgstr "El límite superior para compartir constantes enteras"
+msgstr "El límite superior para compartir constantes enteras."
#: params.def:675
-#, fuzzy, no-c-format
-#| msgid "The lower bound for a buffer to be considered for stack smashing protection"
+#, no-c-format
msgid "The lower bound for a buffer to be considered for stack smashing protection."
-msgstr "El límite inferior para considerar un almacenamiento temporal para protección contra destrucción de pila"
+msgstr "El límite inferior para considerar un almacenamiento temporal para protección contra destrucción de pila."
#: params.def:680
#, no-c-format
msgid "The minimum size of variables taking part in stack slot sharing when not optimizing."
-msgstr ""
+msgstr "Tamaño mínimo de las variables que participan en la compartición de ranuras de pila cuando no hay optimización."
#: params.def:699
-#, fuzzy, no-c-format
-#| msgid "Maximum number of statements allowed in a block that needs to be duplicated when threading jumps"
+#, no-c-format
msgid "Maximum number of statements allowed in a block that needs to be duplicated when threading jumps."
-msgstr "Número máximo de sentencias permitidas en un bloque que necesitan ser duplicadas al hacer hilos de saltos"
+msgstr "Número máximo de sentencias permitidas en un bloque que necesitan ser duplicadas al hacer hilos de saltos."
#: params.def:708
-#, fuzzy, no-c-format
-#| msgid "Maximum number of fields in a structure before pointer analysis treats the structure as a single variable"
+#, no-c-format
msgid "Maximum number of fields in a structure before pointer analysis treats the structure as a single variable."
-msgstr "El número máximo de campos en una estructura antes de que el análisis de punteros trate a la estructura como una sola variable"
+msgstr "El número máximo de campos en una estructura antes de que el análisis de punteros trate a la estructura como una sola variable."
#: params.def:713
-#, fuzzy, no-c-format
-#| msgid "The maximum number of instructions ready to be issued to be considered by the scheduler during the first scheduling pass"
+#, no-c-format
msgid "The maximum number of instructions ready to be issued to be considered by the scheduler during the first scheduling pass."
-msgstr "El número máximo de instrucciones listas para ser ejecutadas para ser consideradas por el calendarizador durante el primer paso de calendarización"
+msgstr "El número máximo de instrucciones listas para ser ejecutadas que el planificador tendrá en cuenta durante el primer paso de planificación."
#: params.def:719
-#, fuzzy, no-c-format
-#| msgid "Maximum number of active local stores in RTL dead store elimination"
+#, no-c-format
msgid "Maximum number of active local stores in RTL dead store elimination."
-msgstr "Número máximo de almacenamientos locales activos en la eliminación de almacenamiento muerto RTL"
+msgstr "Número máximo de almacenamientos locales activos en la eliminación de almacenamiento muerto RTL."
#: params.def:729
-#, fuzzy, no-c-format
-#| msgid "The number of insns executed before prefetch is completed"
+#, no-c-format
msgid "The number of insns executed before prefetch is completed."
-msgstr "El número de insns ejecutadas antes de completar la precarga"
+msgstr "El número de insns ejecutadas antes de completar la precarga."
#: params.def:736
-#, fuzzy, no-c-format
-#| msgid "The number of prefetches that can run at the same time"
+#, no-c-format
msgid "The number of prefetches that can run at the same time."
-msgstr "El número de precargas que se pueden ejecutar simultánamente"
+msgstr "El número de precargas que se pueden ejecutar simultánamente."
#: params.def:743
-#, fuzzy, no-c-format
-#| msgid "The size of L1 cache"
+#, no-c-format
msgid "The size of L1 cache."
-msgstr "El tamaño del caché L1"
+msgstr "El tamaño del caché L1i."
#: params.def:750
-#, fuzzy, no-c-format
-#| msgid "The size of L1 cache line"
+#, no-c-format
msgid "The size of L1 cache line."
-msgstr "El tamaño de la línea del caché L1"
+msgstr "El tamaño de la línea del caché L1."
#: params.def:757
-#, fuzzy, no-c-format
-#| msgid "The size of L2 cache"
+#, no-c-format
msgid "The size of L2 cache."
-msgstr "El tamaño del caché L2"
+msgstr "El tamaño del caché L2."
#: params.def:768
-#, fuzzy, no-c-format
-#| msgid "Whether to use canonical types"
+#, no-c-format
msgid "Whether to use canonical types."
-msgstr "Decide si se usan tipos canónicos"
+msgstr "Decide si se usan tipos canónicos."
#: params.def:773
-#, fuzzy, no-c-format
-#| msgid "Maximum length of partial antic set when performing tree pre optimization"
+#, no-c-format
msgid "Maximum length of partial antic set when performing tree pre optimization."
-msgstr "Longitud máxima del conjunto antic parcial al realizar pre optimización de árbol"
+msgstr "Longitud máxima del conjunto antic parcial al realizar pre optimización de árbol."
#: params.def:783
-#, fuzzy, no-c-format
-#| msgid "Maximum size of a SCC before SCCVN stops processing a function"
+#, no-c-format
msgid "Maximum size of a SCC before SCCVN stops processing a function."
-msgstr "Tamaño máxmo de un SCC antes de que SCCVN detenga el procesamiento de una función"
+msgstr "Tamaño máxmo de un SCC antes de que SCCVN detenga el procesamiento de una función."
#: params.def:794
#, no-c-format
msgid "Maximum number of disambiguations to perform per memory access."
-msgstr ""
+msgstr "Número máximo de desambiguaciones que realizar por cada acceso a memoria."
#: params.def:799
-#, fuzzy, no-c-format
-#| msgid "Max loops number for regional RA"
+#, no-c-format
msgid "Max loops number for regional RA."
-msgstr "Número de bucles máximo para el RA regional"
+msgstr "Número de bucles máximo para el RA regional."
#: params.def:804
-#, fuzzy, no-c-format
-#| msgid "Max size of conflict table in MB"
+#, no-c-format
msgid "Max size of conflict table in MB."
-msgstr "Tamaño máximo de la tabla de conflictos en MB"
+msgstr "Tamaño máximo de la tabla de conflictos en MB."
#: params.def:809
-#, fuzzy, no-c-format
-#| msgid "The number of registers in each class kept unused by loop invariant motion"
+#, no-c-format
msgid "The number of registers in each class kept unused by loop invariant motion."
-msgstr "El número de registros conservados sin uso en cada clase por el movimiento invariante del bucle"
+msgstr "El número de registros conservados sin uso en cada clase por el movimiento invariante del bucle."
#: params.def:814
#, no-c-format
msgid "The max number of reload pseudos which are considered during spilling a non-reload pseudo."
-msgstr ""
+msgstr "El número máximo de pseudos de recarga que se tienen en cuenta durante el vaciado de pseudos de no recarga."
#: params.def:819
#, no-c-format
@@ -2408,63 +2310,54 @@ msgid "Minimal fall-through edge probability in percentage used to add BB to inh
msgstr ""
#: params.def:827
-#, fuzzy, no-c-format
-#| msgid "The maximum ratio between array size and switch branches for a switch conversion to take place"
+#, no-c-format
msgid "The maximum ratio between array size and switch branches for a switch conversion to take place."
-msgstr "La tasa máxima entre el tamaño de la matriz y las ramificaciones switch para que tome lugar una conversión switch"
+msgstr "La tasa máxima entre el tamaño de la matriz y las ramificaciones switch para que tenga lugar una conversión switch."
#: params.def:835
-#, fuzzy, no-c-format
-#| msgid "size of tiles for loop blocking"
+#, no-c-format
msgid "size of tiles for loop blocking."
-msgstr "tamaño de bloques para el bloqueo de bucles"
+msgstr "tamaño de bloques para el bloqueo de bucles."
#: params.def:842
-#, fuzzy, no-c-format
-#| msgid "maximum number of parameters in a SCoP"
+#, no-c-format
msgid "maximum number of parameters in a SCoP."
-msgstr "número máximo de parámetros en un SCoP"
+msgstr "número máximo de parámetros en un SCoP."
#: params.def:849
-#, fuzzy, no-c-format
-#| msgid "maximum number of basic blocks per function to be analyzed by Graphite"
+#, no-c-format
msgid "maximum number of basic blocks per function to be analyzed by Graphite."
-msgstr "número máximo de bloques básicos por función para analizar con Graphite"
+msgstr "número máximo de bloques básicos por función para analizar con Graphite."
#: params.def:856
-#, fuzzy, no-c-format
-#| msgid "maximum number of parameters in a SCoP"
+#, no-c-format
msgid "maximum number of arrays per scop."
-msgstr "número máximo de parámetros en un SCoP"
+msgstr "número máximo de arrays por scop."
#: params.def:863
-#, fuzzy, no-c-format
-#| msgid "maximum number of basic blocks per function to be analyzed by Graphite"
+#, no-c-format
msgid "minimal number of loops per function to be analyzed by Graphite."
-msgstr "número máximo de bloques básicos por función para analizar con Graphite"
+msgstr "número mínimo de bucles por función para analizar con Graphite."
#: params.def:868
-#, fuzzy, no-c-format
-#| msgid "The maximum number of insns of an unswitched loop"
+#, no-c-format
msgid "maximum number of isl operations, 0 means unlimited"
-msgstr "El número máximo de insns en un bucle sin switch"
+msgstr "número máximo de operaciones isl; 0 significa que no hay límite"
#: params.def:874
-#, fuzzy, no-c-format
-#| msgid "Maximum number of datarefs in loop for building loop data dependencies"
+#, no-c-format
msgid "Maximum number of datarefs in loop for building loop data dependencies."
-msgstr "Número máximo de referencia de datos en bucles para construir dependencia de datos de bucles"
+msgstr "Número máximo de referencia de datos en bucles para construir dependencias de datos de bucles."
#: params.def:881
-#, fuzzy, no-c-format
-#| msgid "Max basic blocks number in loop for loop invariant motion"
+#, no-c-format
msgid "Max basic blocks number in loop for loop invariant motion."
-msgstr "Número máximo de bloques básicos en el bucle para el movimiento invariante de bucle"
+msgstr "Número máximo de bloques básicos en bucles para movimiento invariante de bucle."
#: params.def:889
#, no-c-format
msgid "use internal function id in profile lookup."
-msgstr ""
+msgstr "utilizar id de función interno en búsqueda de perfil."
#: params.def:897
#, no-c-format
@@ -2472,179 +2365,159 @@ msgid "track topn target addresses in indirect-call profile."
msgstr ""
#: params.def:903
-#, fuzzy, no-c-format
-#| msgid "Maximum number of instructions in basic block to be considered for SLP vectorization"
+#, no-c-format
msgid "Maximum number of instructions in basic block to be considered for SLP vectorization."
-msgstr "El número máximo de instrucciones en bloque básico que se consideran para vectorización SLP"
+msgstr "El número máximo de instrucciones en bloque básico que se consideran para vectorización SLP."
#: params.def:908
-#, fuzzy, no-c-format
-#| msgid "Min. ratio of insns to prefetches to enable prefetching for a loop with an unknown trip count"
+#, no-c-format
msgid "Min. ratio of insns to prefetches to enable prefetching for a loop with an unknown trip count."
-msgstr "Tasa mínima de insns a precargar para activar la precarga para un bucle con una cuenta de viajes desconocida"
+msgstr "Tasa mínima de insns a precargar para activar la precarga para un bucle con una cuenta de viajes desconocida."
#: params.def:914
-#, fuzzy, no-c-format
-#| msgid "Min. ratio of insns to mem ops to enable prefetching in a loop"
+#, no-c-format
msgid "Min. ratio of insns to mem ops to enable prefetching in a loop."
-msgstr "Tasa mínima de insns a ops de mem para activar la precarga en un bucle"
+msgstr "Tasa mínima de insns a ops de mem para activar la precarga en un bucle."
#: params.def:921
-#, fuzzy, no-c-format
-#| msgid "Max. size of var tracking hash tables"
+#, no-c-format
msgid "Max. size of var tracking hash tables."
-msgstr "Tamaño máximo de las tablas de dispersión de rastreo de variables"
+msgstr "Tamaño máximo de las tablas de dispersión de rastreo de variables."
#: params.def:929
-#, fuzzy, no-c-format
-#| msgid "Max. recursion depth for expanding var tracking expressions"
+#, no-c-format
msgid "Max. recursion depth for expanding var tracking expressions."
-msgstr "Profundidad máxima de recursión para expandir expresiones de rastreo de variables"
+msgstr "Profundidad máxima de recursión para expandir expresiones de rastreo de variables."
#: params.def:937
#, no-c-format
msgid "Max. size of loc list for which reverse ops should be added."
-msgstr ""
+msgstr "Máximo tamaño de lista loc para que deban añadirse ops inversas."
#: params.def:944
-#, fuzzy, no-c-format
-#| msgid "The minimum UID to be used for a nondebug insn"
+#, no-c-format
msgid "The minimum UID to be used for a nondebug insn."
-msgstr "El UID mínimo a usar para una insn que no es de depuración"
+msgstr "El UID mínimo a usar para una insn que no es de depuración."
#: params.def:949
-#, fuzzy, no-c-format
-#| msgid "Maximum allowed growth of size of new parameters ipa-sra replaces a pointer to an aggregate with"
+#, no-c-format
msgid "Maximum allowed growth of size of new parameters ipa-sra replaces a pointer to an aggregate with."
-msgstr "El crecimiento máximo permitido de tamaño de los parámetros nuevos ipa-sra que reemplazan un puntero a un agregado con"
+msgstr "El crecimiento máximo permitido de tamaño de los parámetros nuevos ipa-sra que reemplazan un puntero a un agregado con."
#: params.def:955
-#, fuzzy, no-c-format
-#| msgid "Size in bytes after which thread-local aggregates should be instrumented with the logging functions instead of save/restore pairs"
+#, no-c-format
msgid "Size in bytes after which thread-local aggregates should be instrumented with the logging functions instead of save/restore pairs."
-msgstr "Tamaño en bytes después del cual los agregados thread-local se deben instrumentar con las funciones de registro en lugar de pares save/restore"
+msgstr "Tamaño en bytes después del cual los agregados thread-local se deben instrumentar con las funciones de registro en lugar de pares save/restore."
#: params.def:962
#, no-c-format
msgid "Maximum size, in storage units, of an aggregate which should be considered for scalarization when compiling for speed."
-msgstr ""
+msgstr "Máximo tamaño, en unidades de almacenamiento, de un agregado para tenerlo en cuenta en escalarización cuando se compila para velocidad."
#: params.def:968
#, no-c-format
msgid "Maximum size, in storage units, of an aggregate which should be considered for scalarization when compiling for size."
-msgstr ""
+msgstr "Máximo tamaño, en unidades de almacenamiento, de un agregado para tenerlo en cuenta en escalarización cuando se compila para tamaño."
#: params.def:974
-#, fuzzy, no-c-format
-#| msgid "Maximum size of a list of values associated with each parameter for interprocedural constant propagation"
+#, no-c-format
msgid "Maximum size of a list of values associated with each parameter for interprocedural constant propagation."
-msgstr "Tamaño máximo de una lista de valores asociada con cada parámetro para propagación constante entre procedimientos"
+msgstr "Tamaño máximo de una lista de valores asociada con cada parámetro para propagación constante entre procedimientos."
#: params.def:980
-#, fuzzy, no-c-format
-#| msgid "Threshold ipa-cp opportunity evaluation that is still considered beneficial to clone."
+#, no-c-format
msgid "Threshold ipa-cp opportunity evaluation that is still considered beneficial to clone.."
-msgstr "Rango de evaluación de oportunidad ipa-cp que aún se considera benéfico para clonar."
+msgstr "Rango de evaluación de oportunidad ipa-cp que aún se considera beneficioso para clonar.."
#: params.def:986
#, no-c-format
msgid "Percentage penalty the recursive functions will receive when they are evaluated for cloning.."
-msgstr ""
+msgstr "Penalización porcentual que recibirán las funciones recursivas cuando se evalúen para clonación.."
#: params.def:992
#, no-c-format
msgid "Percentage penalty functions containg a single call to another function will receive when they are evaluated for cloning.."
-msgstr ""
+msgstr "Penalización porcentual que recibirán las funciones que contien una sola llamada a otra función cuando se evalúen para clonación.."
#: params.def:998
#, no-c-format
msgid "Maximum number of aggregate content items for a parameter in jump functions and lattices."
-msgstr ""
+msgstr "Número máximo de elementos de contenido agregado de un parámetro en funciones de salto y celosías."
#: params.def:1004
#, no-c-format
msgid "Compile-time bonus IPA-CP assigns to candidates which make loop bounds or strides known.."
-msgstr ""
+msgstr "Bonificación de tiempo de compilación que IPA-CP asigna a los candidatos que dan a conocer los límites o los pasos de los bucles.."
#: params.def:1010
#, no-c-format
msgid "Compile-time bonus IPA-CP assigns to candidates which make an array index known.."
-msgstr ""
+msgstr "Bonificación de tiempo de compilación que IPA-CP asigna a los candidatos que dan conocer el índice de un array.."
#: params.def:1016
#, no-c-format
msgid "Maximum number of statements that will be visited by IPA formal parameter analysis based on alias analysis in any given function."
-msgstr ""
+msgstr "Número máximo de sentencias que visitará el análisis de parámetros formales de IPA basado en el análisis de alias de una función dada."
#: params.def:1024
-#, fuzzy, no-c-format
-#| msgid "Number of partitions the program should be split to"
+#, no-c-format
msgid "Number of partitions the program should be split to."
-msgstr "Número de particiones en las que se debe dividir el programa"
+msgstr "Número de particiones en las que se debe dividir el programa."
#: params.def:1029
-#, fuzzy, no-c-format
-#| msgid "Minimal size of a partition for LTO (in estimated instructions)"
+#, no-c-format
msgid "Minimal size of a partition for LTO (in estimated instructions)."
-msgstr "Tamaño minimal de una partición para LTO (en instrucciones estimadas)"
+msgstr "Tamaño minimal de una partición para LTO (en instrucciones estimadas)."
#: params.def:1036
-#, fuzzy, no-c-format
-#| msgid "Maximum number of namespaces to search for alternatives when name lookup fails"
+#, no-c-format
msgid "Maximum number of namespaces to search for alternatives when name lookup fails."
-msgstr "Número máximo de espacios de nombres a buscar por alternativas cuando falla la búsqueda de nombre"
+msgstr "Número máximo de espacios de nombres a buscar por alternativas cuando falla la búsqueda de nombre."
#: params.def:1043
-#, fuzzy, no-c-format
-#| msgid "Maximum number of conditional store pairs that can be sunk"
+#, no-c-format
msgid "Maximum number of conditional store pairs that can be sunk."
-msgstr "El número máximo de pares de almacenamiento condicional que se pueden hundir"
+msgstr "Número máximo de pares de almacenamiento condicional que se pueden hundir."
#: params.def:1051
-#, fuzzy, no-c-format
-#| msgid "The smallest number of different values for which it is best to use a jump-table instead of a tree of conditional branches, if 0, use the default for the machine"
+#, no-c-format
msgid "The smallest number of different values for which it is best to use a jump-table instead of a tree of conditional branches, if 0, use the default for the machine."
-msgstr "El número más pequeño de valores diferentes para los cuales es mejor usar una tabla-salto en lugar de un árbol de ramificaciones condicionales; si es 0, usa el valor por defecto para la máquina"
+msgstr "El número más pequeño de valores diferentes para los cuales es mejor usar una tabla-salto en lugar de un árbol de ramificaciones condicionales; si es 0, usa el valor por defecto para la máquina."
#: params.def:1059
-#, fuzzy, no-c-format
-#| msgid "Allow new data races on stores to be introduced"
+#, no-c-format
msgid "Allow new data races on stores to be introduced."
-msgstr "Permite que se introduzcan carreras de datos nuevos en stores"
+msgstr "Permite que se introduzcan carreras de datos nuevos en stores."
#: params.def:1065
-#, fuzzy, no-c-format
-#| msgid "Set the maximum number of instructions executed in parallel in reassociated tree. If 0, use the target dependent heuristic."
+#, no-c-format
msgid "Set the maximum number of instructions executed in parallel in reassociated tree. If 0, use the target dependent heuristic.."
-msgstr "Establece el número máximo de instrucciones ejecutadas en paralelo en el árbol de reasociación. Si es 0, usa la heurística dependiente del objetivo."
+msgstr "Establece el número máximo de instrucciones ejecutadas en paralelo en el árbol de reasociación. Si es 0, usa la heurística dependiente del objetivo.."
#: params.def:1071
-#, fuzzy, no-c-format
-#| msgid "Maximum amount of similar bbs to compare a bb with"
+#, no-c-format
msgid "Maximum amount of similar bbs to compare a bb with."
-msgstr "Cantidad máxima de bbs similares con las cuales comparar un bb"
+msgstr "Cantidad máxima de bbs similares con las cuales comparar un bb."
#: params.def:1076
-#, fuzzy, no-c-format
-#| msgid "Maximum amount of iterations of the pass over a function"
+#, no-c-format
msgid "Maximum amount of iterations of the pass over a function."
-msgstr "Cantidad máxima de iteraciones del paso sobre una función"
+msgstr "Cantidad máxima de iteraciones del paso sobre una función."
#: params.def:1083
-#, fuzzy, no-c-format
-#| msgid "Maximum number of strings for which strlen optimization pass will track string lengths"
+#, no-c-format
msgid "Maximum number of strings for which strlen optimization pass will track string lengths."
-msgstr "Número máximo de cadenas para las que el paso de optimización de strlen rastreará longitudes de cadenas"
+msgstr "Número máximo de cadenas para las que el paso de optimización de strlen rastreará longitudes de cadenas."
#: params.def:1090
#, no-c-format
msgid "Which -fsched-pressure algorithm to apply."
-msgstr ""
+msgstr "Qué algoritmo -fsched-pressure aplicar."
#: params.def:1096
#, no-c-format
msgid "Maximum length of candidate scans for straight-line strength reduction."
-msgstr ""
+msgstr "Longitud máxima de los rastreos de candidatos para reducción de fuerza de línea directa."
#: params.def:1102
#, fuzzy, no-c-format
@@ -2684,81 +2557,77 @@ msgstr ""
#: params.def:1132
#, no-c-format
msgid "Use callbacks instead of inline code if number of accesses in function becomes greater or equal to this number."
-msgstr ""
+msgstr "Utiliza callbacks en lugar de código en línea si el número de accesos en la función se hace mayor o igual que este número."
#: params.def:1138
-#, fuzzy, no-c-format
-#| msgid "Maximum number of namespaces to search for alternatives when name lookup fails"
+#, no-c-format
msgid "Maximum number of nested calls to search for control dependencies during uninitialized variable analysis."
-msgstr "Número máximo de espacios de nombres a buscar por alternativas cuando falla la búsqueda de nombre"
+msgstr "Número máximo de llamadas anidadas para buscar dependencias de control durante el análisis de variables sin inicializar."
#: params.def:1144
#, no-c-format
msgid "Maximum number of statements to be included into a single static constructor generated by Pointer Bounds Checker."
-msgstr ""
+msgstr "Número máximo de sentencias que se incluirán en un único constructor estático generado mediante comprobador de límites de puntero."
#: params.def:1150
#, no-c-format
msgid "Scale factor to apply to the number of statements in a threading path when comparing to the number of (scaled) blocks."
-msgstr ""
+msgstr "Factor de escala que se aplicará al número de sentencias en un camino de hilo cuando se compara con el número de bloques (escaladas)."
#: params.def:1155
#, no-c-format
msgid "Maximum number of arguments a PHI may have before the FSM threader will not try to thread through its block."
-msgstr ""
+msgstr "Número máximo de argumentos que un PHI puede tener antes de que el hilador FSM no intente hacer hilo a través de su bloque."
#: params.def:1160
#, no-c-format
msgid "Scale factor to apply to the number of blocks in a threading path when comparing to the number of (scaled) statements."
-msgstr ""
+msgstr "Factor de escala que se aplicará al número de bloques en un camibo de hilo cuando se compara con el número de sentencias (escaladas)."
#: params.def:1165
#, no-c-format
msgid "Maximum number of instructions to copy when duplicating blocks on a finite state automaton jump thread path."
-msgstr ""
+msgstr "Número máximo de instrucciones que se copiarán cuando se dupliquen bloques en un camino de hilo de salto de máquina de estados."
#: params.def:1170
-#, fuzzy, no-c-format
-#| msgid "maximum number of basic blocks per function to be analyzed by Graphite"
+#, no-c-format
msgid "Maximum number of basic blocks on a finite state automaton jump thread path."
-msgstr "número máximo de bloques básicos por función para analizar con Graphite"
+msgstr "Número máximo de bloques básicos en un camino de hilo de salto de máquina de estados."
#: params.def:1175
-#, fuzzy, no-c-format
-#| msgid "Maximum number of nops to insert for a hint (Default 2)"
+#, no-c-format
msgid "Maximum number of new jump thread paths to create for a finite state automaton."
-msgstr "Número máximo de nops a insertar para una pista (Por defecto 2)"
+msgstr "Número máximo de caminos de hilo de salto nuevos que se crearán para una máquina de estados."
#: params.def:1180
#, no-c-format
msgid "Chunk size of omp schedule for loops parallelized by parloops."
-msgstr ""
+msgstr "Tamaño de la porción de planificación omp para bucles paralelizadps por parloops."
#: params.def:1185
#, no-c-format
msgid "Schedule type of omp schedule for loops parallelized by parloops (static, dynamic, guided, auto, runtime)."
-msgstr ""
+msgstr "Tipo de planificación de planificación omp para bucles paralelizados por parloops (estático, dinámico, guiado, auto, en tiempo de ejecución)."
#: params.def:1192
#, no-c-format
msgid "Maximum recursion depth allowed when querying a property of an SSA name."
-msgstr ""
+msgstr "Máxima profundidad permitida de recursividad cuando se consulta una propiedad de un nombre SSA."
#: params.def:1198
-#, fuzzy, no-c-format
-#| msgid "Maximum number of instructions in basic block to be considered for SLP vectorization"
+#, no-c-format
msgid "Maximum number of insns in a basic block to consider for RTL if-conversion."
-msgstr "El número máximo de instrucciones en bloque básico que se consideran para vectorización SLP"
+msgstr "Número máximo de insns en bloque básico que se consideran para conversión-if RTL."
#: params.def:1204
#, no-c-format
msgid "Level of hsa debug stores verbosity"
-msgstr ""
+msgstr "Nivel de expresividad de los almacenes de depuración hsa"
#: params.def:1209
#, no-c-format
msgid "Maximum number of may-defs visited when devirtualizing speculatively"
-msgstr ""
+msgstr "Número máximo de definiciones posibles visitadas cuando se desvirtualiza especulativamente"
#: c-family/c-format.c:417
msgid "format"
@@ -3043,16 +2912,15 @@ msgstr "No se admite el operando para el código '%c'"
#: config/aarch64/aarch64.c:4492 config/aarch64/aarch64.c:4504
#: config/aarch64/aarch64.c:4515 config/aarch64/aarch64.c:4538
#: config/aarch64/aarch64.c:4591 config/aarch64/aarch64.c:4794
-#, fuzzy, c-format
-#| msgid "invalid operand for code '%c'"
+#, c-format
msgid "invalid operand for '%%%c'"
-msgstr "operando inválido para el código '%c'"
+msgstr "operando no válido para '%%%c'"
#: config/aarch64/aarch64.c:4558 config/aarch64/aarch64.c:4571
#: config/aarch64/aarch64.c:4581
#, c-format
msgid "incompatible floating point / vector register operand for '%%%c'"
-msgstr ""
+msgstr "coma flotante incompatible / operando de registro de vector para '%%%c'"
#: config/aarch64/aarch64.c:4627 config/arm/arm.c:22504
#, c-format
@@ -3060,22 +2928,19 @@ msgid "missing operand"
msgstr "falta un operando"
#: config/aarch64/aarch64.c:4689
-#, fuzzy, c-format
-#| msgid "invalid insn:"
+#, c-format
msgid "invalid constant"
-msgstr "insn inválida:"
+msgstr "constante no válida"
#: config/aarch64/aarch64.c:4692
-#, fuzzy, c-format
-#| msgid "invalid %%d operand"
+#, c-format
msgid "invalid operand"
-msgstr "operando %%d inválido"
+msgstr "operando no válido"
#: config/aarch64/aarch64.c:4805
-#, fuzzy, c-format
-#| msgid "invalid operand code '%c'"
+#, c-format
msgid "invalid operand prefix '%%%c'"
-msgstr "código de operando '%c' inválido"
+msgstr "prefijo de operando no válido '%%%c'"
#: config/alpha/alpha.c:5102 config/i386/i386.c:17140
#: config/rs6000/rs6000.c:21150 config/sparc/sparc.c:8749
@@ -3308,7 +3173,7 @@ msgstr "error interno del compilador. Dirección errónea:"
#: config/avr/avr.c:2418
#, c-format
msgid "Unsupported code '%c' for fixed-point:"
-msgstr ""
+msgstr "Código '%c' no admitido para coma fija:"
#: config/avr/avr.c:2426
msgid "internal compiler error. Unknown mode:"
@@ -3340,18 +3205,17 @@ msgid "internal compiler error. Incorrect shift:"
msgstr "error interno del compilador. Desplazamiento incorrecto:"
#: config/avr/avr.c:7975
-#, fuzzy
-#| msgid "unsupported version"
msgid "unsupported fixed-point conversion"
-msgstr "versión sin soporte"
+msgstr "conversión de coma fija no admitida"
#: config/avr/driver-avr.c:71
-#, fuzzy, c-format
-#| msgid "unknown spec function %qs"
+#, c-format
msgid ""
"Running spec function '%s' with %d args\n"
"\n"
-msgstr "función de especificación %qs desconocida"
+msgstr ""
+"función de especificación '%s' con %d args\n"
+"\n"
#: config/avr/driver-avr.c:118
#, c-format
@@ -3360,6 +3224,9 @@ msgid ""
"'%s': specfile='%s'\n"
"\n"
msgstr ""
+"'%s': mmcu='%s'\n"
+"'%s': specfile='%s'\n"
+"\n"
#: config/bfin/bfin.c:1385
#, c-format
@@ -3894,7 +3761,7 @@ msgstr "Pruebe ejecutar '%s' en el intérprete de órdenes para elevar su límit
#: config/rs6000/rs6000.c:3959
msgid "-maltivec=le not allowed for big-endian targets"
-msgstr ""
+msgstr "-maltivec=le no permitida para destinos big-endian"
#: config/rs6000/rs6000.c:3971
msgid "-mvsx requires hardware floating point"
@@ -3917,30 +3784,24 @@ msgid "-mno-altivec disables vsx"
msgstr "-mno-altivec desactiva vsx"
#: config/rs6000/rs6000.c:4129
-#, fuzzy
-#| msgid "--resource requires -o"
msgid "-mquad-memory requires 64-bit mode"
-msgstr "--resource requiere -o"
+msgstr "-mquad-memory requiere modo de 64 bits"
#: config/rs6000/rs6000.c:4132
msgid "-mquad-memory-atomic requires 64-bit mode"
-msgstr ""
+msgstr "-mquad-memory-atomic requiere modo de 64 bits"
#: config/rs6000/rs6000.c:4144
-#, fuzzy
-#| msgid "Generate code in little endian mode"
msgid "-mquad-memory is not available in little endian mode"
-msgstr "Genera código en modo little endian"
+msgstr "-mquad-memory no está disponible en modo little endian"
#: config/rs6000/rs6000.c:4212
-#, fuzzy
-#| msgid "--resource requires -o"
msgid "-mtoc-fusion requires 64-bit"
-msgstr "--resource requiere -o"
+msgstr "-mtoc-fusion requiere 64 bits"
#: config/rs6000/rs6000.c:4219
msgid "-mtoc-fusion requires medium/large code model"
-msgstr ""
+msgstr "-mtoc-fusion requiere modelo de código medio/grande"
#: config/rs6000/rs6000.c:9919
msgid "bad move"
@@ -3948,13 +3809,12 @@ msgstr "move erróneo"
#: config/rs6000/rs6000.c:20411
msgid "Bad 128-bit move"
-msgstr ""
+msgstr "Movimiento de 128 bits erróneo"
#: config/rs6000/rs6000.c:20602
-#, fuzzy, c-format
-#| msgid "invalid %%H value"
+#, c-format
msgid "invalid %%e value"
-msgstr "valor %%H inválido"
+msgstr "valor %%e no válido"
#: config/rs6000/rs6000.c:20623
#, c-format
@@ -4028,59 +3888,55 @@ msgstr "valor %%y inválido, pruebe usando la restricción 'Z'"
#: config/rs6000/rs6000.c:21814
msgid "__float128 and __ibm128 cannot be used in the same expression"
-msgstr ""
+msgstr "__float128 y __ibm128 no pueden utilizarse en la misma expresión"
#: config/rs6000/rs6000.c:21820
msgid "__ibm128 and long double cannot be used in the same expression"
-msgstr ""
+msgstr "__ibm128 y long double no pueden utilizarse en la misma expresión"
#: config/rs6000/rs6000.c:21826
msgid "__float128 and long double cannot be used in the same expression"
-msgstr ""
+msgstr "__float128 y long double no pueden utilizarse en la misma expresión"
#: config/rs6000/rs6000.c:35706
msgid "AltiVec argument passed to unprototyped function"
msgstr "Se pasó un argumento Altivec a una función sin prototipo"
#: config/rs6000/rs6000.c:37429
-#, fuzzy
-#| msgid "Do not generate code for a Sun FPA"
msgid "Could not generate addis value for fusion"
-msgstr "No generar código para un FPA de Sun"
+msgstr "No se ha podido generar valor addis para fusión"
#: config/rs6000/rs6000.c:37501
-#, fuzzy
-#| msgid "unable to generate reloads for:"
msgid "Unable to generate load/store offset for fusion"
-msgstr "no se pueden generar recargas para:"
+msgstr "No se puede generar desplazamiento de carga/almacenamiento para fusión"
#: config/rs6000/rs6000.c:37605
msgid "Bad GPR fusion"
-msgstr ""
+msgstr "Fusión GPR errónea"
#: config/rs6000/rs6000.c:37823
msgid "emit_fusion_p9_load, bad reg #1"
-msgstr ""
+msgstr "emit_fusion_p9_load, reg #1 erróneo"
#: config/rs6000/rs6000.c:37860
msgid "emit_fusion_p9_load, bad reg #2"
-msgstr ""
+msgstr "emit_fusion_p9_load, reg #2 erróneo"
#: config/rs6000/rs6000.c:37863
msgid "emit_fusion_p9_load not MEM"
-msgstr ""
+msgstr "emit_fusion_p9_load no MEM"
#: config/rs6000/rs6000.c:37901
msgid "emit_fusion_p9_store, bad reg #1"
-msgstr ""
+msgstr "emit_fusion_p9_store, reg #1 erróneo"
#: config/rs6000/rs6000.c:37938
msgid "emit_fusion_p9_store, bad reg #2"
-msgstr ""
+msgstr "emit_fusion_p9_store, reg #2 erróneo"
#: config/rs6000/rs6000.c:37941
msgid "emit_fusion_p9_store not MEM"
-msgstr ""
+msgstr "emit_fusion_p9_store no MEM"
#: config/s390/s390.c:7168
#, c-format
@@ -4159,30 +4015,24 @@ msgid "invalid expression for output modifier '%c'"
msgstr "expresión inválida para el modificador de salida '%c'"
#: config/s390/s390.c:11377
-#, fuzzy
-#| msgid "AltiVec argument passed to unprototyped function"
msgid "Vector argument passed to unprototyped function"
-msgstr "Se pasó un argumento Altivec a una función sin prototipo"
+msgstr "Se pasó un argumento vector a una función sin prototipo"
#: config/s390/s390.c:15036
-#, fuzzy
-#| msgid "pointer targets in return differ in signedness"
msgid "types differ in signess"
-msgstr "el puntero que apunta en la devolución difiere en signo"
+msgstr "los tipos difieren en el signo"
#: config/s390/s390.c:15046
msgid "binary operator does not support two vector bool operands"
-msgstr ""
+msgstr "el operador binario no admite dos operadores bool vector"
#: config/s390/s390.c:15049
-#, fuzzy
-#| msgid "profiling does not support code models other than medlow"
msgid "binary operator does not support vector bool operand"
-msgstr "el análisis de perfil no soporta modelos de código que no sean medlow"
+msgstr "el operador binario no admite operador bool vector"
#: config/s390/s390.c:15057
msgid "binary operator does not support mixing vector bool with floating point vector operands"
-msgstr ""
+msgstr "el operador binario no admite que se mezclen operandos bool vector y vector de coma flotante"
#: config/sh/sh.c:1313
#, c-format
@@ -4444,7 +4294,7 @@ msgstr "el desplazamiento de dirección no es una constante"
#: c/c-objc-common.c:160
msgid "aka"
-msgstr ""
+msgstr "también conocido como"
#: c/c-objc-common.c:187
msgid "({anonymous})"
@@ -4548,21 +4398,19 @@ msgstr "se esperaba %<:%>"
#: c/c-parser.c:5185 cp/semantics.c:613
msgid "Cilk array notation cannot be used as a computed goto expression"
-msgstr ""
+msgstr "La notaicón de array de Cilk no puede utilizarse como una expresión goto calculada"
#: c/c-parser.c:5244
-#, fuzzy
-#| msgid "expression %qE of abstract class type %qT cannot be used in throw-expression"
msgid "Cilk array notation cannot be used for a throw expression"
-msgstr "no se puede usar la expresión %qE del tipo de clase abstracta %qT en las expresiones throw"
+msgstr "La notaicón de array de Cilk no puede utilizarse para expresiones throw"
#: c/c-parser.c:5556 cp/semantics.c:1136
msgid "Cilk array notation cannot be used as a condition for switch statement"
-msgstr ""
+msgstr "La notaicón de array de Cilk no puede utilizarse para sentencias switch"
#: c/c-parser.c:5605 cp/semantics.c:791
msgid "Cilk array notation cannot be used as a condition for while statement"
-msgstr ""
+msgstr "La notaicón de array de Cilk no puede utilizarse para sentencias while"
#: c/c-parser.c:5656 cp/parser.c:26897
#, gcc-internal-format
@@ -4571,11 +4419,11 @@ msgstr "se esperaba %<while%>"
#: c/c-parser.c:5663 cp/semantics.c:850
msgid "Cilk array notation cannot be used as a condition for a do-while statement"
-msgstr ""
+msgstr "La notaicón de array de Cilk no puede utilizarse para sentencias do-while"
#: c/c-parser.c:5866 cp/semantics.c:969
msgid "Cilk array notation cannot be used in a condition for a for-loop"
-msgstr ""
+msgstr "La notaicón de array de Cilk no puede utilizarse para sentencias do-while"
#: c/c-parser.c:7497
msgid "expected %<.%>"
@@ -4724,21 +4572,19 @@ msgstr "<expresión-throw>"
#: cp/error.c:2115
msgid "<ubsan routine call>"
-msgstr ""
+msgstr "<llamada a rutina ubsan>"
#: cp/error.c:2572
msgid "<unparsed>"
msgstr "<sidecodificar>"
#: cp/error.c:2723
-#, fuzzy
-#| msgid "<lambda"
msgid "<lambda>"
-msgstr "<lambda"
+msgstr "<lambda>"
#: cp/error.c:2766
msgid "*this"
-msgstr ""
+msgstr "*this"
#: cp/error.c:2776
msgid "<expression error>"
@@ -4998,30 +4844,24 @@ msgid "arguments '%s' and '%s' for intrinsic '%s'"
msgstr "argumentos '%s' y '%s' para el intrínseco '%s'"
#: fortran/error.c:871
-#, fuzzy
-#| msgid "Fortran 2008 obsolescent feature: ENTRY statement at %C"
msgid "Fortran 2008 obsolescent feature:"
-msgstr "Característica obsoleta de Fortran 2008: declaración ENTRY en %C"
+msgstr "Característica obsoleta de Fortran 2008:"
#: fortran/error.c:880
msgid "GNU Extension:"
-msgstr ""
+msgstr "Extensión GNU:"
#: fortran/error.c:883
msgid "Legacy Extension:"
-msgstr ""
+msgstr "Extensión antigua:"
#: fortran/error.c:886
-#, fuzzy
-#| msgid "Obsolescent feature: Computed GOTO at %C"
msgid "Obsolescent feature:"
-msgstr "Característica obsoleta: GOTO computado en %C"
+msgstr "Característica obsoleta:"
#: fortran/error.c:889
-#, fuzzy
-#| msgid "expected operator"
msgid "Deleted feature:"
-msgstr "operador inesperado"
+msgstr "Característica borrada:"
#: fortran/expr.c:622
#, c-format
@@ -5060,10 +4900,8 @@ msgid "Nonnegative width required"
msgstr "Se requiere una anchura que no sea negativa"
#: fortran/io.c:552
-#, fuzzy
-#| msgid "Unexpected element '%c' in format string at %L"
msgid "Unexpected element %qc in format string at %L"
-msgstr "Elemento '%c' inesperado en la cadena de formato en %L"
+msgstr "Elemento %qc inesperado en la cadena de formato en %L"
#: fortran/io.c:554
msgid "Unexpected end of format string"
@@ -5078,10 +4916,8 @@ msgid "Missing leading left parenthesis"
msgstr "Falta el paréntesis izquierdo inicial"
#: fortran/io.c:604
-#, fuzzy
-#| msgid "Left parenthesis required after '*'"
msgid "Left parenthesis required after %<*%>"
-msgstr "Se requiere paréntesis izquierdo después de '*'"
+msgstr "Se requiere paréntesis izquierdo después de %<*%>"
#: fortran/io.c:635
msgid "Expected P edit descriptor"
@@ -5254,34 +5090,24 @@ msgid "elemental procedure"
msgstr "procedimiento elemental"
#: fortran/resolve.c:2254
-#, fuzzy
-#| msgid "invalid type argument"
msgid "allocatable argument"
-msgstr "argumento de tipo inválido"
+msgstr "argumento asignable"
#: fortran/resolve.c:2259
-#, fuzzy
-#| msgid "not enough arguments"
msgid "asynchronous argument"
-msgstr "faltan argumentos"
+msgstr "argumento asíncrono"
#: fortran/resolve.c:2264
-#, fuzzy
-#| msgid "invalid PHI argument"
msgid "optional argument"
-msgstr "argumento PHI inválido"
+msgstr "argumento opcional"
#: fortran/resolve.c:2269
-#, fuzzy
-#| msgid "pointer assignment"
msgid "pointer argument"
-msgstr "asignación de puntero"
+msgstr "argumento puntero"
#: fortran/resolve.c:2274
-#, fuzzy
-#| msgid "too many arguments"
msgid "target argument"
-msgstr "demasiados argumentos"
+msgstr "argumento destino"
#: fortran/resolve.c:2279
#, fuzzy
@@ -5290,10 +5116,8 @@ msgid "value argument"
msgstr "argumento de tipo inválido"
#: fortran/resolve.c:2284
-#, fuzzy
-#| msgid "no arguments"
msgid "volatile argument"
-msgstr "sin argumentos"
+msgstr "argumento volátil"
#: fortran/resolve.c:2289
#, fuzzy
@@ -5302,16 +5126,12 @@ msgid "assumed-shape argument"
msgstr "no coinciden los argumentos"
#: fortran/resolve.c:2294
-#, fuzzy
-#| msgid "mismatched arguments"
msgid "assumed-rank argument"
-msgstr "no coinciden los argumentos"
+msgstr "se asume argumento de rango"
#: fortran/resolve.c:2299
-#, fuzzy
-#| msgid "array assignment"
msgid "coarray argument"
-msgstr "asignación de matriz"
+msgstr "argumento de coarray"
#: fortran/resolve.c:2304
#, fuzzy
@@ -5320,14 +5140,12 @@ msgid "parametrized derived type argument"
msgstr "no se han implementado las estructuras parametrizadas"
#: fortran/resolve.c:2309
-#, fuzzy
-#| msgid "no arguments"
msgid "polymorphic argument"
-msgstr "sin argumentos"
+msgstr "argumento polimórfico"
#: fortran/resolve.c:2314
msgid "NO_ARG_CHECK attribute"
-msgstr ""
+msgstr "atributo NO_ARG_CHECK"
#. As assumed-type is unlimited polymorphic (cf. above).
#. See also TS 29113, Note 6.1.
@@ -5339,13 +5157,11 @@ msgstr "argumento de tipo inválido"
#: fortran/resolve.c:2332
msgid "array result"
-msgstr ""
+msgstr "resultado array"
#: fortran/resolve.c:2337
-#, fuzzy
-#| msgid "Coindexed allocatable object at %L"
msgid "pointer or allocatable result"
-msgstr "Objeto alojable coindizado en %L"
+msgstr "puntero o resultado asignable"
#: fortran/resolve.c:2344
#, fuzzy
@@ -5365,16 +5181,14 @@ msgid "Invalid context for NULL() pointer at %%L"
msgstr "Contexto inválido para el puntero NULL() en %%L"
#: fortran/resolve.c:3574
-#, fuzzy, c-format
-#| msgid "Operand of unary numeric operator '%s' at %%L is %s"
+#, c-format
msgid "Operand of unary numeric operator %%<%s%%> at %%L is %s"
-msgstr "El operando del operador numérico unario '%s' en %%L es %s"
+msgstr "El operando del operador numérico unitario %%<%s%%> en %%L es %s"
#: fortran/resolve.c:3590
-#, fuzzy, c-format
-#| msgid "Operands of binary numeric operator '%s' at %%L are %s/%s"
+#, c-format
msgid "Operands of binary numeric operator %%<%s%%> at %%L are %s/%s"
-msgstr "Los operandos del operador binario numérico '%s' en %%L son %s/%s"
+msgstr "Los operandos del operador numérico binario %%<%s%%> en %%L son %s/%s"
#: fortran/resolve.c:3605
#, c-format
@@ -5382,10 +5196,9 @@ msgid "Operands of string concatenation operator at %%L are %s/%s"
msgstr "Los operandos del operador de concatenación de cadenas en %%L son %s/%s"
#: fortran/resolve.c:3624
-#, fuzzy, c-format
-#| msgid "Operands of logical operator '%s' at %%L are %s/%s"
+#, c-format
msgid "Operands of logical operator %%<%s%%> at %%L are %s/%s"
-msgstr "Los operandos del operador lógico '%s' en %%L son %s/%s"
+msgstr "Los operandos del operador lógico %%<%s%%> en %%L son %s/%s"
#: fortran/resolve.c:3638
#, c-format
@@ -5402,28 +5215,24 @@ msgid "Logicals at %%L must be compared with %s instead of %s"
msgstr "Los lógicos en %%L se deben comparar con %s en lugar de %s"
#: fortran/resolve.c:3709
-#, fuzzy, c-format
-#| msgid "Operands of comparison operator '%s' at %%L are %s/%s"
+#, c-format
msgid "Operands of comparison operator %%<%s%%> at %%L are %s/%s"
-msgstr "Los operandos del operador de comparación '%s' en %%L son %s/%s"
+msgstr "Los operandos del operador de comparación %%<%s%%> en %%L son %s/%s"
#: fortran/resolve.c:3717
-#, fuzzy, c-format
-#| msgid "Unknown operator '%s' at %%L"
+#, c-format
msgid "Unknown operator %%<%s%%> at %%L"
-msgstr "Operador '%s' desconocido en %%L"
+msgstr "Operador %%<%s%%> desconocido en %%L"
#: fortran/resolve.c:3720
-#, fuzzy, c-format
-#| msgid "Operand of user operator '%s' at %%L is %s"
+#, c-format
msgid "Operand of user operator %%<%s%%> at %%L is %s"
-msgstr "El operando del operador de usuario '%s' en %%L es %s"
+msgstr "El operando del operador de usuario %%<%s%%> en %%L es %s"
#: fortran/resolve.c:3724
-#, fuzzy, c-format
-#| msgid "Operands of user operator '%s' at %%L are %s/%s"
+#, c-format
msgid "Operands of user operator %%<%s%%> at %%L are %s/%s"
-msgstr "Los operandos del operador de usuario '%s' en %%L son %s/%s"
+msgstr "Los operandos del operador de usuario %%<%s%%> en %%L son %s/%s"
#: fortran/resolve.c:3812
#, c-format
@@ -5500,7 +5309,7 @@ msgstr "El objetivo del remapeo de rango es demasiado pequeño (%ld < %ld)"
#: fortran/trans-expr.c:9375
msgid "Assignment of scalar to unallocated array"
-msgstr ""
+msgstr "Asignación de escalar a un array sin espacio asignado"
#: fortran/trans-intrinsic.c:897
#, c-format
@@ -5769,7 +5578,7 @@ msgid ""
"For bug reporting instructions, please see:\n"
"%s.\n"
msgstr ""
-"Para instrucciones de reporte de bichos, por favor vea:\n"
+"Para instrucciones de informe de errores, por favor vea:\n"
"%s.\n"
#: java/jcf-dump.c:1258 java/jcf-dump.c:1326
@@ -5813,16 +5622,12 @@ msgid "<unnamed>"
msgstr "<sinnombre>"
#: gcc.c:747 gcc.c:751 gcc.c:806
-#, fuzzy
-#| msgid "-m%s not supported in this configuration"
msgid "-gz is not supported in this configuration"
-msgstr "no se admite -m%s en esta configuración"
+msgstr "no se admite -gz en esta configuración"
#: gcc.c:757 gcc.c:817
-#, fuzzy
-#| msgid "ifunc is not supported in this configuration"
msgid "-gz=zlib is not supported in this configuration"
-msgstr "ifunc no se admite en esta configuración"
+msgstr "no se admite -gz=zlib en esta configuración"
#: gcc.c:961
msgid "-fuse-linker-plugin is not supported in this configuration"
@@ -5830,11 +5635,11 @@ msgstr "-fuse-linker-plugin no se admite en esta configuración"
#: gcc.c:976
msgid "cannot specify -static with -fsanitize=address"
-msgstr ""
+msgstr "no se puede especificar -static con -fsanitize=address"
#: gcc.c:978
msgid "cannot specify -static with -fsanitize=thread"
-msgstr ""
+msgstr "no se puede especificar -static con -fsanitize=thread"
#: gcc.c:1122 ada/gcc-interface/lang-specs.h:33 java/jvspec.c:79
msgid "-pg and -fomit-frame-pointer are incompatible"
@@ -5964,14 +5769,12 @@ msgid "-msingle-float and -msoft-float cannot both be specified"
msgstr "no se pueden especificar -msingle-float y -msoft-float al mismo tiempo"
#: config/moxie/moxiebox.h:43
-#, fuzzy
-#| msgid "Assume target CPU is configured as little endian"
msgid "this target is little-endian"
-msgstr "Asume que el CPU destino está configurado como little endian"
+msgstr "este destino es little endian"
#: config/nios2/elf.h:44
msgid "You need a C startup file for -msys-crt0="
-msgstr ""
+msgstr "Se necesita un fichero de arranque de C para -msys-crt0="
#: config/pa/pa-hpux10.h:102 config/pa/pa-hpux10.h:105
#: config/pa/pa-hpux10.h:113 config/pa/pa-hpux10.h:116
@@ -6076,54 +5879,40 @@ msgid "objc++-cpp-output is deprecated; please use objective-c++-cpp-output inst
msgstr "objc++-cpp-output es obsoleto; pr favor use en su lugar objective-c++-cpp-output"
#: fortran/lang.opt:146
-#, fuzzy
-#| msgid "-J<directory>\tPut MODULE files in 'directory'"
msgid "-J<directory>\tPut MODULE files in 'directory'."
-msgstr "-J<directorio>\tColoca los ficheros MODULE en el 'directorio'"
+msgstr "-J<directorio>\tColoca los ficheros MODULE en el 'directorio'."
#: fortran/lang.opt:198
-#, fuzzy
-#| msgid "Warn about possible aliasing of dummy arguments"
msgid "Warn about possible aliasing of dummy arguments."
-msgstr "Avisa sobre posibles aliases de argumentos de relleno"
+msgstr "Avisa sobre posibles aliases de argumentos de relleno."
#: fortran/lang.opt:202
-#, fuzzy
-#| msgid "Warn about alignment of COMMON blocks"
msgid "Warn about alignment of COMMON blocks."
-msgstr "Avisa sobre la alineación de bloques COMMON"
+msgstr "Avisa sobre la alineación de bloques COMMON."
#: fortran/lang.opt:206
-#, fuzzy
-#| msgid "Warn about missing ampersand in continued character constants"
msgid "Warn about missing ampersand in continued character constants."
-msgstr "Avisa sobre '&' faltantes en las literales de carácter continuadas"
+msgstr "Avisa sobre '&' faltantes en las literales de carácter continuadas."
#: fortran/lang.opt:210
-#, fuzzy
-#| msgid "Warn about creation of array temporaries"
msgid "Warn about creation of array temporaries."
-msgstr "Avisa sobre la creación de matrices temporales"
+msgstr "Avisa sobre la creación de matrices temporales."
#: fortran/lang.opt:214
msgid "Warn if the type of a variable might be not interoperable with C."
-msgstr ""
+msgstr "Avisa si el tipo de una variable podría no ser interoperable con C."
#: fortran/lang.opt:222
-#, fuzzy
-#| msgid "Warn about truncated character expressions"
msgid "Warn about truncated character expressions."
-msgstr "Avisa sobre expresiones de carácter truncadas"
+msgstr "Avisa sobre expresiones de carácter truncadas."
#: fortran/lang.opt:226
msgid "Warn about equality comparisons involving REAL or COMPLEX expressions."
-msgstr ""
+msgstr "Avisa sobre comparaciones de igualdad que involucran expresiones REAL o COMPLEX."
#: fortran/lang.opt:234
-#, fuzzy
-#| msgid "Warn about most implicit conversions"
msgid "Warn about most implicit conversions."
-msgstr "Avisa sobre la mayoría de las conversiones implícitas"
+msgstr "Avisa sobre la mayoría de las conversiones implícitas."
#: fortran/lang.opt:242
#, fuzzy
@@ -8264,7 +8053,7 @@ msgstr "Asume que los valores de tipo de enumeración están siempre dentro del
#, fuzzy
#| msgid "-ftabstop=<number>\tDistance between tab stops for column reporting"
msgid "-ftabstop=<number>\tDistance between tab stops for column reporting."
-msgstr "-ftabstop=<número>\tDistancia entre topes de tabulador para reportes en columnas"
+msgstr "-ftabstop=<número>\tDistancia entre topes de tabulador para informes en columnas"
#: c-family/c.opt:1507
#, fuzzy
@@ -9494,13 +9283,13 @@ msgstr "Especifica el tamaño de bit para los desplazamientos TLS inmediatos"
#, fuzzy
#| msgid "-mcpu=CPU\tUse features of and schedule code for given CPU"
msgid "-march=ARCH\tUse features of architecture ARCH."
-msgstr "-mcpu=CPU\tUsa las características y el código de calendarizador para el CPU dado"
+msgstr "-mcpu=CPU\tUsa las características y el código de planificador para el CPU dado"
#: config/aarch64/aarch64.opt:124
#, fuzzy
#| msgid "-mcpu=CPU\tUse features of and schedule code for given CPU"
msgid "-mcpu=CPU\tUse features of and optimize for CPU."
-msgstr "-mcpu=CPU\tUsa las características y el código de calendarizador para el CPU dado"
+msgstr "-mcpu=CPU\tUsa las características y el código de planificador para el CPU dado"
#: config/aarch64/aarch64.opt:128
msgid "-mtune=CPU\tOptimize for CPU."
@@ -9704,7 +9493,7 @@ msgstr "Especifica el tamaño de bit para los desplazamientos TLS inmediatos"
#, fuzzy
#| msgid "Schedule code for given CPU"
msgid "Schedule code for given CPU."
-msgstr "Código de calendarizador para el CPU dado"
+msgstr "Código de planificador para el CPU dado"
#: config/ia64/ia64.opt:126
msgid "Known Itanium CPUs (for use with the -mtune= option):"
@@ -10660,7 +10449,7 @@ msgstr ""
#, fuzzy
#| msgid "Do dispatch scheduling if processor is bdver1 or bdver2 and Haifa scheduling"
msgid "Do dispatch scheduling if processor is bdver1, bdver2, bdver3, bdver4"
-msgstr "Despacha al calendarizador si el procesador es bdver1 o bdver2 y la calendarización es Haifa"
+msgstr "Despacha al planificador si el procesador es bdver1 o bdver2 y la calendarización es Haifa"
#: config/i386/i386.opt:582
msgid "Use 128-bit AVX instructions instead of 256-bit AVX instructions in the auto-vectorizer."
@@ -12235,7 +12024,7 @@ msgstr ""
#, fuzzy
#| msgid "Use features of and schedule code for given CPU"
msgid "Use features of and schedule code for given CPU."
-msgstr "Usa las características y el código de calendarizador para el CPU dado"
+msgstr "Usa las características y el código de planificador para el CPU dado"
#: config/sparc/sparc.opt:206
#, fuzzy
@@ -12653,13 +12442,13 @@ msgstr "se usa long double de precisión extendida de IBM"
#, fuzzy
#| msgid "-mcpu=\tUse features of and schedule code for given CPU"
msgid "-mcpu=\tUse features of and schedule code for given CPU."
-msgstr "-mcpu=\tUsa las características y el código de calendarizador para el CPU dado"
+msgstr "-mcpu=\tUsa las características y el código de planificador para el CPU dado"
#: config/rs6000/rs6000.opt:414
#, fuzzy
#| msgid "-mtune=\tSchedule code for given CPU"
msgid "-mtune=\tSchedule code for given CPU."
-msgstr "-mtune=\tCódigo de calendarizador para el CPU dado"
+msgstr "-mtune=\tCódigo de planificador para el CPU dado"
#: config/rs6000/rs6000.opt:418
#, fuzzy
@@ -13113,7 +12902,7 @@ msgstr "Emite rdval en lugar de rduniq para un puntero thread"
#, fuzzy
#| msgid "Use features of and schedule given CPU"
msgid "Use features of and schedule given CPU."
-msgstr "Usa las características y el calendarizador del CPU dado"
+msgstr "Usa las características y el planificador del CPU dado"
#: config/alpha/alpha.opt:110
#, fuzzy
@@ -13153,7 +12942,7 @@ msgstr "Compila con longs y punteros de 32 bit, el cual es el único admitido"
#, fuzzy
#| msgid "-mcpu=CPU\tUse features of and schedule code for given CPU"
msgid "-mcpu=CPU\tUse features of and schedule code for given CPU."
-msgstr "-mcpu=CPU\tUsa las características y el código de calendarizador para el CPU dado"
+msgstr "-mcpu=CPU\tUsa las características y el código de planificador para el CPU dado"
#: config/tilepro/tilepro.opt:32
msgid "Known TILEPro CPUs (for use with the -mcpu= option):"
@@ -14039,7 +13828,7 @@ msgstr "Usa las optimización de búsqueda de tabla para divisiones enteras smal
#, fuzzy
#| msgid "-mcpu=PROCESSOR\t\tUse features of and schedule code for given CPU"
msgid "-mcpu=PROCESSOR\t\tUse features of and schedule code for given CPU."
-msgstr "-mcpu=PROCESADOR\t\tUsa las características y el código de calendarizador para el CPU dado"
+msgstr "-mcpu=PROCESADOR\t\tUsa las características y el código de planificador para el CPU dado"
#: config/microblaze/microblaze.opt:56
#, fuzzy
@@ -14369,7 +14158,7 @@ msgstr "Permite establecer los GPRs al resultado de las comparaciones"
#, fuzzy
#| msgid "Change the amount of scheduler lookahead"
msgid "Change the amount of scheduler lookahead."
-msgstr "Cambia la cantidad de vista hacia adelante del calendarizador"
+msgstr "Cambia la cantidad de vista hacia adelante del planificador"
#: config/frv/frv.opt:219
#, fuzzy
@@ -14423,7 +14212,7 @@ msgstr "Apunta al procesador AM34"
#, fuzzy
#| msgid "Work around hardware multiply bug"
msgid "Work around hardware multiply bug."
-msgstr "Evita el bicho de multiplicación de hardware"
+msgstr "Evita el error de multiplicación de hardware"
#: config/mn10300/mn10300.opt:55
#, fuzzy
@@ -14591,7 +14380,7 @@ msgstr "Junto con -fpic y -fPIC, no utiliza referencias GOTPLT"
#, fuzzy
#| msgid "Work around bug in multiplication instruction"
msgid "Work around bug in multiplication instruction."
-msgstr "Evita el bicho en la instrucción de multiplicación"
+msgstr "Evita el error en la instrucción de multiplicación"
#: config/cris/cris.opt:51
#, fuzzy
@@ -18036,7 +17825,7 @@ msgstr "Permite el movimiento especulativo de más loads"
#, fuzzy
#| msgid "-fsched-verbose=<number>\tSet the verbosity level of the scheduler"
msgid "-fsched-verbose=<number>\tSet the verbosity level of the scheduler."
-msgstr "-fsched-verbose=<número>\tEstablece el nivel de detalle del calendarizador"
+msgstr "-fsched-verbose=<número>\tEstablece el nivel de detalle del planificador"
#: common.opt:2031
#, fuzzy
@@ -18118,37 +17907,37 @@ msgstr "-fsched-stalled-insns-dep=<número>\tEstablece la revisión de distancia
#, fuzzy
#| msgid "Enable the group heuristic in the scheduler"
msgid "Enable the group heuristic in the scheduler."
-msgstr "Activa la heurística de grupo en el calendarizador"
+msgstr "Activa la heurística de grupo en el planificador"
#: common.opt:2100
#, fuzzy
#| msgid "Enable the critical path heuristic in the scheduler"
msgid "Enable the critical path heuristic in the scheduler."
-msgstr "Activa la heurística de ruta crítica en el calendarizador"
+msgstr "Activa la heurística de ruta crítica en el planificador"
#: common.opt:2104
#, fuzzy
#| msgid "Enable the speculative instruction heuristic in the scheduler"
msgid "Enable the speculative instruction heuristic in the scheduler."
-msgstr "Activa la heurística de instrucción especulativa en el calendarizador"
+msgstr "Activa la heurística de instrucción especulativa en el planificador"
#: common.opt:2108
#, fuzzy
#| msgid "Enable the rank heuristic in the scheduler"
msgid "Enable the rank heuristic in the scheduler."
-msgstr "Activa la heurística de rango en el calendarizador"
+msgstr "Activa la heurística de rango en el planificador"
#: common.opt:2112
#, fuzzy
#| msgid "Enable the last instruction heuristic in the scheduler"
msgid "Enable the last instruction heuristic in the scheduler."
-msgstr "Activa la heurística de última instrucción en el calendarizador"
+msgstr "Activa la heurística de última instrucción en el planificador"
#: common.opt:2116
#, fuzzy
#| msgid "Enable the dependent count heuristic in the scheduler"
msgid "Enable the dependent count heuristic in the scheduler."
-msgstr "Activa la heurística de cuenta dependiente en el calendarizador"
+msgstr "Activa la heurística de cuenta dependiente en el planificador"
#: common.opt:2120
#, fuzzy
@@ -24102,7 +23891,7 @@ msgstr "se solicitó seguimiento de variables, pero no se admite este formato de
#: toplev.c:1471
#, gcc-internal-format
msgid "var-tracking-assignments changes selective scheduling"
-msgstr "las asignaciones-de-rastreo-de-variable cambian el calendarizador selectivo"
+msgstr "las asignaciones-de-rastreo-de-variable cambian el planificador selectivo"
#: toplev.c:1497
#, gcc-internal-format
@@ -37228,17 +37017,17 @@ msgstr "se usaron al mismo tiempo %<long%> y %<void%> en los especificadores de
#: c/c-parser.c:12101 cp/parser.c:31327
#, gcc-internal-format
msgid "schedule %<runtime%> does not take a %<chunk_size%> parameter"
-msgstr "el calendarizador %<runtime%> no toma un parámetro %<chunk_size%>"
+msgstr "el planificador %<runtime%> no toma un parámetro %<chunk_size%>"
#: c/c-parser.c:12105 cp/parser.c:31330
#, gcc-internal-format
msgid "schedule %<auto%> does not take a %<chunk_size%> parameter"
-msgstr "el calendarizador %<auto%> no toma un parámetro %<chunk_size%>"
+msgstr "el planificador %<auto%> no toma un parámetro %<chunk_size%>"
#: c/c-parser.c:12127 cp/parser.c:31350
#, gcc-internal-format
msgid "invalid schedule kind"
-msgstr "género de calendarizador inválido"
+msgstr "género de planificador inválido"
#: c/c-parser.c:12188
#, fuzzy, gcc-internal-format
@@ -37292,7 +37081,7 @@ msgstr "%Hel argumento de collapse necesita ser una expresión entera constante
#, fuzzy, gcc-internal-format
#| msgid "invalid schedule kind"
msgid "invalid depend kind"
-msgstr "género de calendarizador inválido"
+msgstr "género de planificador inválido"
#: c/c-parser.c:12768 cp/parser.c:31917
#, fuzzy, gcc-internal-format
@@ -37304,13 +37093,13 @@ msgstr "máscara inválida"
#, fuzzy, gcc-internal-format
#| msgid "invalid schedule kind"
msgid "invalid dist_schedule kind"
-msgstr "género de calendarizador inválido"
+msgstr "género de planificador inválido"
#: c/c-parser.c:12931
#, fuzzy, gcc-internal-format
#| msgid "invalid schedule kind"
msgid "invalid proc_bind kind"
-msgstr "género de calendarizador inválido"
+msgstr "género de planificador inválido"
#: c/c-parser.c:13144 cp/parser.c:32292
#, fuzzy, gcc-internal-format
@@ -68207,10 +67996,10 @@ msgstr "se crea un selector para el método %qE que no existe"
#~ msgstr "%Hdemasiadas cláusulas %qs"
#~ msgid "%Hschedule %<runtime%> does not take a %<chunk_size%> parameter"
-#~ msgstr "%Hel calendarizador %<runtime%> no toma un parámetro %<chunk_size%>"
+#~ msgstr "%Hel planificador %<runtime%> no toma un parámetro %<chunk_size%>"
#~ msgid "%Hschedule %<auto%> does not take a %<chunk_size%> parameter"
-#~ msgstr "%Hel calendarizador %<auto%> no toma un parámetro %<chunk_size%>"
+#~ msgstr "%Hel planificador %<auto%> no toma un parámetro %<chunk_size%>"
#~ msgid "%H%qs is not valid for %qs"
#~ msgstr "%H%qs no es válido para %qs"
diff --git a/gcc/postreload.c b/gcc/postreload.c
index 26871e8d12b..8a4456238c4 100644
--- a/gcc/postreload.c
+++ b/gcc/postreload.c
@@ -41,10 +41,6 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pass.h"
#include "dbgcnt.h"
-#ifndef LOAD_EXTEND_OP
-#define LOAD_EXTEND_OP(M) UNKNOWN
-#endif
-
static int reload_cse_noop_set_p (rtx);
static bool reload_cse_simplify (rtx_insn *, rtx);
static void reload_cse_regs_1 (void);
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 341ecdfedb8..3f15a216c96 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -564,6 +564,43 @@ rtx_writer::print_rtx_operand (const_rtx in_rtx, int idx)
}
}
+/* Subroutine of rtx_writer::print_rtx.
+ In compact mode, determine if operand IDX of IN_RTX is interesting
+ to dump, or (if in a trailing position) it can be omitted. */
+
+bool
+rtx_writer::operand_has_default_value_p (const_rtx in_rtx, int idx)
+{
+ const char *format_ptr = GET_RTX_FORMAT (GET_CODE (in_rtx));
+
+ switch (format_ptr[idx])
+ {
+ case 'e':
+ case 'u':
+ return XEXP (in_rtx, idx) == NULL_RTX;
+
+ case 's':
+ return XSTR (in_rtx, idx) == NULL;
+
+ case '0':
+ switch (GET_CODE (in_rtx))
+ {
+ case JUMP_INSN:
+ /* JUMP_LABELs are always omitted in compact mode, so treat
+ any value here as omittable, so that earlier operands can
+ potentially be omitted also. */
+ return m_compact;
+
+ default:
+ return false;
+
+ }
+
+ default:
+ return false;
+ }
+}
+
/* Print IN_RTX onto m_outfile. This is the recursive part of printing. */
void
@@ -681,9 +718,18 @@ rtx_writer::print_rtx (const_rtx in_rtx)
fprintf (m_outfile, " %d", INSN_UID (in_rtx));
}
+ /* Determine which is the final operand to print.
+ In compact mode, skip trailing operands that have the default values
+ e.g. trailing "(nil)" values. */
+ int limit = GET_RTX_LENGTH (GET_CODE (in_rtx));
+ if (m_compact)
+ while (limit > idx && operand_has_default_value_p (in_rtx, limit - 1))
+ limit--;
+
/* Get the format string and skip the first elements if we have handled
them already. */
- for (; idx < GET_RTX_LENGTH (GET_CODE (in_rtx)); idx++)
+
+ for (; idx < limit; idx++)
print_rtx_operand (in_rtx, idx);
switch (GET_CODE (in_rtx))
diff --git a/gcc/print-rtl.h b/gcc/print-rtl.h
index 8496ffa1491..68db057b201 100644
--- a/gcc/print-rtl.h
+++ b/gcc/print-rtl.h
@@ -39,6 +39,7 @@ class rtx_writer
void print_rtx_operand_code_r (const_rtx in_rtx);
void print_rtx_operand_code_u (const_rtx in_rtx, int idx);
void print_rtx_operand (const_rtx in_rtx, int idx);
+ bool operand_has_default_value_p (const_rtx in_rtx, int idx);
private:
FILE *m_outfile;
diff --git a/gcc/profile.c b/gcc/profile.c
index 2564f07abf7..ef38f988a34 100644
--- a/gcc/profile.c
+++ b/gcc/profile.c
@@ -192,15 +192,9 @@ instrument_values (histogram_values values)
gimple_gen_ior_profiler (hist, t, 0);
break;
- case HIST_TYPE_TIME_PROFILE:
- {
- basic_block bb =
- split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
- gimple_stmt_iterator gsi = gsi_start_bb (bb);
-
- gimple_gen_time_profiler (t, 0, gsi);
- break;
- }
+ case HIST_TYPE_TIME_PROFILE:
+ gimple_gen_time_profiler (t, 0);
+ break;
default:
gcc_unreachable ();
@@ -1305,7 +1299,7 @@ branch_prob (void)
{
unsigned n_instrumented;
- gimple_init_edge_profiler ();
+ gimple_init_gcov_profiler ();
n_instrumented = instrument_edges (el);
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index 5374169b9a4..962dbb8007e 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -149,6 +149,11 @@ REG_NOTE (CFA_REGISTER)
store of a register to an arbitrary (non-validated) memory address. */
REG_NOTE (CFA_EXPRESSION)
+/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
+ for FRAME_RELATED_EXPR intuition. The DWARF expression computes the value of
+ the given register. */
+REG_NOTE (CFA_VAL_EXPRESSION)
+
/* Attached to insns that are RTX_FRAME_RELATED_P, with the information
that this is a restore operation, i.e. will result in DW_CFA_restore
or the like. Either the attached rtx, or the destination of the insn's
diff --git a/gcc/reload.c b/gcc/reload.c
index 3ec4b310f50..7d1681772b4 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -1064,7 +1064,6 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|| MEM_P (SUBREG_REG (in)))
&& ((GET_MODE_PRECISION (inmode)
> GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
-#ifdef LOAD_EXTEND_OP
|| (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
<= UNITS_PER_WORD)
@@ -1072,15 +1071,12 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
> GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
&& INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in)))
&& LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != UNKNOWN)
-#endif
-#if WORD_REGISTER_OPERATIONS
- || ((GET_MODE_PRECISION (inmode)
- < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
+ || (WORD_REGISTER_OPERATIONS
+ && (GET_MODE_PRECISION (inmode)
+ < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (in))))
&& ((GET_MODE_SIZE (inmode) - 1) / UNITS_PER_WORD ==
((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - 1)
- / UNITS_PER_WORD)))
-#endif
- ))
+ / UNITS_PER_WORD)))))
|| (REG_P (SUBREG_REG (in))
&& REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
/* The case where out is nonzero
@@ -1111,13 +1107,14 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
#endif
inloc = &SUBREG_REG (in);
in = *inloc;
-#if ! defined (LOAD_EXTEND_OP)
+
if (!WORD_REGISTER_OPERATIONS
+ && LOAD_EXTEND_OP (GET_MODE (in)) == UNKNOWN
&& MEM_P (in))
/* This is supposed to happen only for paradoxical subregs made by
combine.c. (SUBREG (MEM)) isn't supposed to occur other ways. */
gcc_assert (GET_MODE_SIZE (GET_MODE (in)) <= GET_MODE_SIZE (inmode));
-#endif
+
inmode = GET_MODE (in);
}
@@ -1175,14 +1172,12 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc,
|| MEM_P (SUBREG_REG (out)))
&& ((GET_MODE_PRECISION (outmode)
> GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
-#if WORD_REGISTER_OPERATIONS
- || ((GET_MODE_PRECISION (outmode)
- < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
+ || (WORD_REGISTER_OPERATIONS
+ && (GET_MODE_PRECISION (outmode)
+ < GET_MODE_PRECISION (GET_MODE (SUBREG_REG (out))))
&& ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD ==
((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1)
- / UNITS_PER_WORD)))
-#endif
- ))
+ / UNITS_PER_WORD)))))
|| (REG_P (SUBREG_REG (out))
&& REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
/* The case of a word mode subreg
@@ -3139,24 +3134,21 @@ find_reloads (rtx_insn *insn, int replace, int ind_levels, int live_known,
|| ((MEM_P (operand)
|| (REG_P (operand)
&& REGNO (operand) >= FIRST_PSEUDO_REGISTER))
-#if !WORD_REGISTER_OPERATIONS
- && (((GET_MODE_BITSIZE (GET_MODE (operand))
- < BIGGEST_ALIGNMENT)
- && (GET_MODE_SIZE (operand_mode[i])
- > GET_MODE_SIZE (GET_MODE (operand))))
+ && (WORD_REGISTER_OPERATIONS
+ || ((GET_MODE_BITSIZE (GET_MODE (operand))
+ < BIGGEST_ALIGNMENT)
+ && (GET_MODE_SIZE (operand_mode[i])
+ > GET_MODE_SIZE (GET_MODE (operand))))
|| BYTES_BIG_ENDIAN
-#ifdef LOAD_EXTEND_OP
- || (GET_MODE_SIZE (operand_mode[i]) <= UNITS_PER_WORD
+ || ((GET_MODE_SIZE (operand_mode[i])
+ <= UNITS_PER_WORD)
&& (GET_MODE_SIZE (GET_MODE (operand))
<= UNITS_PER_WORD)
&& (GET_MODE_SIZE (operand_mode[i])
> GET_MODE_SIZE (GET_MODE (operand)))
&& INTEGRAL_MODE_P (GET_MODE (operand))
- && LOAD_EXTEND_OP (GET_MODE (operand)) != UNKNOWN)
-#endif
- )
-#endif
- )
+ && LOAD_EXTEND_OP (GET_MODE (operand))
+ != UNKNOWN)))
)
force_reload = 1;
}
diff --git a/gcc/reload1.c b/gcc/reload1.c
index 4b9c7c7dcaf..4ee3840850e 100644
--- a/gcc/reload1.c
+++ b/gcc/reload1.c
@@ -2819,18 +2819,16 @@ eliminate_regs_1 (rtx x, machine_mode mem_mode, rtx insn,
if (MEM_P (new_rtx)
&& ((x_size < new_size
-#if WORD_REGISTER_OPERATIONS
- /* On these machines, combine can create rtl of the form
+ /* On RISC machines, combine can create rtl of the form
(set (subreg:m1 (reg:m2 R) 0) ...)
where m1 < m2, and expects something interesting to
happen to the entire word. Moreover, it will use the
(reg:m2 R) later, expecting all bits to be preserved.
So if the number of words is the same, preserve the
subreg so that push_reload can see it. */
- && ! ((x_size - 1) / UNITS_PER_WORD
- == (new_size -1 ) / UNITS_PER_WORD)
-#endif
- )
+ && !(WORD_REGISTER_OPERATIONS
+ && (x_size - 1) / UNITS_PER_WORD
+ == (new_size -1 ) / UNITS_PER_WORD))
|| x_size == new_size)
)
return adjust_address_nv (new_rtx, GET_MODE (x), SUBREG_BYTE (x));
@@ -8703,7 +8701,6 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
#endif
else if (REG_P (out) && UNARY_P (in))
{
- rtx insn;
rtx op1;
rtx out_moded;
rtx_insn *set;
@@ -8728,13 +8725,13 @@ gen_reload (rtx out, rtx in, int opnum, enum reload_type type)
gen_reload (out_moded, op1, opnum, type);
- insn = gen_rtx_SET (out, gen_rtx_fmt_e (GET_CODE (in), GET_MODE (in),
- out_moded));
- insn = emit_insn_if_valid_for_reload (insn);
+ rtx temp = gen_rtx_SET (out, gen_rtx_fmt_e (GET_CODE (in), GET_MODE (in),
+ out_moded));
+ rtx_insn *insn = emit_insn_if_valid_for_reload (temp);
if (insn)
{
set_unique_reg_note (insn, REG_EQUIV, in);
- return as_a <rtx_insn *> (insn);
+ return insn;
}
fatal_insn ("failure trying to reload:", set);
diff --git a/gcc/reorg.c b/gcc/reorg.c
index 799d27b064f..caad82a0305 100644
--- a/gcc/reorg.c
+++ b/gcc/reorg.c
@@ -222,11 +222,11 @@ static void steal_delay_list_from_fallthrough (rtx_insn *, rtx, rtx_sequence *,
static void try_merge_delay_insns (rtx_insn *, rtx_insn *);
static rtx_insn *redundant_insn (rtx, rtx_insn *, const vec<rtx_insn *> &);
static int own_thread_p (rtx, rtx, int);
-static void update_block (rtx_insn *, rtx);
+static void update_block (rtx_insn *, rtx_insn *);
static int reorg_redirect_jump (rtx_jump_insn *, rtx);
static void update_reg_dead_notes (rtx_insn *, rtx_insn *);
static void fix_reg_dead_note (rtx_insn *, rtx);
-static void update_reg_unused_notes (rtx, rtx);
+static void update_reg_unused_notes (rtx_insn *, rtx);
static void fill_simple_delay_slots (int);
static void fill_slots_from_thread (rtx_jump_insn *, rtx, rtx, rtx,
int, int, int, int,
@@ -1703,7 +1703,7 @@ own_thread_p (rtx thread, rtx label, int allow_fallthrough)
BARRIER in relax_delay_slots. */
static void
-update_block (rtx_insn *insn, rtx where)
+update_block (rtx_insn *insn, rtx_insn *where)
{
/* Ignore if this was in a delay slot and it came from the target of
a branch. */
@@ -1805,7 +1805,7 @@ fix_reg_dead_note (rtx_insn *start_insn, rtx stop_insn)
does. */
static void
-update_reg_unused_notes (rtx insn, rtx redundant_insn)
+update_reg_unused_notes (rtx_insn *insn, rtx redundant_insn)
{
rtx link, next;
@@ -3118,7 +3118,6 @@ relax_delay_slots (rtx_insn *first)
{
rtx_insn *insn, *next;
rtx_sequence *pat;
- rtx trial;
rtx_insn *delay_insn;
rtx target_label;
@@ -3271,10 +3270,10 @@ relax_delay_slots (rtx_insn *first)
for (i = 0; i < XVECLEN (pat, 0); i++)
INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
- trial = PREV_INSN (insn);
+ rtx_insn *prev = PREV_INSN (insn);
delete_related_insns (insn);
gcc_assert (GET_CODE (pat) == SEQUENCE);
- add_insn_after (delay_insn, trial, NULL);
+ add_insn_after (delay_insn, prev, NULL);
after = delay_insn;
for (i = 1; i < pat->len (); i++)
after = emit_copy_of_insn_after (pat->insn (i), after);
@@ -3295,9 +3294,9 @@ relax_delay_slots (rtx_insn *first)
/* If this jump goes to another unconditional jump, thread it, but
don't convert a jump into a RETURN here. */
- trial = skip_consecutive_labels (follow_jumps (target_label,
- delay_jump_insn,
- &crossing));
+ rtx trial = skip_consecutive_labels (follow_jumps (target_label,
+ delay_jump_insn,
+ &crossing));
if (ANY_RETURN_P (trial))
trial = find_end_label (trial);
@@ -3401,10 +3400,10 @@ relax_delay_slots (rtx_insn *first)
for (i = 0; i < XVECLEN (pat, 0); i++)
INSN_FROM_TARGET_P (XVECEXP (pat, 0, i)) = 0;
- trial = PREV_INSN (insn);
+ rtx_insn *prev = PREV_INSN (insn);
delete_related_insns (insn);
gcc_assert (GET_CODE (pat) == SEQUENCE);
- add_insn_after (delay_jump_insn, trial, NULL);
+ add_insn_after (delay_jump_insn, prev, NULL);
after = delay_jump_insn;
for (i = 1; i < pat->len (); i++)
after = emit_copy_of_insn_after (pat->insn (i), after);
diff --git a/gcc/rtl-tests.c b/gcc/rtl-tests.c
index 4e534b2316f..228226bbb68 100644
--- a/gcc/rtl-tests.c
+++ b/gcc/rtl-tests.c
@@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see
#include "cfgbuild.h"
#include "print-rtl.h"
#include "selftest.h"
+#include "selftest-rtl.h"
#include "function.h"
#include "memmodel.h"
#include "emit-rtl.h"
@@ -60,7 +61,7 @@ verify_print_pattern (const char *expected, rtx pat)
/* Verify that X is dumped as EXPECTED_DUMP, using compact mode.
Use LOC as the effective location when reporting errors. */
-static void
+void
assert_rtl_dump_eq (const location &loc, const char *expected_dump, rtx x)
{
named_temp_file tmp_out (".rtl");
@@ -74,18 +75,13 @@ assert_rtl_dump_eq (const location &loc, const char *expected_dump, rtx x)
free (dump);
}
-/* Verify that RTX is dumped as EXPECTED_DUMP, using compact mode. */
-
-#define ASSERT_RTL_DUMP_EQ(EXPECTED_DUMP, RTX) \
- assert_rtl_dump_eq (SELFTEST_LOCATION, (EXPECTED_DUMP), (RTX))
-
/* Verify that regs are dumped as expected (in compact mode). */
static void
test_dumping_regs ()
{
/* Dumps of hard regs contain a target-specific name, so we don't test
- it here. */
+ it here; this can be tested in target-specific selftests. */
/* Test dumping of virtual regs. The various virtual regs are inited as
Pmode, so this is target-specific. The tests below assume DImode, so
@@ -126,7 +122,7 @@ test_dumping_insns ()
/* Labels. */
rtx_insn *label = gen_label_rtx ();
CODE_LABEL_NUMBER (label) = 42;
- ASSERT_RTL_DUMP_EQ ("(clabel 0 42 \"\")\n", label);
+ ASSERT_RTL_DUMP_EQ ("(clabel 0 42)\n", label);
LABEL_NAME (label)= "some_label";
ASSERT_RTL_DUMP_EQ ("(clabel 0 42 (\"some_label\"))\n", label);
@@ -180,8 +176,7 @@ test_uncond_jump ()
ASSERT_TRUE (control_flow_insn_p (jump_insn));
ASSERT_RTL_DUMP_EQ ("(cjump_insn 1 (set (pc)\n"
- " (label_ref 0))\n"
- " (nil))\n",
+ " (label_ref 0)))\n",
jump_insn);
}
diff --git a/gcc/rtl.h b/gcc/rtl.h
index d054c6c905d..7a44e3bd3ef 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2858,7 +2858,7 @@ extern rtx_call_insn *last_call_insn (void);
extern rtx_insn *previous_insn (rtx_insn *);
extern rtx_insn *next_insn (rtx_insn *);
extern rtx_insn *prev_nonnote_insn (rtx_insn *);
-extern rtx_insn *prev_nonnote_insn_bb (rtx);
+extern rtx_insn *prev_nonnote_insn_bb (rtx_insn *);
extern rtx_insn *next_nonnote_insn (rtx_insn *);
extern rtx_insn *next_nonnote_insn_bb (rtx_insn *);
extern rtx_insn *prev_nondebug_insn (rtx_insn *);
@@ -3019,7 +3019,8 @@ extern rtx alloc_reg_note (enum reg_note, rtx, rtx);
extern void add_reg_note (rtx, enum reg_note, rtx);
extern void add_int_reg_note (rtx, enum reg_note, int);
extern void add_shallow_copy_of_reg_note (rtx_insn *, rtx);
-extern void remove_note (rtx, const_rtx);
+extern rtx duplicate_reg_note (rtx);
+extern void remove_note (rtx_insn *, const_rtx);
extern void remove_reg_equal_equiv_notes (rtx_insn *);
extern void remove_reg_equal_equiv_notes_for_regno (unsigned int);
extern int side_effects_p (const_rtx);
diff --git a/gcc/rtlanal.c b/gcc/rtlanal.c
index 4e600c0de6d..4d7aad0dff0 100644
--- a/gcc/rtlanal.c
+++ b/gcc/rtlanal.c
@@ -2304,10 +2304,24 @@ add_shallow_copy_of_reg_note (rtx_insn *insn, rtx note)
add_reg_note (insn, REG_NOTE_KIND (note), XEXP (note, 0));
}
+/* Duplicate NOTE and return the copy. */
+rtx
+duplicate_reg_note (rtx note)
+{
+ reg_note kind = REG_NOTE_KIND (note);
+
+ if (GET_CODE (note) == INT_LIST)
+ return gen_rtx_INT_LIST ((machine_mode) kind, XINT (note, 0), NULL_RTX);
+ else if (GET_CODE (note) == EXPR_LIST)
+ return alloc_reg_note (kind, copy_insn_1 (XEXP (note, 0)), NULL_RTX);
+ else
+ return alloc_reg_note (kind, XEXP (note, 0), NULL_RTX);
+}
+
/* Remove register note NOTE from the REG_NOTES of INSN. */
void
-remove_note (rtx insn, const_rtx note)
+remove_note (rtx_insn *insn, const_rtx note)
{
rtx link;
@@ -2328,7 +2342,7 @@ remove_note (rtx insn, const_rtx note)
{
case REG_EQUAL:
case REG_EQUIV:
- df_notes_rescan (as_a <rtx_insn *> (insn));
+ df_notes_rescan (insn);
break;
default:
break;
@@ -4361,13 +4375,11 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
return UINTVAL (x);
case MEM:
-#ifdef LOAD_EXTEND_OP
/* In many, if not most, RISC machines, reading a byte from memory
zeros the rest of the register. Noticing that fact saves a lot
of extra zero-extends. */
if (LOAD_EXTEND_OP (GET_MODE (x)) == ZERO_EXTEND)
nonzero &= GET_MODE_MASK (GET_MODE (x));
-#endif
break;
case EQ: case NE:
@@ -4567,19 +4579,17 @@ nonzero_bits1 (const_rtx x, machine_mode mode, const_rtx known_x,
nonzero &= cached_nonzero_bits (SUBREG_REG (x), mode,
known_x, known_mode, known_ret);
-#ifdef LOAD_EXTEND_OP
- /* If this is a typical RISC machine, we only have to worry
- about the way loads are extended. */
- if (WORD_REGISTER_OPERATIONS
- && ((LOAD_EXTEND_OP (inner_mode) == SIGN_EXTEND
+ /* On many CISC machines, accessing an object in a wider mode
+ causes the high-order bits to become undefined. So they are
+ not known to be zero. */
+ if (!WORD_REGISTER_OPERATIONS
+ /* If this is a typical RISC machine, we only have to worry
+ about the way loads are extended. */
+ || ((LOAD_EXTEND_OP (inner_mode) == SIGN_EXTEND
? val_signbit_known_set_p (inner_mode, nonzero)
: LOAD_EXTEND_OP (inner_mode) != ZERO_EXTEND)
|| !MEM_P (SUBREG_REG (x))))
-#endif
{
- /* On many CISC machines, accessing an object in a wider mode
- causes the high-order bits to become undefined. So they are
- not known to be zero. */
if (GET_MODE_PRECISION (GET_MODE (x))
> GET_MODE_PRECISION (inner_mode))
nonzero |= (GET_MODE_MASK (GET_MODE (x))
@@ -4824,10 +4834,7 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
than a word and loads of that size don't sign extend, we can say
nothing about the high order bits. */
if (GET_MODE_PRECISION (GET_MODE (x)) < BITS_PER_WORD
-#ifdef LOAD_EXTEND_OP
- && LOAD_EXTEND_OP (GET_MODE (x)) != SIGN_EXTEND
-#endif
- )
+ && LOAD_EXTEND_OP (GET_MODE (x)) != SIGN_EXTEND)
return 1;
}
@@ -4868,12 +4875,10 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
break;
case MEM:
-#ifdef LOAD_EXTEND_OP
/* Some RISC machines sign-extend all loads of smaller than a word. */
if (LOAD_EXTEND_OP (GET_MODE (x)) == SIGN_EXTEND)
return MAX (1, ((int) bitwidth
- (int) GET_MODE_PRECISION (GET_MODE (x)) + 1));
-#endif
break;
case CONST_INT:
@@ -4910,7 +4915,6 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
- bitwidth)));
}
-#ifdef LOAD_EXTEND_OP
/* For paradoxical SUBREGs on machines where all register operations
affect the entire register, just look inside. Note that we are
passing MODE to the recursive call, so the number of sign bit copies
@@ -4927,7 +4931,6 @@ num_sign_bit_copies1 (const_rtx x, machine_mode mode, const_rtx known_x,
&& MEM_P (SUBREG_REG (x)))
return cached_num_sign_bit_copies (SUBREG_REG (x), mode,
known_x, known_mode, known_ret);
-#endif
break;
case SIGN_EXTRACT:
diff --git a/gcc/sanitizer.def b/gcc/sanitizer.def
index 303c1e46df4..3db08a7b702 100644
--- a/gcc/sanitizer.def
+++ b/gcc/sanitizer.def
@@ -34,7 +34,7 @@ DEF_BUILTIN_STUB(BEGIN_SANITIZER_BUILTINS, (const char *)0)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_VERSION_MISMATCH_CHECK,
- "__asan_version_mismatch_check_v6",
+ "__asan_version_mismatch_check_v8",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
/* Do not reorder the BUILT_IN_ASAN_{REPORT,CHECK}* builtins, e.g. cfgcleanup.c
relies on this order. */
@@ -165,6 +165,10 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_BEFORE_DYNAMIC_INIT,
DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_AFTER_DYNAMIC_INIT,
"__asan_after_dynamic_init",
BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_CLOBBER_N, "__asan_poison_stack_memory",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
+DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_UNCLOBBER_N, "__asan_unpoison_stack_memory",
+ BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST)
/* Thread Sanitizer */
DEF_SANITIZER_BUILTIN(BUILT_IN_TSAN_INIT, "__tsan_init",
diff --git a/gcc/sanopt.c b/gcc/sanopt.c
index 8a6fbe9da95..320e14e9421 100644
--- a/gcc/sanopt.c
+++ b/gcc/sanopt.c
@@ -732,6 +732,9 @@ pass_sanopt::execute (function *fun)
case IFN_ASAN_CHECK:
no_next = asan_expand_check_ifn (&gsi, use_calls);
break;
+ case IFN_ASAN_MARK:
+ no_next = asan_expand_mark_ifn (&gsi);
+ break;
default:
break;
}
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index 26bc1422167..02157b4c736 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -5762,6 +5762,11 @@ create_copy_of_insn_rtx (rtx insn_rtx)
res = create_insn_rtx_from_pattern (copy_rtx (PATTERN (insn_rtx)),
NULL_RTX);
+ /* Locate the end of existing REG_NOTES in NEW_RTX. */
+ rtx *ptail = &REG_NOTES (res);
+ while (*ptail != NULL_RTX)
+ ptail = &XEXP (*ptail, 1);
+
/* Copy all REG_NOTES except REG_EQUAL/REG_EQUIV and REG_LABEL_OPERAND
since mark_jump_label will make them. REG_LABEL_TARGETs are created
there too, but are supposed to be sticky, so we copy them. */
@@ -5770,11 +5775,8 @@ create_copy_of_insn_rtx (rtx insn_rtx)
&& REG_NOTE_KIND (link) != REG_EQUAL
&& REG_NOTE_KIND (link) != REG_EQUIV)
{
- if (GET_CODE (link) == EXPR_LIST)
- add_reg_note (res, REG_NOTE_KIND (link),
- copy_insn_1 (XEXP (link, 0)));
- else
- add_reg_note (res, REG_NOTE_KIND (link), XEXP (link, 0));
+ *ptail = duplicate_reg_note (link);
+ ptail = &XEXP (*ptail, 1);
}
return res;
diff --git a/gcc/selftest-rtl.h b/gcc/selftest-rtl.h
new file mode 100644
index 00000000000..0f0e1673ab3
--- /dev/null
+++ b/gcc/selftest-rtl.h
@@ -0,0 +1,45 @@
+/* A self-testing framework, for use by -fself-test.
+ Copyright (C) 2016 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#ifndef GCC_SELFTEST_RTL_H
+#define GCC_SELFTEST_RTL_H
+
+/* The selftest code should entirely disappear in a production
+ configuration, hence we guard all of it with #if CHECKING_P. */
+
+#if CHECKING_P
+
+namespace selftest {
+
+/* Verify that X is dumped as EXPECTED_DUMP, using compact mode.
+ Use LOC as the effective location when reporting errors. */
+
+extern void
+assert_rtl_dump_eq (const location &loc, const char *expected_dump, rtx x);
+
+/* Verify that RTX is dumped as EXPECTED_DUMP, using compact mode. */
+
+#define ASSERT_RTL_DUMP_EQ(EXPECTED_DUMP, RTX) \
+ assert_rtl_dump_eq (SELFTEST_LOCATION, (EXPECTED_DUMP), (RTX))
+
+} /* end of namespace selftest. */
+
+#endif /* #if CHECKING_P */
+
+#endif /* GCC_SELFTEST_RTL_H */
diff --git a/gcc/selftest-run-tests.c b/gcc/selftest-run-tests.c
index 54a9b0f6c7e..a4cdb555436 100644
--- a/gcc/selftest-run-tests.c
+++ b/gcc/selftest-run-tests.c
@@ -22,6 +22,7 @@ along with GCC; see the file COPYING3. If not see
#include "coretypes.h"
#include "selftest.h"
#include "tree.h"
+#include "target.h"
#include "langhooks.h"
/* This function needed to be split out from selftest.c as it references
@@ -77,6 +78,12 @@ selftest::run_tests ()
/* This one relies on most of the above. */
function_tests_c_tests ();
+ /* Run any target-specific selftests. */
+ if (targetm.run_target_selftests)
+ targetm.run_target_selftests ();
+
+ store_merging_c_tests ();
+
/* Run any lang-specific selftests. */
lang_hooks.run_lang_selftests ();
diff --git a/gcc/selftest.h b/gcc/selftest.h
index 845eb01b125..dcce474be6e 100644
--- a/gcc/selftest.h
+++ b/gcc/selftest.h
@@ -179,6 +179,7 @@ extern void selftest_c_tests ();
extern void spellcheck_c_tests ();
extern void spellcheck_tree_c_tests ();
extern void sreal_c_tests ();
+extern void store_merging_c_tests ();
extern void typed_splay_tree_c_tests ();
extern void tree_c_tests ();
extern void tree_cfg_c_tests ();
diff --git a/gcc/target.def b/gcc/target.def
index 7dc1d6ec02d..2b357494ede 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -2639,7 +2639,7 @@ DEFHOOK
insns are saved in @var{gen_seq}. They will be emitted when all the\n\
compares in the the conditional comparision are generated without error.\n\
@var{code} is the @code{rtx_code} of the compare for @var{op0} and @var{op1}.",
- rtx, (rtx *prep_seq, rtx *gen_seq, int code, tree op0, tree op1),
+ rtx, (rtx_insn **prep_seq, rtx_insn **gen_seq, int code, tree op0, tree op1),
NULL)
DEFHOOK
@@ -2656,7 +2656,7 @@ DEFHOOK
be appropriate for passing to @code{gen_ccmp_next} or @code{cbranch_optab}.\n\
@var{code} is the @code{rtx_code} of the compare for @var{op0} and @var{op1}.\n\
@var{bit_code} is @code{AND} or @code{IOR}, which is the op on the compares.",
- rtx, (rtx *prep_seq, rtx *gen_seq, rtx prev, int cmp_code, tree op0, tree op1, int bit_code),
+ rtx, (rtx_insn **prep_seq, rtx_insn **gen_seq, rtx prev, int cmp_code, tree op0, tree op1, int bit_code),
NULL)
/* Return a new value for loop unroll size. */
@@ -5051,6 +5051,16 @@ DEFHOOK
machine_mode, (enum insn_code icode),
default_cstore_mode)
+/* This target hook allows the backend to compute the register pressure
+ classes to use. */
+DEFHOOK
+(compute_pressure_classes,
+ "A target hook which lets a backend compute the set of pressure classes to\
+ be used by those optimization passes which take register pressure into\
+ account, as opposed to letting IRA compute them. It returns the number of\
+ register classes stored in the array @var{pressure_classes}.",
+ int, (enum reg_class *pressure_classes), NULL)
+
/* True if a structure, union or array with MODE containing FIELD should
be accessed using BLKmode. */
DEFHOOK
@@ -5067,6 +5077,15 @@ Normally, this is not needed.",
bool, (const_tree field, machine_mode mode),
default_member_type_forces_blk)
+/* See tree-ssa-math-opts.c:divmod_candidate_p for conditions
+ that gate the divod transform. */
+DEFHOOK
+(expand_divmod_libfunc,
+ "Define this hook for enabling divmod transform if the port does not have\n\
+hardware divmod insn but defines target-specific divmod libfuncs.",
+ void, (rtx libfunc, machine_mode mode, rtx op0, rtx op1, rtx *quot, rtx *rem),
+ NULL)
+
/* Return the class for a secondary reload, and fill in extra information. */
DEFHOOK
(secondary_reload,
@@ -5944,6 +5963,24 @@ comparison code or operands.",
void, (int *code, rtx *op0, rtx *op1, bool op0_preserve_value),
default_canonicalize_comparison)
+DEFHOOK
+(min_arithmetic_precision,
+ "On some RISC architectures with 64-bit registers, the processor also\n\
+maintains 32-bit condition codes that make it possible to do real 32-bit\n\
+arithmetic, although the operations are performed on the full registers.\n\
+\n\
+On such architectures, defining this hook to 32 tells the compiler to try\n\
+using 32-bit arithmetical operations setting the condition codes instead\n\
+of doing full 64-bit arithmetic.\n\
+\n\
+More generally, define this hook on RISC architectures if you want the\n\
+compiler to try using arithmetical operations setting the condition codes\n\
+with a precision lower than the word precision.\n\
+\n\
+You need not define this hook if @code{WORD_REGISTER_OPERATIONS} is not\n\
+defined to 1.",
+ unsigned int, (void), default_min_arithmetic_precision)
+
DEFHOOKPOD
(atomic_test_and_set_trueval,
"This value should be set if the result written by\
@@ -6141,6 +6178,12 @@ HOOK_VECTOR_END (mode_switching)
#include "target-insns.def"
#undef DEF_TARGET_INSN
+DEFHOOK
+(run_target_selftests,
+ "If selftests are enabled, run any selftests for this target.",
+ void, (void),
+ NULL)
+
/* Close the 'struct gcc_target' definition. */
HOOK_VECTOR_END (C90_EMPTY_HACK)
diff --git a/gcc/targhooks.c b/gcc/targhooks.c
index d6fd8b8a77f..866747a9ddf 100644
--- a/gcc/targhooks.c
+++ b/gcc/targhooks.c
@@ -2127,4 +2127,12 @@ default_max_noce_ifcvt_seq_cost (edge e)
return BRANCH_COST (true, predictable_p) * COSTS_N_INSNS (3);
}
+/* Default implementation of TARGET_MIN_ARITHMETIC_PRECISION. */
+
+unsigned int
+default_min_arithmetic_precision (void)
+{
+ return WORD_REGISTER_OPERATIONS ? BITS_PER_WORD : BITS_PER_UNIT;
+}
+
#include "gt-targhooks.h"
diff --git a/gcc/targhooks.h b/gcc/targhooks.h
index afb1c00caf4..94f5e31f80f 100644
--- a/gcc/targhooks.h
+++ b/gcc/targhooks.h
@@ -260,7 +260,7 @@ extern void default_setup_incoming_vararg_bounds (cumulative_args_t ca ATTRIBUTE
int second_time ATTRIBUTE_UNUSED);
extern bool default_optab_supported_p (int, machine_mode, machine_mode,
optimization_type);
-
extern unsigned int default_max_noce_ifcvt_seq_cost (edge);
+extern unsigned int default_min_arithmetic_precision (void);
#endif /* GCC_TARGHOOKS_H */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 3a4041de42d..5da9220fe71 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,6 +1,603 @@
+2016-11-09 Thomas Preud'homme <thomas.preudhomme@arm.com>
+
+ PR testsuite/78269
+ * g++.dg/cpp1z/noexcept-type9.C: Make it a compile test.
+
+2016-11-09 Paul Thomas <pault@gcc.gnu.org>
+
+ * gfortran.dg/move_alloc_18.f90: New test.
+
+2016-11-09 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR middle-end/78256
+ * gcc.dg/pr35691-1.c (foo): Use & instead of &&.
+ * gcc.dg/pr35691-2.c (foo): Use | instead of ||.
+
+2016-11-09 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/71894
+ * gfortran.dg/class_59.f90: New test.
+
+2016-11-09 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78007
+ * gcc.dg/vect/vect-bswap32.c: Adjust.
+ * gcc.dg/vect/vect-bswap64.c: Likewise.
+
+2016-11-09 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ * gcc.dg/ipa/vrp7.c: New test.
+
+2016-11-09 Kugan Vivekanandarajah <kuganv@linaro.org>
+
+ PR ipa/78121
+ * gcc.dg/ipa/pr78121.c: New test.
+
+2016-11-09 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * c-c++-common/asan/default_options.h: New file.
+ * c-c++-common/asan/strcasestr-1.c: New test.
+ * c-c++-common/asan/strcasestr-2.c: Likewise.
+ * c-c++-common/asan/strcspn-1.c: Likewise.
+ * c-c++-common/asan/strcspn-2.c: Likewise.
+ * c-c++-common/asan/strpbrk-1.c: Likewise.
+ * c-c++-common/asan/strpbrk-2.c: Likewise.
+ * c-c++-common/asan/strspn-1.c: Likewise.
+ * c-c++-common/asan/strspn-2.c: Likewise.
+ * c-c++-common/asan/strstr-1.c: Likewise.
+ * c-c++-common/asan/strstr-2.c: Likewise.
+ * c-c++-common/asan/halt_on_error_suppress_equal_pcs-1.c: Likewise.
+
+2016-11-09 Maxim Ostapenko <m.ostapenko@samsung.com>
+
+ * c-c++-common/asan/null-deref-1.c: Adjust testcase.
+
+2016-11-08 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/68440
+ * gfortran.dg/class_58.f90: New test.
+
+2016-11-08 Uros Bizjak <ubizjak@gmail.com>
+
+ PR target/70799
+ * gcc.target/i386/pr70799-2.c: New test.
+
+2016-11-08 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/77596
+ * gfortran.dg/proc_ptr_comp_46.f90: New test.
+
+2016-11-08 Bin Cheng <bin.cheng@arm.com>
+
+ * gcc.dg/vect/pr56541.c: Xfail on !vect_cond_mixed targets.
+
+2016-11-08 Bin Cheng <bin.cheng@arm.com>
+
+ * gcc.dg/tree-ssa/pr71347.c: Drop xfail.
+
+2016-11-08 Bin Cheng <bin.cheng@arm.com>
+
+ * gcc.dg/vect/vect-cond-2.c: Drop xfail.
+
+2016-11-08 Martin Liska <mliska@suse.cz>
+
+ PR testsuite/78242
+ * g++.dg/asan/use-after-scope-4.C: New test.
+ * g++.dg/asan/use-after-scope-types-4.C: Update scanned pattern.
+ * gcc.dg/asan/use-after-scope-8.c: Remove.
+
+2016-11-08 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/vect/vect-nb-iter-ub-2.c: Adjust.
+
+2016-11-08 Tamar Christina <tamar.christina@arm.com>
+
+ PR testsuite/78136
+ * gcc.dg/cpp/trad/trad.exp
+ (dg-runtest): Added $srcdir/$subdir/ to Include dirs.
+ * gcc.dg/cpp/trad/include.c: Use local header file.
+
+2016-11-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78205
+ * gcc.dg/vect/bb-slp-pr78205.c: New testcase.
+
+2016-11-08 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78224
+ * g++.dg/torture/pr78224.C: New testcase.
+
+2016-11-08 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
+
+ * gcc.dg/store_merging_1.c: Require store_merge.
+ * gcc.dg/store_merging_2.c: Likewise.
+ * gcc.dg/store_merging_4.c: Likewise.
+ * gcc.dg/store_merging_5.c: Likewise.
+ * gcc.dg/store_merging_6.c: Likewise.
+ * gcc.dg/store_merging_7.c: Likewise.
+ * gcc.dg/store_merging_8.c: Likewise.
+ * lib/target-supports.exp (check_effective_target_store_merge): New.
+
+2016-11-07 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.target/powerpc/fold-vec-add-1.c: Add dg-options -maltivec.
+ * gcc.target/powerpc/fold-vec-add-2.c: Add dg-options -maltivec.
+ * gcc.target/powerpc/fold-vec-add-3.c: Add dg-options -maltivec.
+ * gcc.target/powerpc/fold-vec-add-4.c: Add dg-options -maltivec
+ -mvsx -mpower8-vector.
+ * gcc.target/powerpc/fold-vec-add-5.c: Add dg-options -maltivec -mno-vsx.
+ * gcc.target/powerpc/fold-vec-add-6.c: Add dg-options -maltivec -mvsx.
+ * gcc.target/powerpc/fold-vec-add-7.c: Add dg-options -maltivec
+ -mvsx -mpower8-vector.
+
+2016-11-07 David Edelsohn <dje.gcc@gmail.com>
+
+ * lib/scanasm.exp (hidden-scan-for): Add XCOFF support.
+
+ * gfortran.dg/implicit_class_1.f90: Skip on AIX.
+ * gcc.dg/visibility-14.c: XFAIL AIX.
+ * gcc.dg/visibility-15.c: XFAIL AIX.
+ * gcc.dg/visibility-16.c: XFAIL AIX.
+ * gcc.dg/visibility-17.c: XFAIL AIX.
+ * gcc.dg/visibility-18.c: XFAIL AIX.
+ * gcc.dg/visibility-19.c: XFAIL AIX.
+ * g++.dg/ext/visibility/anon1.C: XFAIL AIX.
+ * g++.dg/ext/visibility/anon2.C: XFAIL AIX.
+ * g++.dg/ext/visibility/pragma-override1.C: XFAIL AIX.
+ * g++.dg/ext/visibility/pragma-override2.C: XFAIL AIX.
+
+2016-11-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/78227
+ * gcc.target/i386/pr78227-1.c: New test.
+ * gcc.target/i386/pr78227-2.c: New test.
+
+2016-11-07 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+
+ PR middle-end/35691
+ * gcc.dg/pr35691-1.c: New test-case.
+ * gcc.dg/pr35691-2.c: Likewise.
+
+2016-11-07 Bernd Schmidt <bschmidt@redhat.com>
+
+ PR rtl-optimization/77309
+ * gcc.dg/torture/pr77309.c: New test.
+
+2016-11-07 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/71529
+ * gcc.target/i386/pr71529.C: Moved to ...
+ * g++.dg/opt/pr71529.C: ... here. New test. Guard for i?86/x86_64.
+
+ PR target/64411
+ * gcc.target/i386/pr64411.C: Moved to ...
+ * g++.dg/opt/pr64411.C: ... here. New test. Guard for i?86/x86_64
+ lp64.
+
+ PR target/65105
+ * gcc.target/i386/pr65105-4.C: Moved to ...
+ * g++.dg/opt/pr65105-4.C: ... here. New test. Guard for i?86/x86_64.
+ Run into compile test rather than execute test.
+
+2016-11-07 Richard Biener <rguenther@suse.de>
+
+ PR target/78229
+ * g++.dg/pr78229.C: New testcase.
+
+2016-11-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78218
+ * gcc.dg/torture/pr78218.c: New testcase.
+
+2016-11-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78228
+ * gcc.dg/tree-ssa/phi-opt-15.c: New testcase.
+
+2016-11-07 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR target/77822
+ * g++.dg/torture/pr77822.C: New test.
+
+2016-11-07 Martin Liska <mliska@suse.cz>
+
+ * c-c++-common/asan/force-inline-opt0-1.c: Disable
+ -f-sanitize-address-use-after-scope.
+ * c-c++-common/asan/inc.c: Change number of expected ASAN_CHECK
+ internal fn calls.
+ * g++.dg/asan/use-after-scope-1.C: New test.
+ * g++.dg/asan/use-after-scope-2.C: Likewise.
+ * g++.dg/asan/use-after-scope-3.C: Likewise.
+ * g++.dg/asan/use-after-scope-types-1.C: Likewise.
+ * g++.dg/asan/use-after-scope-types-2.C: Likewise.
+ * g++.dg/asan/use-after-scope-types-3.C: Likewise.
+ * g++.dg/asan/use-after-scope-types-4.C: Likewise.
+ * g++.dg/asan/use-after-scope-types-5.C: Likewise.
+ * g++.dg/asan/use-after-scope-types.h: Likewise.
+ * gcc.dg/asan/use-after-scope-1.c: Likewise.
+ * gcc.dg/asan/use-after-scope-2.c: Likewise.
+ * gcc.dg/asan/use-after-scope-3.c: Likewise.
+ * gcc.dg/asan/use-after-scope-4.c: Likewise.
+ * gcc.dg/asan/use-after-scope-5.c: Likewise.
+ * gcc.dg/asan/use-after-scope-6.c: Likewise.
+ * gcc.dg/asan/use-after-scope-7.c: Likewise.
+ * gcc.dg/asan/use-after-scope-8.c: Likewise.
+ * gcc.dg/asan/use-after-scope-9.c: Likewise.
+ * gcc.dg/asan/use-after-scope-switch-1.c: Likewise.
+ * gcc.dg/asan/use-after-scope-switch-2.c: Likewise.
+ * gcc.dg/asan/use-after-scope-switch-3.c: Likewise.
+ * gcc.dg/asan/use-after-scope-goto-1.c: Likewise.
+ * gcc.dg/asan/use-after-scope-goto-2.c: Likewise.
+
+2016-11-07 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78189
+ * g++.dg/torture/pr78189.C: New testcase.
+
+2016-11-06 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.dg/Wtrampolines.c: XFAIL AIX.
+
+2016-11-06 Andre Vehreschild <vehre@gcc.gnu.org>
+
+ * gfortran.dg/allocate_with_source_14.f03: Fixed number mallocs
+ occuring.
+
+2016-11-06 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/78221
+ * arith.c (gfc_complex2real): Change gfc_warning_now to
+ gfc_warning.
+
+2016-11-05 Paul Thomas <pault@gcc.gnu.org>
+
+ * gfortran.dg/move_alloc_17.f03: New test.
+
+2016-11-05 Richard Biener <rguenther@suse.de>
+
+ PR bootstrap/78188
+ * g++.dg/ipa/pr78188.C: New test.
+
+2016-11-05 Janus Weil <janus@gcc.gnu.org>
+ Dominique d'Humieres <dominiq@lps.ens.fr>
+
+ PR fortran/69495
+ * gfortran.dg/elemental_optional_args_6.f90: Use -Wpedantic flag.
+
+2016-11-05 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/67564
+ * gfortran.dg/select_type_39.f03: New test.
+
+2016-11-04 Paul Thomas <pault@gcc.gnu.org>
+
+ PR fortran/64933
+ * gfortran.dg/associate_23.f90: New test.
+
+2016-11-04 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/77834
+ * gcc.dg/pr77834.c: New test.
+
+2016-11-04 Paolo Carlini <paolo.carlini@oracle.com>
+
+ PR c++/67980
+ * g++.dg/cpp1y/pr67980.C: New.
+
+2016-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/fold-vec-add-1.c: New.
+ * gcc.target/powerpc/fold-vec-add-2.c: New.
+ * gcc.target/powerpc/fold-vec-add-3.c: New.
+ * gcc.target/powerpc/fold-vec-add-4.c: New.
+ * gcc.target/powerpc/fold-vec-add-5.c: New.
+ * gcc.target/powerpc/fold-vec-add-6.c: New.
+ * gcc.target/powerpc/fold-vec-add-7.c: New.
+
+2016-11-04 Toma Tabacu <toma.tabacu@imgtec.com>
+
+ * gcc.target/mips/mips.exp (mips-dg-options): Downgrade to R5
+ for -mbranch-likely, infer -mno-branch-likely for R6.
+
+2016-11-04 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR c++/71973
+ * g++.dg/cpp1y/lambda-generic-udt.C: Fix builtin function declaration.
+ * g++.dg/init/new15.C: Likewise.
+ * g++.dg/ipa/inline-1.C: Likewise.
+ * g++.dg/ipa/inline-2.C: Likewise.
+ * g++.dg/lto/20080908-1_0.C: Likewise.
+ * g++.dg/tc1/dr20.C: Likewise.
+ * g++.dg/tree-ssa/inline-1.C: Likewise.
+ * g++.dg/tree-ssa/inline-2.C: Likewise.
+ * g++.old-deja/g++.law/except1.C: Likewise.
+ * g++.old-deja/g++.other/vbase5.C: Likewise.
+ * obj-c++.dg/lto/trivial-1_0.mm: Likewise.
+
+2016-11-04 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR tree-optimization/78210
+ * gcc.dg/tree-ssa/slsr-8.c: Fix slsr scan to include the
+ possibility of widening multiplies.
+
+2016-11-04 Richard Biener <rguenther@suse.de>
+
+ PR middle-end/78185
+ * gcc.dg/pr78185.c: New testcase.
+
+2016-10-04 David Edelsohn <dje.gcc@gmail.com>
+
+ * g++.dg/debug/dwarf2/ref-3.C: XFAIL AIX.
+ * g++.dg/debug/dwarf2/ref-4.C: XFAIL AIX.
+
+2016-11-03 Jakub Jelinek <jakub@redhat.com>
+ Alexandre Oliva <aoliva@redhat.com>
+ Jason Merrill <jason@redhat.com>
+
+ PR debug/28767
+ PR debug/56974
+ * g++.dg/debug/dwarf2/ptrdmem-1.C: New test.
+ * g++.dg/debug/dwarf2/ref-3.C: New test.
+ * g++.dg/debug/dwarf2/ref-4.C: New test.
+ * g++.dg/debug/dwarf2/refqual-1.C: New test.
+ * g++.dg/debug/dwarf2/refqual-2.C: New test.
+
+2016-11-03 Fritz Reese <fritzoreese@gmail.com>
+
+ * gfortran.dg/dec_exp_1.f90: New test.
+ * gfortran.dg/dec_exp_2.f90: Likewise.
+ * gfortran.dg/dec_exp_3.f90: Likewise.
+
+2016-11-03 Fritz O. Reese <fritzoreese@gmail.com>
+
+ * gfortran.dg/dec_parameter_1.f: New test.
+ * gfortran.dg/dec_parameter_2.f90: Likewise.
+ * gfortran.dg/dec_parameter_3.f90: Likewise.
+ * gfortran.dg/dec_parameter_4.f90: Likewise.
+
+2016-11-03 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/no_profile_instrument_function-attr-1.c: Update scanned
+ output.
+ * gcc.dg/tree-prof/time-profiler-3.c: New test.
+
+2016-11-03 Bernd Edlinger <bernd.edlinger@hotmail.de>
+
+ PR libgcc/78067
+ * gcc.dg/torture/fp-int-convert.h: Add more conversion tests.
+
+2016-11-03 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
+
+ * gcc.c-torture/execute/pr78170.c: Require int32plus.
+
+2016-11-02 Max Filippov <jcmvbkbc@gmail.com>
+
+ * gcc.c-torture/compile/20001226-1.c: Don't xfail on xtensa.
+
+2016-11-01 Tamar Christina <tamar.christina@arm.com>
+
+ * gcc.target/arm/simd/vmaxnm_f32_1.c (dg-require-effective-target):
+ Check for arm_v8_neon_hw.
+ * gcc.target/arm/simd/vmaxnmq_f32_1.c (dg-require-effective-target):
+ Likewise.
+ * gcc.target/arm/simd/vminnm_f32_1.c (dg-require-effective-target):
+ Likewise.
+ * gcc.target/arm/simd/vminnmq_f32_1.c(dg-require-effective-target):
+ Likewise.
+
+2016-11-02 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/store_merging_8.c: New testcase.
+
+2016-11-02 Fritz O. Reese <fritzoreese@gmail.com>
+
+ * gfortran.dg/warn_argument_mismatch_1.f90: New test.
+
+2016-11-02 David Edelsohn <dje.gcc@gmail.com>
+
+ * gcc.dg/debug/dwarf2/prod-options.c: XFAIL AIX.
+ * gcc.dg/debug/dwarf2/pr71855.c: XFAIL AIX.
+ * gcc.dg/addr_equal_1.c: XFAIL AIX.
+ * gcc.dg/pr65779.c: XFAIL AIX.
+ * gcc.dg/pr70405.c: XFAIL AIX.
+
+ * g++.dg/debug/dwarf2/inline-var-1.C: XFAIL AIX.
+ * g++.dg/debug/dwarf2/ref-2.C: XFAIL AIX.
+ * g++.dg/debug/dwarf2/constexpr-var-1.C: XFAIL AIX.
+
+2016-11-02 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
+
+ * lib/target-supports.exp (check_gc_sections_available): Use
+ -print-prog-name=ld to determine linker used.
+
+2016-11-02 Martin Liska <mliska@suse.cz>
+
+ * gcc.dg/tree-ssa/builtins-folding-gimple-ub.c (main): Add
+ test case.
+
+2016-11-02 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/78170
+ * gcc.c-torture/execute/pr78170.c: New test.
+
+2016-11-02 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ PR tree-optimization/78162
+ * gcc.c-torture/compile/pr78162.c: New test.
+
+2016-11-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/78035
+ PR tree-optimization/77964
+ * gcc.target/i386/pr78035.c: New testcase.
+
+2016-11-02 Richard Biener <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/vrp111.c: New testcase.
+ * gcc.dg/tree-ssa/pr20702.c: Disable EVRP.
+ * gcc.dg/tree-ssa/pr21086.c: Likewise.
+ * gcc.dg/tree-ssa/pr58480.c: Likewise.
+ * gcc.dg/tree-ssa/vrp08.c: Likewise.
+
+2016-11-01 David Edelsohn <dje.gcc@gmail.com>
+
+ * gfortran.dg/pr70937.f90: require-effective-target lto.
+
+2016-11-01 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/69544
+ * gfortran.dg/where_6.f90: New test.
+
+2016-11-01 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/debug/dwarf2/inline-var-1.C: New test.
+
+2016-11-01 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/69544
+ * gfortran.dg/where_5.f90: New test.
+
+2016-11-01 Bilyan Borisov <bilyan.borisov@arm.com>
+
+ * gcc.target/arm/simd/vmaxnm_f32_1.c: New.
+ * gcc.target/arm/simd/vmaxnmq_f32_1.c: Likewise.
+ * gcc.target/arm/simd/vminnm_f32_1.c: Likewise.
+ * gcc.target/arm/simd/vminnmq_f32_1.c: Likewise.
+
+2016-11-01 Uros Bizjak <ubizjak@gmail.com>
+
+ * lib/target-supports.exp: Normalize order of i?86 and x86_64 targets.
+ Whitespace fixes.
+ (check_effective_target_vect_cmdline_needed): Check
+ is-effective-target ia32 for x86 targets.
+ (check_effective_target_vect_simd_clones): Simplify condition.
+ (check_effective_target_vect_double): Ditto.
+ (check_effective_target_vect_aligned_arrays): Check
+ is-effective-target ia32 for x86 targets. Simplify condition.
+ (check_effective_target_vect_multiple_sizes): Simplify condition.
+ (check_effective_target_sqrt_insn): Add i?86-*-* target.
+ (check_effective_target_sync_int_128): Simplify condition.
+ (check_effective_target_sync_int_128_runtime): Ditto.
+ (check_effective_target_sync_long_long_runtime): Ditto.
+ (check_effective_target_divmod): Add i?86-*-* target.
+
+2016-10-31 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ * gcc.target/powerpc/vsx-extract-4.c: New test.
+ * gcc.target/powerpc/vsx-extract-5.c: Likewise.
+
+2016-10-31 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/54679
+ * gfortran.dg/fmt_l.f90: Update test.
+ * gfortran.dg/fmt_l0.f90: New test.
+
+2016-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/78089
+ * c-c++-common/builtin-shuffle-1.c: New test.
+ * g++.dg/cpp0x/addressof3.C: New test.
+
+2016-10-31 Ville Voutilainen <ville.voutilainen@gmail.com>
+
+ Add tests for a const member and a reference member for launder.
+ * g++.dg/cpp1z/launder3.C: New.
+ * g++.dg/cpp1z/launder4.C: Likewise.
+ * g++.dg/cpp1z/launder5.C: Likewise.
+ * g++.dg/cpp1z/launder5.cc: Likewise.
+ * g++.dg/cpp1z/launder5.h: Likewise.
+ * g++.dg/cpp1z/launder6.C: Likewise.
+ * g++.dg/cpp1z/launder6.cc: Likewise.
+ * g++.dg/cpp1z/launder6.h: Likewise.
+
+2016-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/77948
+ * g++.dg/cpp0x/pr77948-1.C: New test.
+ * g++.dg/cpp0x/pr77948-2.C: New test.
+ * g++.dg/cpp0x/pr77948-3.C: New test.
+ * g++.dg/cpp0x/pr77948-4.C: New test.
+ * g++.dg/cpp0x/pr77948-5.C: New test.
+ * g++.dg/cpp0x/pr77948-6.C: New test.
+
+ PR tree-optimization/77860
+ * gcc.dg/pr77860.c: New test.
+
+2016-10-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/77886
+ * g++.dg/warn/Wimplicit-fallthrough-2.C: New test.
+
+2016-10-31 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com>
+
+ * gcc.dg/lto/pr60449_0.c: Skip for avr.
+
+2016-10-30 Le-Chun Wu <lcwu@google.com>
+ Mark Wielaard <mjw@redhat.com>
+
+ * gcc.dg/Wshadow-compatible-local-1.c: New test.
+ * gcc.dg/Wshadow-local-1.c: Likewise.
+ * gcc.dg/Wshadow-local-2.c: Likewise.
+ * g++.dg/warn/Wshadow-compatible-local-1.C: Likewise.
+ * g++.dg/warn/Wshadow-local-1.C: Likewise.
+ * g++.dg/warn/Wshadow-local-2.C: Likewise.
+
+2016-10-30 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ PR tree-optimization/71915
+ PR tree-optimization/71490
+ * gcc.dg/tree-ssa/pr54245.c: Delete.
+ * gcc.dg/tree-ssa/slsr-8.c: Adjust for new optimization and
+ document why.
+
+2016-10-30 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+
+ PR fortran/78123
+ * gfortran.dg/fmt_t_9.f: New test.
+
+2016-10-30 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR fortran/67219
+ * gfortran.dg/pr67219.f90: New test.
+
+2016-10-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR rtl-optimization/77919
+ * g++.dg/torture/pr77919-2.C: New test.
+
+ PR target/78148
+ * gcc.dg/pr78148.c: New test.
+
+2016-10-28 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc.target/sparc/overflow-3.c: Replace and move old one to...
+ * gcc.target/sparc/overflow-4.c: ...here.
+ * gcc.target/sparc/overflow-5.c: New test.
+
+2016-10-28 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
+ Kugan Vivekanandarajah <kuganv@linaro.org>
+ Jim Wilson <jim.wilson@linaro.org>
+
+ PR tree-optimization/43721
+ * lib/target-supports.exp (check_effective_target_divmod): New.
+ (check_effective_target_divmod_simode): Likewise.
+ (check_effective_target_arm_divmod_simode): Likewise.
+ * gcc.dg/divmod-1-simode.c: New test.
+ * gcc.dg/divmod-1.c: Likewise.
+ * gcc.dg/divmod-2-simode.c: Likewise.
+ * gcc.dg/divmod-2.c: Likewise.
+ * gcc.dg/divmod-3-simode.c: Likewise.
+ * gcc.dg/divmod-3.c: Likewise.
+ * gcc.dg/divmod-4-simode.c: Likewise.
+ * gcc.dg/divmod-4.c: Likewise.
+ * gcc.dg/divmod-5.c: Likewise.
+ * gcc.dg/divmod-6-simode.c: Likewise.
+ * gcc.dg/divmod-6.c: Likewise.
+ * gcc.dg/divmod-7.c: Likewise.
+
2016-10-28 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
- Jakub Jelinek <jakub@redhat.com>
- Andrew Pinski <pinskia@gmail.com>
+ Jakub Jelinek <jakub@redhat.com>
+ Andrew Pinski <pinskia@gmail.com>
PR middle-end/22141
PR rtl-optimization/23684
@@ -19,7 +616,7 @@
* gcc.target/i386/pr34012.c: Add -fno-store-merging to dg-options.
* g++.dg/init/new17.C: Likewise.
-2016-10-26 Will Schmidt <will_schmidt@vnet.ibm.com>
+2016-10-26 Will Schmidt <will_schmidt@vnet.ibm.com>
PR middle-end/72747
* c-c++-common/pr72747-1.c: New test.
@@ -95,7 +692,7 @@
* gcc.dg/fold-convmaxconv-1.c: New test.
* gcc.dg/fold-convminconv-1.c: New test.
-2016-10-26 Steven G. Kargl <kargl@gcc.gnu.org>
+2016-10-26 Steven G. Kargl <kargl@gcc.gnu.org>
PR fortran/78092
* gfortran.dg/pr78092.f90: New test.
@@ -13087,6 +13684,7 @@
2016-01-28 Ilya Enkovich <enkovich.gnu@gmail.com>
* gcc.dg/declare-simd.c: New test.
+
2016-01-28 Richard Biener <rguenther@suse.de>
PR tree-optimization/69466
diff --git a/gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c b/gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c
index 0576155c284..2e156f70d06 100644
--- a/gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c
+++ b/gcc/testsuite/c-c++-common/asan/force-inline-opt0-1.c
@@ -2,6 +2,7 @@
(before and after inlining) */
/* { dg-do compile } */
+/* { dg-options "-fno-sanitize-address-use-after-scope" } */
/* { dg-final { scan-assembler-not "__asan_report_load" } } */
__attribute__((always_inline))
diff --git a/gcc/testsuite/c-c++-common/asan/inc.c b/gcc/testsuite/c-c++-common/asan/inc.c
index 5abf3731818..98121d2d2b4 100644
--- a/gcc/testsuite/c-c++-common/asan/inc.c
+++ b/gcc/testsuite/c-c++-common/asan/inc.c
@@ -16,5 +16,6 @@ main ()
return 0;
}
-/* { dg-final { scan-tree-dump-times "ASAN_" 1 "asan0" } } */
+/* { dg-final { scan-tree-dump-times "ASAN_" 4 "asan0" } } */
/* { dg-final { scan-tree-dump "ASAN_CHECK \\(.*, 4\\);" "asan0" } } */
+/* { dg-final { scan-tree-dump "ASAN_CHECK \\(.*, 8\\);" "asan0" } } */
diff --git a/gcc/testsuite/c-c++-common/asan/null-deref-1.c b/gcc/testsuite/c-c++-common/asan/null-deref-1.c
index 45d35ac2de3..f4f8f37a795 100644
--- a/gcc/testsuite/c-c++-common/asan/null-deref-1.c
+++ b/gcc/testsuite/c-c++-common/asan/null-deref-1.c
@@ -17,6 +17,6 @@ int main()
}
/* { dg-output "ERROR: AddressSanitizer:? SEGV on unknown address\[^\n\r]*" } */
-/* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */
-/* { dg-output "\[^\n\r]* #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
+/* { dg-output "0x\[0-9a-f\]+ \[^\n\r]*pc 0x\[0-9a-f\]+.*(\n|\r\n|\r)" } */
+/* { dg-output " #0 0x\[0-9a-f\]+ +(in \[^\n\r]*NullDeref\[^\n\r]* (\[^\n\r]*null-deref-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
/* { dg-output " #1 0x\[0-9a-f\]+ +(in _*main (\[^\n\r]*null-deref-1.c:15|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */
diff --git a/gcc/testsuite/c-c++-common/builtin-shuffle-1.c b/gcc/testsuite/c-c++-common/builtin-shuffle-1.c
new file mode 100644
index 00000000000..30fd69082dd
--- /dev/null
+++ b/gcc/testsuite/c-c++-common/builtin-shuffle-1.c
@@ -0,0 +1,22 @@
+/* PR c++/78089 */
+/* { dg-do run } */
+
+typedef int V __attribute__((vector_size (16)));
+V a, b, c;
+
+int
+foo ()
+{
+ return __builtin_shuffle (a, b, c)[3];
+}
+
+int
+main ()
+{
+ a = (V) { 1, 2, 3, 4 };
+ b = (V) { 5, 6, 7, 8 };
+ c = (V) { 7, 2, 5, 6 };
+ if (foo () != 7)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/asan/use-after-scope-1.C b/gcc/testsuite/g++.dg/asan/use-after-scope-1.C
new file mode 100644
index 00000000000..fd875ad7a13
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/use-after-scope-1.C
@@ -0,0 +1,21 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+#include <functional>
+
+int main() {
+ std::function<int()> function;
+ {
+ int v = 0;
+ function = [&v]()
+ {
+ return v;
+ };
+ }
+ return function();
+}
+
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size 4 at.*" }
+// { dg-output ".*'v' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/use-after-scope-2.C b/gcc/testsuite/g++.dg/asan/use-after-scope-2.C
new file mode 100644
index 00000000000..92a4bd13029
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/use-after-scope-2.C
@@ -0,0 +1,40 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+#include <stdio.h>
+
+struct Test
+{
+ Test ()
+ {
+ my_value = 0;
+ }
+
+ ~Test ()
+ {
+ fprintf (stderr, "Value: %d\n", *my_value);
+ }
+
+ void init (int *v)
+ {
+ my_value = v;
+ }
+
+ int *my_value;
+};
+
+int main(int argc, char **argv)
+{
+ Test t;
+
+ {
+ int x = argc;
+ t.init(&x);
+ }
+
+ return 0;
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size 4 at.*" }
+// { dg-output ".*'x' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/use-after-scope-3.C b/gcc/testsuite/g++.dg/asan/use-after-scope-3.C
new file mode 100644
index 00000000000..172f374704b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/use-after-scope-3.C
@@ -0,0 +1,22 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+struct IntHolder {
+ int val;
+};
+
+const IntHolder *saved;
+
+void save(const IntHolder &holder) {
+ saved = &holder;
+}
+
+int main(int argc, char *argv[]) {
+ save({10});
+ int x = saved->val; // BOOM
+ return x;
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size 4 at.*" }
+// { dg-output ".*'<unknown>' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/use-after-scope-4.C b/gcc/testsuite/g++.dg/asan/use-after-scope-4.C
new file mode 100644
index 00000000000..c3b6932609b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/use-after-scope-4.C
@@ -0,0 +1,36 @@
+/* Caused ICE in in make_decl_rtl, at varasm.c:1311. */
+/* { dg-do compile } */
+
+class A
+{
+public:
+ A () : value (123) {}
+ int value;
+};
+
+template <typename StoredFunction> class B
+{
+public:
+ template <typename F> B (F p1) : mFunction (p1) { mFunction (); }
+ StoredFunction mFunction;
+};
+template <typename Function>
+void
+NS_NewRunnableFunction (Function p1)
+{
+ (B<Function> (p1));
+}
+class C
+{
+ void DispatchConnectionCloseEvent (A);
+ void AsyncCloseConnectionWithErrorMsg (const A &);
+};
+void
+C::AsyncCloseConnectionWithErrorMsg (const A &)
+{
+ {
+ A message;
+ NS_NewRunnableFunction (
+ [this, message] { DispatchConnectionCloseEvent (message); });
+ }
+}
diff --git a/gcc/testsuite/g++.dg/asan/use-after-scope-types-1.C b/gcc/testsuite/g++.dg/asan/use-after-scope-types-1.C
new file mode 100644
index 00000000000..bedcfa4edb9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/use-after-scope-types-1.C
@@ -0,0 +1,17 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+#include "use-after-scope-types.h"
+
+int main()
+{
+ using Tests = void (*)();
+ Tests t = &test<bool>;
+ t();
+
+ return 0;
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "WRITE of size " }
+// { dg-output ".*'x' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/use-after-scope-types-2.C b/gcc/testsuite/g++.dg/asan/use-after-scope-types-2.C
new file mode 100644
index 00000000000..75a01d9eb36
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/use-after-scope-types-2.C
@@ -0,0 +1,17 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+#include "use-after-scope-types.h"
+
+int main()
+{
+ using Tests = void (*)();
+ Tests t = &test<float>;
+ t();
+
+ return 0;
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "WRITE of size " }
+// { dg-output ".*'x' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/use-after-scope-types-3.C b/gcc/testsuite/g++.dg/asan/use-after-scope-types-3.C
new file mode 100644
index 00000000000..3350c69c6ae
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/use-after-scope-types-3.C
@@ -0,0 +1,17 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+#include "use-after-scope-types.h"
+
+int main()
+{
+ using Tests = void (*)();
+ Tests t = &test<void *>;
+ t();
+
+ return 0;
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "WRITE of size " }
+// { dg-output ".*'x' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/use-after-scope-types-4.C b/gcc/testsuite/g++.dg/asan/use-after-scope-types-4.C
new file mode 100644
index 00000000000..44f4d3b09f5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/use-after-scope-types-4.C
@@ -0,0 +1,17 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+#include "use-after-scope-types.h"
+
+int main()
+{
+ using Tests = void (*)();
+ Tests t = &test<std::vector<std::string>>;
+ t();
+
+ return 0;
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size " }
+// { dg-output ".*'x' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/use-after-scope-types-5.C b/gcc/testsuite/g++.dg/asan/use-after-scope-types-5.C
new file mode 100644
index 00000000000..42abc2a0ccd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/use-after-scope-types-5.C
@@ -0,0 +1,17 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+#include "use-after-scope-types.h"
+
+int main()
+{
+ using Tests = void (*)();
+ Tests t = &test<char[1000]>;
+ t();
+
+ return 0;
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "WRITE of size " }
+// { dg-output ".*'x' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/g++.dg/asan/use-after-scope-types.h b/gcc/testsuite/g++.dg/asan/use-after-scope-types.h
new file mode 100644
index 00000000000..b96b02ba88c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/asan/use-after-scope-types.h
@@ -0,0 +1,30 @@
+#include <stdlib.h>
+#include <string>
+#include <vector>
+
+template <class T> struct Ptr {
+ void Store(T *ptr) { t = ptr; }
+
+ void Access() { *t = {}; }
+
+ T *t;
+};
+
+template <class T, size_t N> struct Ptr<T[N]> {
+ using Type = T[N];
+ void Store(Type *ptr) { t = *ptr; }
+
+ void Access() { *t = {}; }
+
+ T *t;
+};
+
+template <class T> __attribute__((noinline)) void test() {
+ Ptr<T> ptr;
+ {
+ T x;
+ ptr.Store(&x);
+ }
+
+ ptr.Access();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/addressof3.C b/gcc/testsuite/g++.dg/cpp0x/addressof3.C
new file mode 100644
index 00000000000..fa517908ae3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/addressof3.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+
+struct S { int foo (); int s; };
+int a[10];
+int b;
+S c;
+int d = __builtin_addressof (a)[0][0];
+int e = __builtin_addressof (b)[0];
+int f = __builtin_addressof (c)->foo ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-inhctor1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-inhctor1.C
index ee8757f4dcf..98691101e86 100644
--- a/gcc/testsuite/g++.dg/cpp0x/constexpr-inhctor1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-inhctor1.C
@@ -9,7 +9,7 @@ struct A
struct B : A
{
- using A::A; // { dg-error "A::i" }
+ using A::A; // { dg-prune-output "A::i" }
};
-constexpr B b(0); // { dg-error "B::B" }
+constexpr B b(0); // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor11.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor11.C
index 228e8ec6609..4fc67a4a56a 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor11.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor11.C
@@ -1,4 +1,5 @@
// { dg-do compile { target c++11 } }
+// { dg-options -fno-new-inheriting-ctors }
struct A
{
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor11a.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor11a.C
new file mode 100644
index 00000000000..61b251eb0ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor11a.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct A
+{
+ A(int, ...);
+};
+
+struct B: A
+{
+ using A::A;
+};
+
+B b1(42);
+B b2(42, 1.0); // { dg-bogus "ellipsis" "" { xfail *-*-* } }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor15.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor15.C
index c2d33bff4ff..a0b518c19d3 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor15.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor15.C
@@ -2,6 +2,7 @@
// constructors was a deliberate choice.
// { dg-do compile { target c++11 } }
+// { dg-options -fno-new-inheriting-ctors }
struct A { A(int); };
struct B: public A
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor15a.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor15a.C
new file mode 100644
index 00000000000..a9abb8428a1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor15a.C
@@ -0,0 +1,14 @@
+// P0136 caused us to start inheriting base copy constructors.
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct A { A(int); };
+struct B: public A
+{
+ using A::A;
+};
+
+A a (42);
+
+B b1 (24); // inherited
+B b2 (a); // also inherited now
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor22.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor22.C
new file mode 100644
index 00000000000..1b0e2425cc2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor22.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++11 } }
+
+class A { };
+template<typename> using UniquePtr = int;
+template<typename AllocPolicy> struct BufferList {
+ BufferList(unsigned, unsigned, unsigned, AllocPolicy = AllocPolicy());
+};
+class D : BufferList<A> {
+ using BufferList::BufferList;
+};
+template<typename , typename... Args> UniquePtr<D> MakeUnique(Args... aArgs)
+{
+ D d(aArgs...);
+ return 0;
+}
+UniquePtr<D> setCloneBuffer_impl_buf = MakeUnique<D>(0, 0, 0);
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C
index e8dc84d32ec..8cbeed66047 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor3.C
@@ -1,4 +1,5 @@
// { dg-do compile { target c++11 } }
+// { dg-options -fno-new-inheriting-ctors }
struct B1 {
B1(int);
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor3a.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor3a.C
new file mode 100644
index 00000000000..c9b4ea11412
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor3a.C
@@ -0,0 +1,21 @@
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct B1 {
+ B1(int);
+};
+struct B2 {
+ B2(int);
+};
+struct D1 : B1, B2 {
+ using B1::B1;
+ using B2::B2;
+}; // ambiguous
+struct D2 : B1, B2 {
+ using B1::B1;
+ using B2::B2;
+ D2(int); // OK: user declaration supersedes both implicit declarations
+};
+
+D2 d2(42);
+D1 d1(42); // { dg-error "ambiguous" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C
index 8c79c833a32..d0038c16a14 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor5.C
@@ -15,7 +15,7 @@ void test() {
D1 e; // { dg-error "deleted" } D1 has no default constructor
}
struct D2 : B2 {
- using B2::B2; // { dg-error "no match" } implicitly declares D2(double)
+ using B2::B2; // { dg-error "B1::B1" }
B1 b;
};
D2 f(1.0); // { dg-error "deleted" } B1 has no default constructor
diff --git a/gcc/testsuite/g++.dg/cpp0x/inh-ctor9.C b/gcc/testsuite/g++.dg/cpp0x/inh-ctor9.C
index 676605db9e9..5bfdd499d46 100644
--- a/gcc/testsuite/g++.dg/cpp0x/inh-ctor9.C
+++ b/gcc/testsuite/g++.dg/cpp0x/inh-ctor9.C
@@ -9,7 +9,7 @@ protected:
struct B: A
{
- using A::A; // { dg-message "protected" }
+ using A::A;
};
B b(42); // { dg-error "this context" }
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr77948-1.C b/gcc/testsuite/g++.dg/cpp0x/pr77948-1.C
new file mode 100644
index 00000000000..e7795e95b7f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr77948-1.C
@@ -0,0 +1,10 @@
+// PR c++/77948
+// { dg-do compile }
+// { dg-options "-std=c++11 -std=gnu++11" }
+
+void
+foo ()
+{
+ auto qfp = 1.0q; // { dg-error "unsupported" "" { target { ! has_q_floating_suffix } } }
+ auto Qfp = 1.0Q; // { dg-error "unsupported" "" { target { ! has_q_floating_suffix } } }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr77948-2.C b/gcc/testsuite/g++.dg/cpp0x/pr77948-2.C
new file mode 100644
index 00000000000..7b84c5fdea1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr77948-2.C
@@ -0,0 +1,10 @@
+// PR c++/77948
+// { dg-do compile }
+// { dg-options "-std=gnu++11 -std=c++11" }
+
+void
+foo ()
+{
+ auto qfp = 1.0q; // { dg-error "unable to find numeric literal operator" }
+ auto Qfp = 1.0Q; // { dg-error "unable to find numeric literal operator" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr77948-3.C b/gcc/testsuite/g++.dg/cpp0x/pr77948-3.C
new file mode 100644
index 00000000000..64d4f5b14cc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr77948-3.C
@@ -0,0 +1,10 @@
+// PR c++/77948
+// { dg-do compile }
+// { dg-options "-std=c++11 -std=gnu++98" }
+
+void
+foo ()
+{
+ double qfp = 1.0q; // { dg-error "unsupported" "" { target { ! has_q_floating_suffix } } }
+ double Qfp = 1.0Q; // { dg-error "unsupported" "" { target { ! has_q_floating_suffix } } }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr77948-4.C b/gcc/testsuite/g++.dg/cpp0x/pr77948-4.C
new file mode 100644
index 00000000000..7b66b983bfa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr77948-4.C
@@ -0,0 +1,10 @@
+// PR c++/77948
+// { dg-do compile }
+// { dg-options "-std=c++11 -std=c++98" }
+
+void
+foo ()
+{
+ double qfp = 1.0q; // { dg-error "unsupported" "" { target { ! has_q_floating_suffix } } }
+ double Qfp = 1.0Q; // { dg-error "unsupported" "" { target { ! has_q_floating_suffix } } }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr77948-5.C b/gcc/testsuite/g++.dg/cpp0x/pr77948-5.C
new file mode 100644
index 00000000000..bec34a15fbd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr77948-5.C
@@ -0,0 +1,10 @@
+// PR c++/77948
+// { dg-do compile }
+// { dg-options "-std=gnu++98 -std=c++11" }
+
+void
+foo ()
+{
+ auto qfp = 1.0q; // { dg-error "unable to find numeric literal operator" }
+ auto Qfp = 1.0Q; // { dg-error "unable to find numeric literal operator" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr77948-6.C b/gcc/testsuite/g++.dg/cpp0x/pr77948-6.C
new file mode 100644
index 00000000000..b8a13b5540a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr77948-6.C
@@ -0,0 +1,10 @@
+// PR c++/77948
+// { dg-do compile }
+// { dg-options "-std=c++98 -std=c++11" }
+
+void
+foo ()
+{
+ auto qfp = 1.0q; // { dg-error "unable to find numeric literal operator" }
+ auto Qfp = 1.0Q; // { dg-error "unable to find numeric literal operator" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/feat-cxx11.C b/gcc/testsuite/g++.dg/cpp1y/feat-cxx11.C
index 6928d6bcbd8..2f3b01efc38 100644
--- a/gcc/testsuite/g++.dg/cpp1y/feat-cxx11.C
+++ b/gcc/testsuite/g++.dg/cpp1y/feat-cxx11.C
@@ -109,8 +109,8 @@
#ifndef __cpp_inheriting_constructors
# error "__cpp_inheriting_constructors"
-#elif __cpp_inheriting_constructors!= 200802
-# error "__cpp_inheriting_constructors != 200802"
+#elif __cpp_inheriting_constructors!= 201511
+# error "__cpp_inheriting_constructors != 201511"
#endif
#ifndef __cpp_ref_qualifiers
diff --git a/gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C b/gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C
index dc30a9b3cf8..3b141ef67c4 100644
--- a/gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C
+++ b/gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C
@@ -102,8 +102,8 @@
#ifndef __cpp_inheriting_constructors
# error "__cpp_inheriting_constructors"
-#elif __cpp_inheriting_constructors!= 200802
-# error "__cpp_inheriting_constructors != 200802"
+#elif __cpp_inheriting_constructors!= 201511
+# error "__cpp_inheriting_constructors != 201511"
#endif
#ifndef __cpp_ref_qualifiers
diff --git a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C
index 3597fa8053a..1b0f65e6381 100644
--- a/gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C
+++ b/gcc/testsuite/g++.dg/cpp1y/lambda-generic-udt.C
@@ -14,7 +14,7 @@ struct S
bool shadow = false;
};
-extern "C" void printf(...);
+extern "C" int printf(const char*, ...);
#define assert(e) if (e); else \
printf ("%s:%d: !(%s)\n", __FILE__, __LINE__, #e), __builtin_abort ();
diff --git a/gcc/testsuite/g++.dg/cpp1y/pr67980.C b/gcc/testsuite/g++.dg/cpp1y/pr67980.C
new file mode 100644
index 00000000000..1b8154538fc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/pr67980.C
@@ -0,0 +1,23 @@
+// { dg-do compile { target c++14 } }
+
+template <int Y, class T>
+constexpr T cpp14_constexpr_then(T value) {
+ if (Y < 0)
+ return (value << -Y);
+ else
+ return 0;
+}
+
+template <int Y, class T>
+constexpr T cpp14_constexpr_else(T value) {
+ if (Y > 0)
+ return 0;
+ else
+ return (value << -Y);
+}
+
+int main()
+{
+ cpp14_constexpr_then<1>(0);
+ cpp14_constexpr_else<1>(0);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C b/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
index e023e6a622d..f4658a96067 100644
--- a/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
+++ b/gcc/testsuite/g++.dg/cpp1z/feat-cxx1z.C
@@ -90,8 +90,8 @@
#ifndef __cpp_inheriting_constructors
# error "__cpp_inheriting_constructors"
-#elif __cpp_inheriting_constructors!= 200802
-# error "__cpp_inheriting_constructors != 200802"
+#elif __cpp_inheriting_constructors!= 201511
+# error "__cpp_inheriting_constructors != 201511"
#endif
#ifndef __cpp_ref_qualifiers
@@ -380,6 +380,12 @@
# error "__cpp_capture_star_this != 201603"
#endif
+#ifndef __cpp_noexcept_function_type
+# error "__cpp_noexcept_function_type"
+#elif __cpp_noexcept_function_type != 201510
+# error "__cpp_noexcept_function_type != 201510"
+#endif
+
#ifdef __has_cpp_attribute
# if ! __has_cpp_attribute(maybe_unused)
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor1.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor1.C
new file mode 100644
index 00000000000..bf9df415c05
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor1.C
@@ -0,0 +1,5 @@
+// { dg-do compile { target c++11 } }
+
+struct A { };
+struct B: A { };
+struct C: B { using A::A; }; // { dg-error "direct" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C
new file mode 100644
index 00000000000..02ec58a3e8e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor22.C
@@ -0,0 +1,33 @@
+// Testcase from P0136
+// { dg-do compile { target c++11 } }
+
+struct B1 {
+ template <class... Ts>
+ B1(int, Ts...) { }
+};
+
+struct B2 {
+ B2(double) { }
+};
+
+int get();
+
+struct D1 : B1 { // { dg-message "B1::B1" }
+ using B1::B1; // inherits B1(int, ...)
+ int x;
+ int y = get();
+};
+
+void test() {
+ D1 d(2, 3, 4); // OK: B1 is initialized by calling B1(2, 3, 4),
+ // then d.x is default-initialized (no initialization is performed),
+ // then d.y is initialized by calling get()
+ D1 e; // { dg-error "" } D1 has a deleted default constructor
+}
+
+struct D2 : B2 {
+ using B2::B2; // { dg-message "B1::B1" }
+ B1 b;
+};
+
+D2 f(1.0); // { dg-error "" } B1 has no default constructor
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
new file mode 100644
index 00000000000..0c862f7573f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor23.C
@@ -0,0 +1,19 @@
+// Testcase from P0136
+// { dg-do compile { target c++11 } }
+// { dg-options "-fnew-inheriting-ctors -fdump-tree-gimple" }
+
+struct W { W(int); };
+struct V: W { using W::W; };
+struct X : virtual V { using V::V; X() = delete; };
+struct Y : X { using X::X; };
+struct Z : Y, virtual V { using Y::Y; };
+Z z(0); // OK: initialization of Y does not invoke default constructor of X
+
+// Check that we're passing this and __vtt along to the Y inheriting
+// constructor, but not the int parameter.
+// { dg-final { scan-assembler "_ZN1YCI21WEi" } }
+// { dg-final { scan-tree-dump "Y::Y ._2, _3.;" "gimple" } }
+
+// And that we *are* passing the int along to V::V.
+// { dg-final { scan-assembler "_ZN1VCI21WEi" } }
+// { dg-final { scan-tree-dump "V::V .this, _1.;" "gimple" } }
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor24.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor24.C
new file mode 100644
index 00000000000..21450196da0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor24.C
@@ -0,0 +1,27 @@
+// Testcase from P0136
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct A { A(int); };
+struct B : A { using A::A; };
+
+struct C1 : B { using B::B; };
+struct C2 : B { using B::B; };
+
+struct D1 : C1, C2 {
+ using C1::C1;
+ using C2::C2;
+};
+
+struct V1 : virtual B { using B::B; };
+struct V2 : virtual B { using B::B; };
+
+struct D2 : V1, V2 {
+ using V1::V1;
+ using V2::V2;
+};
+
+D1 d1(0); // { dg-error "" } ambiguous
+D2 d2(0); // OK: initializes virtual B base class, which initializes the A base
+ // class then initializes the V1 and V2 base classes as if by a
+ // defaulted default constructor
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor25.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor25.C
new file mode 100644
index 00000000000..66cd2dabb0d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor25.C
@@ -0,0 +1,9 @@
+// Testcase from P0136
+// { dg-do compile { target c++11 } }
+
+struct M { M(); M(int); };
+struct N : M { using M::M; };
+struct O : M {};
+struct P : N, O { using N::N; using O::O; };
+P p(0); // OK: use M(0) to initialize N's base class,
+ // use M() to initialize O's base class
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor26.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor26.C
new file mode 100644
index 00000000000..28dc33227a8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor26.C
@@ -0,0 +1,17 @@
+// Testcase from P0136
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct A {
+ template<typename T> A(T, typename T::type = 0);
+ A(int);
+};
+struct B : A {
+ using A::A;
+ B(int);
+};
+B b(42L); // now calls B(int), used to call B<long>(long),
+ // which called A(int) due to substitution failure
+ // in A<long>(long).
+
+// { dg-final { scan-assembler "_ZN1BC1Ei" } }
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor27.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor27.C
new file mode 100644
index 00000000000..97f26346b78
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor27.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ A(int = 0);
+};
+
+struct B: A
+{
+ B();
+ using A::A;
+};
+
+B b1(1);
+B b;
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor28.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor28.C
new file mode 100644
index 00000000000..55e1d8c943f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor28.C
@@ -0,0 +1,7 @@
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct V { V(int); };
+struct W : virtual V { using V::V; };
+struct X : virtual W, virtual V { using W::W; };
+X x(0);
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor29.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor29.C
new file mode 100644
index 00000000000..97f26346b78
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor29.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ A(int = 0);
+};
+
+struct B: A
+{
+ B();
+ using A::A;
+};
+
+B b1(1);
+B b;
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor30.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor30.C
new file mode 100644
index 00000000000..494dd91bb80
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor30.C
@@ -0,0 +1,17 @@
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+ A(double);
+};
+
+struct B: A
+{
+ B(short);
+ using A::A;
+};
+
+int main()
+{
+ B b(1); // { dg-error "ambiguous" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor31.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor31.C
new file mode 100644
index 00000000000..3ce080d115b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor31.C
@@ -0,0 +1,15 @@
+// { dg-do compile { target c++11 } }
+
+struct B;
+struct A
+{
+ A(const B&, int = 0);
+};
+
+struct B: A
+{
+ using A::A;
+};
+
+extern B b;
+B b2{b};
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor32.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor32.C
new file mode 100644
index 00000000000..7ce85b0af2e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor32.C
@@ -0,0 +1,16 @@
+// { dg-do compile { target c++11 } }
+
+struct B;
+struct A
+{
+ A(const B&, int = 0);
+};
+
+struct B: A
+{
+ using A::A;
+ B(B&);
+};
+
+extern const B b;
+B b2{b}; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor33.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor33.C
new file mode 100644
index 00000000000..0e8520745a9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor33.C
@@ -0,0 +1,23 @@
+// { dg-do link { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+struct A
+{
+ A() { }
+ A(const A&); // should never be called
+};
+
+struct B
+{
+ B(A) { }
+};
+
+struct C: B
+{
+ using B::B;
+};
+
+int main()
+{
+ C c{A()};
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor34.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor34.C
new file mode 100644
index 00000000000..f47b2a4dc2f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor34.C
@@ -0,0 +1,18 @@
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+class A
+{
+ A(int);
+ friend void f();
+};
+
+struct B: A
+{
+ using A::A;
+};
+
+void f()
+{
+ B b(42);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor35.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor35.C
new file mode 100644
index 00000000000..87f4452c666
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor35.C
@@ -0,0 +1,21 @@
+// Core 1715
+// { dg-do compile { target c++11 } }
+// { dg-options -fno-new-inheriting-ctors }
+
+template<class T> struct S {
+private:
+ typedef int X;
+ friend struct B;
+};
+
+struct B {
+ template<class T> B(T, typename T::X);
+};
+
+struct D: B {
+ using B::B; // { dg-prune-output "private" }
+};
+
+S<int> s;
+B b(s, 2); // Okay, thanks to friendship.
+D d(s, 2); // { dg-error "" } was an error before P0136
diff --git a/gcc/testsuite/g++.dg/cpp1z/inh-ctor35a.C b/gcc/testsuite/g++.dg/cpp1z/inh-ctor35a.C
new file mode 100644
index 00000000000..47f69de41b8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/inh-ctor35a.C
@@ -0,0 +1,21 @@
+// Core 1715
+// { dg-do compile { target c++11 } }
+// { dg-options -fnew-inheriting-ctors }
+
+template<class T> struct S {
+private:
+ typedef int X;
+ friend struct B;
+};
+
+struct B {
+ template<class T> B(T, typename T::X);
+};
+
+struct D: B {
+ using B::B;
+};
+
+S<int> s;
+B b(s, 2); // Okay, thanks to friendship.
+D d(s, 2); // Now OK as well.
diff --git a/gcc/testsuite/g++.dg/cpp1z/launder3.C b/gcc/testsuite/g++.dg/cpp1z/launder3.C
new file mode 100644
index 00000000000..2a2afc5cad1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/launder3.C
@@ -0,0 +1,38 @@
+// { dg-do run { target c++11 } }
+// { dg-additional-options "-O2" }
+
+#include <cassert>
+
+void *
+operator new (decltype (sizeof (0)), void *p)
+{
+ return p;
+}
+
+namespace std
+{
+ template <typename T>
+ T *
+ launder (T *p)
+ {
+ return __builtin_launder (p);
+ }
+}
+
+struct A
+{
+ const int x;
+};
+
+struct B
+{
+ A a;
+};
+
+int
+main ()
+{
+ B b{{42}};
+ new (&b.a) A{666};
+ assert(std::launder(&b.a)->x == 666);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/launder4.C b/gcc/testsuite/g++.dg/cpp1z/launder4.C
new file mode 100644
index 00000000000..3a65eb27f2e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/launder4.C
@@ -0,0 +1,40 @@
+// { dg-do run { target c++11 } }
+// { dg-additional-options "-O2" }
+
+#include <cassert>
+
+void *
+operator new (decltype (sizeof (0)), void *p)
+{
+ return p;
+}
+
+namespace std
+{
+ template <typename T>
+ T *
+ launder (T *p)
+ {
+ return __builtin_launder (p);
+ }
+}
+
+struct A
+{
+ int& x;
+};
+
+struct B
+{
+ A a;
+};
+
+int
+main ()
+{
+ int x = 42;
+ B b{{x}};
+ int y = 666;
+ new (&b.a) A{y};
+ assert(std::launder(&b.a)->x == 666);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/launder5.C b/gcc/testsuite/g++.dg/cpp1z/launder5.C
new file mode 100644
index 00000000000..483d6f29297
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/launder5.C
@@ -0,0 +1,25 @@
+// { dg-do run { target c++11 } }
+// { dg-additional-options "-O2" }
+// { dg-additional-sources "launder5.cc" }
+
+#include <cassert>
+#include "launder5.h"
+
+namespace std
+{
+ template <typename T>
+ T *
+ launder (T *p)
+ {
+ return __builtin_launder (p);
+ }
+}
+
+
+int
+main ()
+{
+ B b{{42}};
+ f(b);
+ assert(std::launder(&b.a)->x == 666);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/launder5.cc b/gcc/testsuite/g++.dg/cpp1z/launder5.cc
new file mode 100644
index 00000000000..f9d867db332
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/launder5.cc
@@ -0,0 +1,12 @@
+#include "launder5.h"
+
+void *
+operator new (decltype (sizeof (0)), void *p)
+{
+ return p;
+}
+
+void f(B& b)
+{
+ new (&b.a) A{666};
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/launder5.h b/gcc/testsuite/g++.dg/cpp1z/launder5.h
new file mode 100644
index 00000000000..b66103aefba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/launder5.h
@@ -0,0 +1,16 @@
+#ifndef GCC_TEST_LAUNDER5_H
+#define GCC_TEST_LAUNDER5_H
+
+struct A
+{
+ const int x;
+};
+
+struct B
+{
+ A a;
+};
+
+void f(B& b);
+
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp1z/launder6.C b/gcc/testsuite/g++.dg/cpp1z/launder6.C
new file mode 100644
index 00000000000..babc4b433ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/launder6.C
@@ -0,0 +1,24 @@
+// { dg-do run { target c++11 } }
+// { dg-additional-options "-O2" }
+// { dg-additional-sources "launder6.cc" }
+#include <cassert>
+#include "launder6.h"
+
+namespace std
+{
+ template <typename T>
+ T *
+ launder (T *p)
+ {
+ return __builtin_launder (p);
+ }
+}
+
+int
+main ()
+{
+ int x = 42;
+ B b{{x}};
+ f(b);
+ assert(std::launder(&b.a)->x == 666);
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/launder6.cc b/gcc/testsuite/g++.dg/cpp1z/launder6.cc
new file mode 100644
index 00000000000..1822891a0a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/launder6.cc
@@ -0,0 +1,14 @@
+#include "launder6.h"
+
+void *
+operator new (decltype (sizeof (0)), void *p)
+{
+ return p;
+}
+
+int y = 666;
+
+void f(B& b)
+{
+ new (&b.a) A{y};
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/launder6.h b/gcc/testsuite/g++.dg/cpp1z/launder6.h
new file mode 100644
index 00000000000..eca2ad46f18
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/launder6.h
@@ -0,0 +1,16 @@
+#ifndef GCC_TEST_LAUNDER6_H
+#define GCC_TEST_LAUNDER6_H
+
+struct A
+{
+ int& x;
+};
+
+struct B
+{
+ A a;
+};
+
+void f(B& b);
+
+#endif
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type1.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type1.C
new file mode 100644
index 00000000000..62e1322e35a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type1.C
@@ -0,0 +1,8 @@
+// Testcase from P0012r1
+// { dg-options -std=c++1z }
+
+void (*p)() throw(int);
+void (**pp)() noexcept = &p; // { dg-error "" } cannot convert to pointer to noexcept function
+
+struct S { typedef void (*p)(); operator p(); };
+void (*q)() noexcept = S(); // { dg-error "" } cannot convert to pointer to noexcept function
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type11.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type11.C
new file mode 100644
index 00000000000..bcd4d8d613d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type11.C
@@ -0,0 +1,3 @@
+// { dg-options "-Wall -std=c++14" }
+
+void f(int(*)() noexcept) { } // { dg-warning "mangled" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type12.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type12.C
new file mode 100644
index 00000000000..39820af136e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type12.C
@@ -0,0 +1,23 @@
+// { dg-options -std=c++1z }
+
+template <class R, class... A, bool B>
+void f(R (*)(A...) noexcept(B)) { }
+
+template <class R, class... A, bool B>
+void f2(R (*)(A...) noexcept(B)) { }
+
+void g(int);
+void h(int) noexcept;
+
+int main()
+{
+ f(g);
+ f2(h);
+}
+
+// { dg-final { scan-assembler "_Z1fIvJiELb0EEvPDOT1_EFT_DpT0_E" } }
+// { dg-final { scan-assembler "_Z2f2IvJiELb1EEvPDOT1_EFT_DpT0_E" } }
+
+void f3(void (*)() noexcept) { }
+
+// { dg-final { scan-assembler "_Z2f3PDoFvvE" } }
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type2.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type2.C
new file mode 100644
index 00000000000..747bb194c30
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type2.C
@@ -0,0 +1,10 @@
+// Test for function pointer conversion on template arguments.
+// { dg-options -std=c++1z }
+
+template <void (*P)()> struct A { };
+
+void f() noexcept { };
+constexpr void (*p)() noexcept = f;
+
+A<f> a;
+A<p> b;
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type3.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type3.C
new file mode 100644
index 00000000000..9303da87b8c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type3.C
@@ -0,0 +1,13 @@
+// Test for overload resolution.
+// { dg-options -std=c++1z }
+
+void f(void (*)() noexcept) = delete;
+void f(void (*)()) { }
+void g() {}
+void h() noexcept {}
+
+int main()
+{
+ f(g);
+ f(h); // { dg-error "deleted" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type4.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type4.C
new file mode 100644
index 00000000000..621da9341ea
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type4.C
@@ -0,0 +1,16 @@
+// Test for deduction.
+// { dg-options -std=c++1z }
+
+template <class R, class... A>
+void f(R (*)(A...));
+void g(int) noexcept;
+
+template <class R, class... A>
+void h(R (*)(A...) noexcept);
+void i(int);
+
+int main()
+{
+ f(g);
+ h(i); // { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type5.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type5.C
new file mode 100644
index 00000000000..9e5d20224e2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type5.C
@@ -0,0 +1,25 @@
+// Test for composite pointer type.
+// { dg-options -std=c++1z }
+
+typedef void (*P)();
+typedef void (*NP)() noexcept;
+
+void f();
+void g() noexcept;
+
+bool b;
+
+template <class T, class U> struct Same;
+template <class T> struct Same<T,T> { };
+
+Same<decltype(b ? &f : &g),P> s;
+
+int main()
+{
+ P p = 0;
+ NP np = 0;
+
+ p == np;
+ p != np;
+ p < np;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type6.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type6.C
new file mode 100644
index 00000000000..50684571b62
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type6.C
@@ -0,0 +1,13 @@
+// Test for lambda conversion.
+// { dg-options -std=c++1z }
+
+void f()
+{
+ auto l = []() noexcept { return 0; };
+ int (*p)() noexcept = l;
+ int (*q)() = l;
+
+ auto l2 = []{ return 0; };
+ p = l2; // { dg-error "" }
+ q = l2;
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type7.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type7.C
new file mode 100644
index 00000000000..1f78114dc74
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type7.C
@@ -0,0 +1,14 @@
+// Test for static_cast.
+// { dg-options -std=c++1z }
+
+void f()
+{
+ typedef void (*P)();
+ typedef void (*NP)() noexcept;
+
+ P p;
+ NP np;
+
+ static_cast<P>(np);
+ static_cast<NP>(p); // { dg-error "" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type8.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type8.C
new file mode 100644
index 00000000000..0182e3a3111
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type8.C
@@ -0,0 +1,22 @@
+// Test for exception handling.
+// { dg-options -std=c++1z }
+// { dg-do run }
+
+void f() {}
+void g() noexcept {}
+
+int main()
+{
+ try { throw g; }
+ catch (void (*)()) { }
+
+ try { throw g; }
+ catch (void (*)() noexcept) { }
+
+ try { throw f; }
+ catch (void (*)()) { }
+
+ try { throw f; }
+ catch (void (*)() noexcept) { __builtin_abort(); }
+ catch (...) { }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1z/noexcept-type9.C b/gcc/testsuite/g++.dg/cpp1z/noexcept-type9.C
new file mode 100644
index 00000000000..a29618a3001
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/noexcept-type9.C
@@ -0,0 +1,18 @@
+// Test for PMF template args.
+// { dg-options -std=c++1z }
+// { dg-do compile }
+
+struct A
+{
+ void f() noexcept;
+ void g();
+};
+
+template <void (A::*)()> struct B { };
+template <void (A::*)() noexcept> struct C { };
+
+B<&A::f> b1;
+B<&A::g> b2;
+
+C<&A::f> c1;
+C<&A::g> c2; // { dg-error "" }
diff --git a/gcc/testsuite/g++.dg/cpp1z/using1.C b/gcc/testsuite/g++.dg/cpp1z/using1.C
new file mode 100644
index 00000000000..1ed939d45fd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/using1.C
@@ -0,0 +1,23 @@
+// Test for hiding of used base functions when all the conversion sequences are
+// equivalent, needed to avoid a regression on inherited default ctors.
+
+struct A
+{
+ void f(short,int=0);
+ void g(char,int=0);
+};
+
+struct B:A
+{
+ using A::f;
+ void f(short);
+ using A::g;
+ void g(short);
+};
+
+int main()
+{
+ B().f(1); // OK, derived f hides base f for single arg
+ B().f(1,2); // OK, base f can still be called with two args
+ B().g(1); // { dg-error "" } signatures differ, ambiguous
+}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/constexpr-var-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/constexpr-var-1.C
index 045d5fed744..19062e29fd5 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/constexpr-var-1.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/constexpr-var-1.C
@@ -1,6 +1,6 @@
// { dg-do compile }
// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
-// { dg-final { scan-assembler-times " DW_AT_const_expr" 2 } }
+// { dg-final { scan-assembler-times " DW_AT_const_expr" 2 { xfail *-*-aix* } } }
constexpr int a = 5;
struct S
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C
new file mode 100644
index 00000000000..f4f4b6d77d1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/inline-var-1.C
@@ -0,0 +1,27 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++1z -g -dA -gno-strict-dwarf" }
+// { dg-require-weak "" }
+// { dg-final { scan-assembler-times "0x3\[^\n\r]* DW_AT_inline" 6 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times "0x1\[^\n\r]* DW_AT_inline" 2 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times " DW_AT_declaration" 6 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times " DW_AT_specification" 6 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times " DW_AT_\[^\n\r]*linkage_name" 7 { xfail *-*-aix* } } }
+
+inline int a;
+struct S
+{
+ static inline double b = 4.0;
+ static constexpr int c = 2;
+ static constexpr inline char d = 3;
+} s;
+template <int N>
+inline int e = N;
+int &f = e<2>;
+template <int N>
+struct T
+{
+ static inline double g = 4.0;
+ static constexpr int h = 2;
+ static inline constexpr char i = 3;
+};
+T<5> t;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C
new file mode 100644
index 00000000000..5d65196f7af
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/ptrdmem-1.C
@@ -0,0 +1,9 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_use_location" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_reference" { xfail { powerpc-ibm-aix* } } } }
+
+struct S;
+typedef int S::*pdm;
+pdm pmf = 0;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/ref-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/ref-2.C
index dd1f457d3ec..43939c9d697 100644
--- a/gcc/testsuite/g++.dg/debug/dwarf2/ref-2.C
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/ref-2.C
@@ -1,7 +1,7 @@
// { dg-do compile { target c++11 } }
// { dg-options "-g -gno-strict-dwarf -dA" }
-// { dg-final { scan-assembler-times " DW_AT_reference" 1 } }
-// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 1 } }
+// { dg-final { scan-assembler-times " DW_AT_reference" 1 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 1 { xfail *-*-aix* } } }
struct S
{
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C b/gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C
new file mode 100644
index 00000000000..d7932d8a237
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/ref-3.C
@@ -0,0 +1,56 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-g -gno-strict-dwarf -dA" }
+// { dg-final { scan-assembler-times " DW_AT_reference" 5 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 5 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_subroutine_type" 6 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 7 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times " DW_AT_use_location" 1 { xfail *-*-aix* } } }
+
+struct S
+{
+ void foo1 ();
+ void bar1 () &;
+ void baz1 () &&;
+ void foo2 () const;
+ void bar2 () const &;
+ void baz2 () const &&;
+ void foo3 () const;
+ void bar3 () const &;
+ void baz3 () const &&;
+ int d;
+};
+
+void
+test ()
+{
+ S s;
+ auto o1 = &S::foo1;
+ auto r1 = &S::bar1;
+ auto z1 = &S::baz1;
+ auto o2 = &S::foo2;
+ auto r2 = &S::bar2;
+ auto z2 = &S::baz2;
+ auto o3 = &S::foo3;
+ auto r3 = &S::bar3;
+ auto z3 = &S::baz3;
+ auto d1 = &S::d;
+ void (S::*o4) () const;
+ o4 = &S::foo3;
+ void (S::*r4) () const &;
+ r4 = &S::bar3;
+ void (S::*z4) () const &&;
+ z4 = &S::baz3;
+ (s.*o1) ();
+ (s.*r1) ();
+ (S ().*z1) ();
+ (s.*o2) ();
+ (s.*r2) ();
+ (S ().*z2) ();
+ (s.*o3) ();
+ (s.*r3) ();
+ (S ().*z3) ();
+ (s.*o4) ();
+ (s.*r4) ();
+ (S ().*z4) ();
+ s.*d1 = 2;
+}
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/ref-4.C b/gcc/testsuite/g++.dg/debug/dwarf2/ref-4.C
new file mode 100644
index 00000000000..00cf81f4bcc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/ref-4.C
@@ -0,0 +1,11 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-g -gno-strict-dwarf -dA" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_typedef" 2 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 2 { xfail *-*-aix* } } }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_subroutine_type" 1 { xfail *-*-aix* } } }
+
+struct A { void foo (); int a; };
+typedef void (A::*PMF) ();
+typedef int A::*PMI;
+PMF pmf;
+PMI pmi;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C
new file mode 100644
index 00000000000..221008e9981
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/refqual-1.C
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_reference" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_use_location" { xfail { powerpc-ibm-aix* } } } }
+/* It is not clear what if anything we should output for
+ DW_AT_use_location in a pointer to member function, so we don't
+ output it for now. */
+
+struct S {
+ void mf(void) &;
+};
+
+void S::mf() & {}
+
+typedef void (S::*pmft)(void) &;
+pmft pmf = &S::mf;
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C b/gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C
new file mode 100644
index 00000000000..ddf33c1971e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/refqual-2.C
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O -std=c++11 -g -dA -gno-strict-dwarf" }
+// { dg-final { scan-assembler-times "DIE \\(\[^\n\]*\\) DW_TAG_ptr_to_member_type" 1 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-times " DW_AT_rvalue_reference" 2 { xfail { powerpc-ibm-aix* } } } }
+// { dg-final { scan-assembler-not " DW_AT_use_location" { xfail { powerpc-ibm-aix* } } } }
+/* It is not clear what if anything we should output for
+ DW_AT_use_location in a pointer to member function, so we don't
+ output it for now. */
+
+struct S {
+ void mf(void) &&;
+};
+
+void S::mf() && {}
+
+typedef void (S::*pmft)(void) &&;
+pmft pmf = &S::mf;
diff --git a/gcc/testsuite/g++.dg/eh/spec2.C b/gcc/testsuite/g++.dg/eh/spec2.C
index 64807dd2677..8107f019eb7 100644
--- a/gcc/testsuite/g++.dg/eh/spec2.C
+++ b/gcc/testsuite/g++.dg/eh/spec2.C
@@ -2,9 +2,9 @@
struct S { void f (void); };
-typedef void f1 (void) throw (int); // { dg-error "exception" }
-typedef void (*f2) (void) throw (int); // { dg-error "exception" }
-typedef void (S::*f3) (void) throw (int); // { dg-error "exception" }
+typedef void f1 (void) throw (int); // { dg-error "exception" "" { target c++14_down } }
+typedef void (*f2) (void) throw (int); // { dg-error "exception" "" { target c++14_down } }
+typedef void (S::*f3) (void) throw (int); // { dg-error "exception" "" { target c++14_down } }
void (*f4) (void) throw (int);
void (S::*f5) (void) throw (int);
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon1.C b/gcc/testsuite/g++.dg/ext/visibility/anon1.C
index 1f3be3b774b..0135f931a6f 100644
--- a/gcc/testsuite/g++.dg/ext/visibility/anon1.C
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon1.C
@@ -2,7 +2,7 @@
// Test for anonymous namespace internal linkage
// { dg-do compile }
-// { dg-final { scan-assembler-not "globl.*_ZN.*1fEv" } }
+// { dg-final { scan-assembler-not "globl.*_ZN.*1fEv" { xfail *-*-aix* } } }
// { dg-require-visibility "" }
namespace
diff --git a/gcc/testsuite/g++.dg/ext/visibility/anon2.C b/gcc/testsuite/g++.dg/ext/visibility/anon2.C
index 49022963127..dcf0e64fa23 100644
--- a/gcc/testsuite/g++.dg/ext/visibility/anon2.C
+++ b/gcc/testsuite/g++.dg/ext/visibility/anon2.C
@@ -1,7 +1,7 @@
// Test for propagation of anonymous namespace internal linkage
// { dg-do compile }
-// { dg-final { scan-assembler-not "globl.*_Z1fv" } }
+// { dg-final { scan-assembler-not "globl.*_Z1fv" { xfail *-*-aix* } } }
// { dg-require-visibility "" }
namespace
diff --git a/gcc/testsuite/g++.dg/ext/visibility/pragma-override1.C b/gcc/testsuite/g++.dg/ext/visibility/pragma-override1.C
index c13161d3ceb..b6bc0c5466a 100644
--- a/gcc/testsuite/g++.dg/ext/visibility/pragma-override1.C
+++ b/gcc/testsuite/g++.dg/ext/visibility/pragma-override1.C
@@ -1,7 +1,7 @@
/* Test that #pragma GCC visibility does not override class member specific settings. */
/* { dg-do compile } */
/* { dg-require-visibility "internal" } */
-/* { dg-final { scan-assembler "\\.internal.*Foo.methodEv" { target { ! { *-*-solaris2* *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler "\\.internal.*Foo.methodEv" { target { ! { *-*-solaris2* *-*-darwin* *-*-aix* } } } } } */
/* { dg-final { scan-assembler "\\.(internal|hidden).*Foo.methodEv" { target *-*-solaris2* } } } */
#pragma GCC visibility push(hidden)
diff --git a/gcc/testsuite/g++.dg/ext/visibility/pragma-override2.C b/gcc/testsuite/g++.dg/ext/visibility/pragma-override2.C
index 25e9ceac076..8499ceff60a 100644
--- a/gcc/testsuite/g++.dg/ext/visibility/pragma-override2.C
+++ b/gcc/testsuite/g++.dg/ext/visibility/pragma-override2.C
@@ -1,7 +1,7 @@
/* Test that #pragma GCC visibility does not override class member specific settings. */
/* { dg-do compile } */
/* { dg-require-visibility "internal" } */
-/* { dg-final { scan-assembler "\\.internal.*Foo.methodEv" { target { ! { *-*-solaris2* *-*-darwin* } } } } } */
+/* { dg-final { scan-assembler "\\.internal.*Foo.methodEv" { target { ! { *-*-solaris2* *-*-darwin* *-*-aix* } } } } } */
/* { dg-final { scan-assembler "\\.(internal|hidden).*Foo.methodEv" { target *-*-solaris2* } } } */
#pragma GCC visibility push(hidden)
diff --git a/gcc/testsuite/g++.dg/init/new15.C b/gcc/testsuite/g++.dg/init/new15.C
index b93b43c833f..1f57f07dfc3 100644
--- a/gcc/testsuite/g++.dg/init/new15.C
+++ b/gcc/testsuite/g++.dg/init/new15.C
@@ -1,6 +1,6 @@
// PR c++/9782
-extern "C" void printf(const char*, ...);
+extern "C" int printf(const char*, ...);
template <int>
struct A {
diff --git a/gcc/testsuite/g++.dg/ipa/inline-1.C b/gcc/testsuite/g++.dg/ipa/inline-1.C
index 9ea614b295d..d570dc67e28 100644
--- a/gcc/testsuite/g++.dg/ipa/inline-1.C
+++ b/gcc/testsuite/g++.dg/ipa/inline-1.C
@@ -3,7 +3,7 @@
/* { dg-add-options bind_pic_locally } */
namespace std {
- extern "C" void puts(const char *s);
+ extern "C" int puts(const char *s);
}
template <class T, class E> void
diff --git a/gcc/testsuite/g++.dg/ipa/inline-2.C b/gcc/testsuite/g++.dg/ipa/inline-2.C
index cc5b2559ae7..eb0f21b1247 100644
--- a/gcc/testsuite/g++.dg/ipa/inline-2.C
+++ b/gcc/testsuite/g++.dg/ipa/inline-2.C
@@ -3,7 +3,7 @@
/* { dg-add-options bind_pic_locally } */
namespace std {
- extern "C" void puts(const char *s);
+ extern "C" int puts(const char *s);
}
template <class T, class E> void
diff --git a/gcc/testsuite/g++.dg/ipa/pr78188.C b/gcc/testsuite/g++.dg/ipa/pr78188.C
new file mode 100644
index 00000000000..f6ee654471e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ipa/pr78188.C
@@ -0,0 +1,20 @@
+// { dg-do compile }
+// { dg-options "-O2 -fno-exceptions" }
+
+int a;
+static void __attribute__((noinline)) foo () { a = 1; }
+static void __attribute__((noinline)) foo2 () { a = 2; }
+
+struct X
+{
+ virtual void bar (int i) { if (!i) { foo (); __builtin_abort (); } }
+};
+
+void baz (int i)
+{
+ if (!i)
+ { foo2 (); __builtin_abort (); }
+}
+
+X xx;
+
diff --git a/gcc/testsuite/g++.dg/lto/20080908-1_0.C b/gcc/testsuite/g++.dg/lto/20080908-1_0.C
index 8b761c0844c..42b20cb3b3a 100644
--- a/gcc/testsuite/g++.dg/lto/20080908-1_0.C
+++ b/gcc/testsuite/g++.dg/lto/20080908-1_0.C
@@ -1,5 +1,5 @@
/* { dg-lto-do run } */
-extern "C" { extern void *memcpy (void *, const void *, unsigned); }
+extern "C" { extern void *memcpy (void *, const void *, __SIZE_TYPE__); }
inline int
bci (const float &source)
diff --git a/gcc/testsuite/gcc.target/i386/pr64411.C b/gcc/testsuite/g++.dg/opt/pr64411.C
index 55858fb48eb..122b9eec414 100644
--- a/gcc/testsuite/gcc.target/i386/pr64411.C
+++ b/gcc/testsuite/g++.dg/opt/pr64411.C
@@ -1,5 +1,6 @@
-/* { dg-do compile } */
-/* { dg-options "-Os -mcmodel=medium -fPIC -fschedule-insns -fselective-scheduling" } */
+// PR target/64411
+// { dg-do compile { target { { i?86-*-* x86_64-*-* } && lp64 } } }
+// { dg-options "-Os -mcmodel=medium -fPIC -fschedule-insns -fselective-scheduling" }
typedef __SIZE_TYPE__ size_t;
diff --git a/gcc/testsuite/gcc.target/i386/pr65105-4.C b/gcc/testsuite/g++.dg/opt/pr65105-4.C
index 9acf368e1fc..d79ba1abab0 100644
--- a/gcc/testsuite/gcc.target/i386/pr65105-4.C
+++ b/gcc/testsuite/g++.dg/opt/pr65105-4.C
@@ -1,6 +1,6 @@
-/* PR target/pr65105 */
-/* { dg-do run { target { ia32 } } } */
-/* { dg-options "-O2 -march=slm" } */
+// PR target/65105
+// { dg-do compile { target { { i?86-*-* x86_64-*-* } && ia32 } } }
+// { dg-options "-O2 -march=slm" }
struct s {
long long l1, l2, l3, l4, l5;
diff --git a/gcc/testsuite/g++.dg/opt/pr71529.C b/gcc/testsuite/g++.dg/opt/pr71529.C
new file mode 100644
index 00000000000..148527f00c4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/opt/pr71529.C
@@ -0,0 +1,22 @@
+// PR middle-end/71529
+// { dg-do compile { target { { i?86-*-* x86_64-*-* } && { ! x32 } } } }
+// { dg-options "-fcheck-pointer-bounds -mmpx -O2" }
+
+class c1
+{
+ public:
+ virtual ~c1 ();
+};
+
+class c2
+{
+ public:
+ virtual ~c2 ();
+};
+
+class c3 : c1, c2 { };
+
+int main (int, char **)
+{
+ c3 obj;
+}
diff --git a/gcc/testsuite/g++.dg/pr78229.C b/gcc/testsuite/g++.dg/pr78229.C
new file mode 100644
index 00000000000..a52141b6b83
--- /dev/null
+++ b/gcc/testsuite/g++.dg/pr78229.C
@@ -0,0 +1,24 @@
+/* { dg-do compile { target x86_64-*-* i?86-*-* } } */
+/* { dg-options "-O2 -mbmi -w" } */
+
+void a();
+inline int b(int c) {
+ int d = c;
+ return __builtin_ia32_tzcnt_u32(d);
+}
+struct e {};
+int f, g, h;
+void fn3() {
+ float j;
+ &j;
+ {
+ e k;
+ while (h) {
+ if (g == 0)
+ continue;
+ int i = b(g);
+ f = i;
+ }
+ a();
+ }
+}
diff --git a/gcc/testsuite/g++.dg/tc1/dr20.C b/gcc/testsuite/g++.dg/tc1/dr20.C
index fe586212995..93338518190 100644
--- a/gcc/testsuite/g++.dg/tc1/dr20.C
+++ b/gcc/testsuite/g++.dg/tc1/dr20.C
@@ -2,7 +2,7 @@
// Origin: Giovanni Bajo <giovannibajo at gcc dot gnu dot org>
// DR20: Some clarifications needed for 12.8 para 15
-extern "C" void printf(const char*, ...);
+extern "C" int printf(const char*, ...);
extern "C" void abort(void);
int count = 0;
diff --git a/gcc/testsuite/g++.dg/template/func2.C b/gcc/testsuite/g++.dg/template/func2.C
index b0f691d242b..746f0e279a7 100644
--- a/gcc/testsuite/g++.dg/template/func2.C
+++ b/gcc/testsuite/g++.dg/template/func2.C
@@ -5,7 +5,7 @@ fptr zeroptr = 0;
template<typename T, fptr F> struct foo { };
template<typename T> struct foo<T,zeroptr> { };
// { dg-error "not a valid template argument" "not valid" { target *-*-* } 6 }
-// { dg-error "must be the address" "must be the address " { target *-*-* } 6 }
+// { dg-message "must be the address" "must be the address " { target *-*-* } 6 }
// The rest is needed to trigger the ICE in 4.0 to 4.3:
void f() { }
diff --git a/gcc/testsuite/g++.dg/torture/pr77822.C b/gcc/testsuite/g++.dg/torture/pr77822.C
new file mode 100644
index 00000000000..4dc428b63ee
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr77822.C
@@ -0,0 +1,30 @@
+// PR target/77822
+// { dg-do compile }
+
+using UINT8 = char;
+using UINT32 = int;
+using UINT64 = long;
+class A
+{
+ void m_fn1 ();
+ struct B
+ {
+ UINT32 m_multiplier;
+ };
+ UINT8 m_datawidth;
+ UINT8 m_subunits;
+ B m_subunit_infos[];
+};
+int a;
+UINT64 b;
+void
+A::m_fn1 ()
+{
+ int c = 32, d = m_datawidth / c;
+ for (int e = 0; e < d; e++)
+ {
+ UINT32 f = e * 32;
+ if (b >> f & 1)
+ m_subunit_infos[m_subunits].m_multiplier = a;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr77919-2.C b/gcc/testsuite/g++.dg/torture/pr77919-2.C
new file mode 100644
index 00000000000..d61e704cb44
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr77919-2.C
@@ -0,0 +1,10 @@
+// PR rtl-optimization/77919
+// { dg-do compile }
+
+typedef _Complex long long B;
+struct A { A (double) {} _Complex double i; };
+typedef struct { B b; } C;
+struct D { D (const B &x) : b (x) {} B b; };
+static inline B foo (const double *x) { C *a; a = (C *) x; return a->b; }
+static inline D baz (const A &x) { return foo ((double *) &x); }
+D b = baz (0);
diff --git a/gcc/testsuite/g++.dg/torture/pr78189.C b/gcc/testsuite/g++.dg/torture/pr78189.C
new file mode 100644
index 00000000000..9b65d2b5a63
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr78189.C
@@ -0,0 +1,41 @@
+/* { dg-do run } */
+/* { dg-additional-options "-ftree-slp-vectorize -fno-vect-cost-model" } */
+
+#include <cstddef>
+
+struct A
+{
+ void * a;
+ void * b;
+};
+
+struct alignas(16) B
+{
+ void * pad;
+ void * misaligned;
+ void * pad2;
+
+ A a;
+
+ void Null();
+};
+
+void B::Null()
+{
+ a.a = nullptr;
+ a.b = nullptr;
+}
+
+void __attribute__((noinline,noclone))
+NullB(void * misalignedPtr)
+{
+ B* b = reinterpret_cast<B*>(reinterpret_cast<char *>(misalignedPtr) - offsetof(B, misaligned));
+ b->Null();
+}
+
+int main()
+{
+ B b;
+ NullB(&b.misaligned);
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/torture/pr78224.C b/gcc/testsuite/g++.dg/torture/pr78224.C
new file mode 100644
index 00000000000..bb85339e8f8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/torture/pr78224.C
@@ -0,0 +1,51 @@
+// { dg-do compile }
+
+extern "C"{
+ float sqrtf(float);
+}
+
+inline float squareroot(const float f)
+{
+ return sqrtf(f);
+}
+
+inline int squareroot(const int f)
+{
+ return static_cast<int>(sqrtf(static_cast<float>(f)));
+}
+
+template <class T>
+class vector2d
+{
+public:
+ vector2d(T nx, T ny) : X(nx), Y(ny) {}
+ T getLength() const { return squareroot( X*X + Y*Y ); }
+ T X;
+ T Y;
+};
+
+vector2d<int> getMousePos();
+
+class Client
+{
+public:
+ Client();
+ ~Client();
+};
+
+void the_game(float turn_amount)
+{
+ Client client;
+ bool first = true;
+
+ while (1) {
+ if (first) {
+ first = false;
+ } else {
+ int dx = getMousePos().X;
+ int dy = getMousePos().Y;
+
+ turn_amount = vector2d<float>(dx, dy).getLength();
+ }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/tree-ssa/inline-1.C b/gcc/testsuite/g++.dg/tree-ssa/inline-1.C
index 1abfa324ad5..4497facb87b 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/inline-1.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/inline-1.C
@@ -3,7 +3,7 @@
/* { dg-add-options bind_pic_locally } */
namespace std {
- extern "C" void puts(const char *s);
+ extern "C" int puts(const char *s);
}
template <class T, class E> void
diff --git a/gcc/testsuite/g++.dg/tree-ssa/inline-2.C b/gcc/testsuite/g++.dg/tree-ssa/inline-2.C
index 53e609ecd8f..79f807cd220 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/inline-2.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/inline-2.C
@@ -3,7 +3,7 @@
/* { dg-add-options bind_pic_locally } */
namespace std {
- extern "C" void puts(const char *s);
+ extern "C" int puts(const char *s);
}
template <class T, class E> void
diff --git a/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-2.C b/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-2.C
new file mode 100644
index 00000000000..cacaf55bb49
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wimplicit-fallthrough-2.C
@@ -0,0 +1,66 @@
+// PR c++/77886
+// { dg-do compile }
+// { dg-options "-Wimplicit-fallthrough" }
+
+template <int N>
+int
+foo (int x, int y)
+{
+ switch (x)
+ {
+ case 1:
+ x++; // { dg-bogus "this statement may f\[ahlotu\]*gh" }
+ // FALLTHROUGH
+ case 2:
+ x++;
+ break;
+ case 3:
+ x++; // { dg-bogus "this statement may f\[ahlotu\]*gh" }
+ // FALLTHROUGH
+ lab:
+ case 4:
+ x++;
+ break;
+ case 5:
+ x++; // { dg-bogus "this statement may f\[ahlotu\]*gh" }
+ // FALLTHROUGH
+ default:
+ x++;
+ break;
+ case 26:
+ goto lab;
+ }
+#if __cplusplus >= 201103L
+ switch (y)
+ {
+ case 1:
+ y++; // { dg-bogus "this statement may f\[ahlotu\]*gh" }
+ [[fallthrough]];
+ case 2:
+ y++;
+ break;
+ case 3:
+ y++; // { dg-bogus "this statement may f\[ahlotu\]*gh" }
+ [[fallthrough]];
+ lab2:
+ case 4:
+ y++;
+ break;
+ case 5:
+ y++; // { dg-bogus "this statement may f\[ahlotu\]*gh" }
+ [[fallthrough]];
+ default:
+ y++;
+ break;
+ case 26:
+ goto lab2;
+ }
+#endif
+ return x + y;
+}
+
+int
+bar (int x, int y)
+{
+ return foo<0> (x, y);
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-compatible-local-1.C b/gcc/testsuite/g++.dg/warn/Wshadow-compatible-local-1.C
new file mode 100644
index 00000000000..aac68619c3a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wshadow-compatible-local-1.C
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options -Wshadow=compatible-local } */
+
+class Bar {
+};
+
+class ChildBar : public Bar {
+};
+
+Bar bar;
+
+class Foo {
+ private:
+ int val;
+
+ public:
+ int func1(int x) {
+ int val;
+ val = x;
+ return val;
+ }
+
+ int func2(int i) { // { dg-message "note: shadowed declaration is here" }
+ int a = 3; // { dg-message "note: shadowed declaration is here" }
+
+ for (int i = 0; i < 5; ++i) { // { dg-warning "shadows a parameter" }
+ for (int i = 0; i < 3; ++i) { // { dg-warning "shadows a previous local" }
+ int a = i; // { dg-warning "shadows a previous local" }
+ func1(a);
+ }
+ }
+
+ return a;
+ }
+
+ int func3() {
+ int bar;
+ float func1 = 0.3;
+ int f = 5; // { dg-message "note: shadowed declaration is here" }
+
+ if (func1 > 1) {
+ float f = 2.0; // { dg-warning "shadows a previous local" }
+ bar = f;
+ }
+ else
+ bar = 1;
+ return bar;
+ }
+
+ void func4() {
+ Bar *bar; // { dg-bogus "shadowed declaration" }
+ ChildBar *cbp; // { dg-bogus "shadowed declaration" }
+ Bar *bp; // { dg-message "note: shadowed declaration is here" }
+ if (val) {
+ int bar; // { dg-bogus "shadows a previous local" }
+ Bar *cbp; // { dg-bogus "shadows a previous local" }
+ ChildBar *bp; // { dg-warning "shadows a previous local" }
+ func1(bar);
+ }
+ }
+};
+
+// { dg-message "note: shadowed declaration" "" { target *-*-* } 26 }
diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-local-1.C b/gcc/testsuite/g++.dg/warn/Wshadow-local-1.C
new file mode 100644
index 00000000000..dba6db5d1c2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wshadow-local-1.C
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options -Wshadow=local } */
+
+struct status
+{
+ int member;
+ void foo2 ();
+
+ inline static int foo3 (int member)
+ {
+ return member;
+ }
+};
+
+int decl1; // { dg-bogus "shadowed declaration" }
+int decl2; // { dg-bogus "shadowed declaration" }
+void foo (struct status &status,
+ double decl1) // { dg-bogus "shadows a global" }
+{
+}
+
+void foo1 (int d)
+{
+ double d; // { dg-error "shadows a parameter" }
+}
+
+void status::foo2 ()
+{
+ int member; // { dg-bogus "shadows a member" }
+ int decl2; // { dg-bogus "shadows a global" }
+ int local; // { dg-message "note: shadowed declaration is here" }
+ {
+ int local; // { dg-warning "shadows a previous local" }
+ }
+}
diff --git a/gcc/testsuite/g++.dg/warn/Wshadow-local-2.C b/gcc/testsuite/g++.dg/warn/Wshadow-local-2.C
new file mode 100644
index 00000000000..fe42c89d242
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wshadow-local-2.C
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+/* { dg-options -Wshadow=local } */
+
+class Bar {
+};
+
+class ChildBar : public Bar {
+};
+
+Bar bar; // { dg-bogus "shadowed declaration" }
+
+class Foo {
+ private:
+ int val;
+
+ public:
+ int func1(int x) {
+ int val; // { dg-bogus "shadows a member" }
+ val = x;
+ return val;
+ }
+
+ int func2(int i) { // { dg-message "shadowed declaration is here" }
+ int a = 3; // { dg-message "shadowed declaration is here" }
+
+ for (int i = 0; i < 5; ++i) { // { dg-warning "shadows a parameter" }
+ for (int i = 0; i < 3; ++i) { // { dg-warning "shadows a previous local" }
+ int a = i; // { dg-warning "shadows a previous local" }
+ func1(a);
+ }
+ }
+
+ return a;
+ }
+
+ int func3() {
+ int bar; // { dg-bogus "shadows a global" }
+ float func1 = 0.3; // { dg-bogus "shadows a member" }
+ int f = 5; // { dg-message "shadowed declaration is here" }
+
+ if (func1 > 1) {
+ float f = 2.0; // { dg-warning "shadows a previous local" }
+ bar = f;
+ }
+ else
+ bar = 1;
+ return bar;
+ }
+
+ void func4() {
+ Bar *bar; // { dg-message "shadowed declaration is here" }
+ ChildBar *cbp; // { dg-message "shadowed declaration is here" }
+ Bar *bp; // { dg-message "shadowed declaration is here" }
+ if (val) {
+ int bar; // { dg-warning "shadows a previous local" }
+ Bar *cbp; // { dg-warning "shadows a previous local" }
+ ChildBar *bp; // { dg-warning "shadows a previous local" }
+ func1(bar);
+ }
+ }
+};
+
+// { dg-message "shadowed declaration is here" "" { target *-*-* } 26 }
diff --git a/gcc/testsuite/g++.old-deja/g++.eh/spec7.C b/gcc/testsuite/g++.old-deja/g++.eh/spec7.C
index 2ef88a24900..2a4a989913d 100644
--- a/gcc/testsuite/g++.old-deja/g++.eh/spec7.C
+++ b/gcc/testsuite/g++.old-deja/g++.eh/spec7.C
@@ -10,7 +10,7 @@ struct A
static void (A::*pmf)() throw ();
};
-void (A::* A::pmf)() = &A::g;
+void (A::* A::pmf)() throw() = &A::g;
int main()
{
diff --git a/gcc/testsuite/g++.old-deja/g++.law/except1.C b/gcc/testsuite/g++.old-deja/g++.law/except1.C
index 9a2123c3e86..d11afc8b64f 100644
--- a/gcc/testsuite/g++.old-deja/g++.law/except1.C
+++ b/gcc/testsuite/g++.old-deja/g++.law/except1.C
@@ -7,7 +7,7 @@
// Subject: Bugs
// Date: Wed, 22 Jul 92 08:29:30 EDT
-extern "C" void puts(const char *);
+extern "C" int puts(const char *);
class foo {
public:
diff --git a/gcc/testsuite/g++.old-deja/g++.other/vbase5.C b/gcc/testsuite/g++.old-deja/g++.other/vbase5.C
index 10c2f313157..3d22ff50dff 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/vbase5.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/vbase5.C
@@ -6,7 +6,7 @@
// vbases. Normally that's just a pessimization, unfortunately during
// constructoring it leads to uninitialized reads.
-extern "C" int printf (...);
+extern "C" int printf (const char*,...);
int fail = 0;
diff --git a/gcc/testsuite/gcc.c-torture/compile/20001226-1.c b/gcc/testsuite/gcc.c-torture/compile/20001226-1.c
index 127c4daec45..687b43a6bcb 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20001226-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20001226-1.c
@@ -1,7 +1,6 @@
/* { dg-do assemble } */
/* { dg-skip-if "too much code for avr" { "avr-*-*" } { "*" } { "" } } */
/* { dg-skip-if "too much code for pdp11" { "pdp11-*-*" } { "*" } { "" } } */
-/* { dg-xfail-if "jump beyond 128K not supported" { xtensa*-*-* } { "-O0" } { "" } } */
/* { dg-xfail-if "PR36698" { spu-*-* } { "-O0" } { "" } } */
/* { dg-skip-if "" { m32c-*-* } { "*" } { "" } } */
/* { dg-timeout-factor 4.0 } */
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr78162.c b/gcc/testsuite/gcc.c-torture/compile/pr78162.c
new file mode 100644
index 00000000000..743d4e678b5
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr78162.c
@@ -0,0 +1,10 @@
+/* PR tree-optimization/78162.
+ Handle negative offsets in store merging gracefully. */
+
+int a, b[1][2];
+
+void fn1()
+{
+ for (a = 0; a < 2; a++)
+ b[-1][a] = 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr78170.c b/gcc/testsuite/gcc.c-torture/execute/pr78170.c
new file mode 100644
index 00000000000..dce8a3eee36
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/pr78170.c
@@ -0,0 +1,39 @@
+/* { dg-require-effective-target int32plus } */
+
+/* PR tree-optimization/78170.
+ Check that sign-extended store to a bitfield
+ doesn't overwrite other fields. */
+
+int a, b, d;
+
+struct S0
+{
+ int f0;
+ int f1;
+ int f2;
+ int f3;
+ int f4;
+ int f5:15;
+ int f6:17;
+ int f7:2;
+ int f8:30;
+} c;
+
+void fn1 ()
+{
+ d = b = 1;
+ for (; b; b = a)
+ {
+ struct S0 e = { 0, 0, 0, 0, 0, 0, 1, 0, 1 };
+ c = e;
+ c.f6 = -1;
+ }
+}
+
+int main ()
+{
+ fn1 ();
+ if (c.f7 != 0)
+ __builtin_abort ();
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/Wshadow-compatible-local-1.c b/gcc/testsuite/gcc.dg/Wshadow-compatible-local-1.c
new file mode 100644
index 00000000000..ed7b2e45ef1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wshadow-compatible-local-1.c
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-options "-Wshadow=compatible-local" } */
+
+struct Bar {
+};
+
+struct Bar bar; /* { dg-bogus "shadowed declaration" } */
+
+int val; /* { dg-bogus "shadowed declaration" } */
+
+int func1(int x) { /* { dg-bogus "shadowed declaration" } */
+ int val; /* { dg-bogus "shadows a global" } */
+ val = x;
+ return val;
+}
+
+int func2(int i) {
+ int a = 3; /* { dg-message "shadowed declaration" } */
+ int j; /* { dg-message "shadowed declaration" } */
+
+ for (j = 0; j < i; ++j) {
+ int a = j; /* { dg-warning "shadows a previous local" } */
+ int j = a + 1; /* { dg-warning "shadows a previous local" } */
+ func1(j);
+ }
+
+ return a;
+}
+
+void func4() {
+ struct Bar bar; /* { dg-bogus "shadowed declaration" } */
+ if (val) {
+ int bar; /* { dg-bogus "shadows a previous local" } */
+ func1(bar);
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/Wshadow-local-1.c b/gcc/testsuite/gcc.dg/Wshadow-local-1.c
new file mode 100644
index 00000000000..161f9941fb6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wshadow-local-1.c
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-Wshadow=local" } */
+
+int decl1; /* should not warn */
+void foo (double decl1) /* should not warn */
+{
+}
+
+void foo2 (int d) /* { dg-message "shadowed declaration" } */
+{
+ {
+ double d; /* { dg-warning "shadows a parameter" } */
+ }
+}
+
+void foo3 ()
+{
+ int local; /* { dg-message "shadowed declaration" } */
+ {
+ int local; /* { dg-warning "shadows a previous local" } */
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/Wshadow-local-2.c b/gcc/testsuite/gcc.dg/Wshadow-local-2.c
new file mode 100644
index 00000000000..8f6b132f66d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wshadow-local-2.c
@@ -0,0 +1,49 @@
+/* { dg-do compile } */
+/* { dg-options "-Wshadow=local" } */
+
+struct Bar {
+};
+
+struct Bar bar; /* { dg-bogus "shadowed declaration" } */
+
+int val; /* { dg-bogus "shadowed declaration" } */
+
+int func1(int x) { /* { dg-bogus "shadowed declaration" } */
+ int val; /* { dg-bogus "shadows a global" } */
+ val = x;
+ return val;
+}
+
+int func2(int i) {
+ int a = 3; /* { dg-message "shadowed declaration" } */
+ int j; /* { dg-message "shadowed declaration" } */
+
+ for (j = 0; j < i; ++j) {
+ int a = j; /* { dg-warning "shadows a previous local" } */
+ int j = a + 1; /* { dg-warning "shadows a previous local" } */
+ func1(j);
+ }
+
+ return a;
+}
+
+int func3() {
+ int bar; /* { dg-bogus "shadows a global" } */
+ float func1 = 0.3; /* { dg-bogus "shadows a global" } */
+
+ if (func1 > 1)
+ bar = 2;
+ else
+ bar = 1;
+ return bar;
+}
+
+void func4() {
+ struct Bar bar; /* { dg-message "shadowed declaration" } */
+ if (val) {
+ int bar; /* { dg-warning "shadows a previous local" } */
+ func1(bar);
+ }
+}
+
+/* { dg-bogus "shadows a global" "" { target *-*-* } 42 } */
diff --git a/gcc/testsuite/gcc.dg/Wshadow-local-3.c b/gcc/testsuite/gcc.dg/Wshadow-local-3.c
new file mode 100644
index 00000000000..429df37f541
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wshadow-local-3.c
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+/* { dg-options "-Wno-shadow" } */
+
+void func() {
+ int i;
+ {
+ int i; /* should not warn */
+ }
+}
diff --git a/gcc/testsuite/gcc.dg/Wtrampolines.c b/gcc/testsuite/gcc.dg/Wtrampolines.c
index 62b782a8bf0..e2e9cd4c8fd 100644
--- a/gcc/testsuite/gcc.dg/Wtrampolines.c
+++ b/gcc/testsuite/gcc.dg/Wtrampolines.c
@@ -28,7 +28,7 @@ void foo (void)
double a (int k, pfun x1, pfun x2, pfun x3, pfun x4, pfun x5)
{
- double b (void) /* { dg-warning "trampoline generated for nested function 'b'" "standard descriptors" { xfail ia64-*-* powerpc64-*-* } } */
+ double b (void) /* { dg-warning "trampoline generated for nested function 'b'" "standard descriptors" { xfail ia64-*-* powerpc64-*-* *-*-aix* } } */
{
k = k - 1;
return a (k, b, x1, x2, x3, x4 );
diff --git a/gcc/testsuite/gcc.dg/addr_equal-1.c b/gcc/testsuite/gcc.dg/addr_equal-1.c
index 94499f067b4..dd237a7d3cd 100644
--- a/gcc/testsuite/gcc.dg/addr_equal-1.c
+++ b/gcc/testsuite/gcc.dg/addr_equal-1.c
@@ -3,6 +3,7 @@
/* { dg-require-weak "" } */
/* { dg-require-alias "" } */
/* { dg-options "-O2" } */
+/* { dg-skip-if "" { powerpc-ibm-aix* } } */
void abort (void);
extern int undef_var0, undef_var1;
extern __attribute__ ((weak)) int weak_undef_var0;
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-1.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-1.c
new file mode 100644
index 00000000000..bdbc97becae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-1.c
@@ -0,0 +1,18 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+int
+main (void)
+{
+ char *ptr;
+ {
+ char my_char[9];
+ ptr = &my_char[0];
+ }
+
+ return *(ptr+8);
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size 1 at.*" }
+// { dg-output ".*'my_char' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-2.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-2.c
new file mode 100644
index 00000000000..dedb73400cd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-2.c
@@ -0,0 +1,47 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+int *bar (int *x, int *y) { return y; }
+
+int foo (void)
+{
+ char *p;
+ {
+ char a = 0;
+ p = &a;
+ }
+
+ if (*p)
+ return 1;
+ else
+ return 0;
+}
+
+int
+main (void)
+{
+ char *ptr;
+ {
+ char my_char[9];
+ ptr = &my_char[0];
+ }
+
+ int a[16];
+ int *p, *q = a;
+ {
+ int b[16];
+ p = bar (a, b);
+ }
+ bar (a, q);
+ {
+ int c[16];
+ q = bar (a, c);
+ }
+ int v = *bar (a, q);
+ return v;
+}
+
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size 4 at.*" }
+// { dg-output ".*'c' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-3.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-3.c
new file mode 100644
index 00000000000..9aeed51a770
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-3.c
@@ -0,0 +1,20 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+int
+main (void)
+{
+ char *ptr;
+ char *ptr2;
+ {
+ char my_char[9];
+ ptr = &my_char[0];
+ __builtin_memcpy (&ptr2, &ptr, sizeof (ptr2));
+ }
+
+ *(ptr2+9) = 'c';
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "WRITE of size 1 at.*" }
+// { dg-output ".*'my_char' <== Memory access at offset \[0-9\]* overflows this variable.*" }
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c
new file mode 100644
index 00000000000..77d7052bd19
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-4.c
@@ -0,0 +1,16 @@
+// { dg-do run }
+
+int
+__attribute__((no_sanitize_address))
+main (void)
+{
+ char *ptr;
+ char *ptr2;
+ {
+ char my_char[9];
+ ptr = &my_char[0];
+ __builtin_memcpy (&ptr2, &ptr, sizeof (ptr2));
+ }
+
+ *(ptr2+9) = 'c';
+}
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-5.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-5.c
new file mode 100644
index 00000000000..b53712daa34
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-5.c
@@ -0,0 +1,27 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+int *ptr;
+
+__attribute__((always_inline))
+inline static void
+foo(int v)
+{
+ int values[10];
+ for (unsigned i = 0; i < 10; i++)
+ values[i] = v;
+
+ ptr = &values[3];
+}
+
+int
+main (int argc, char **argv)
+{
+ foo (argc);
+
+ return *ptr;
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size 4 at.*" }
+// { dg-output ".*'values' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-6.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-6.c
new file mode 100644
index 00000000000..bb13cecbd1a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-6.c
@@ -0,0 +1,15 @@
+// { dg-do run }
+// { dg-additional-options "--param asan-stack=0" }
+
+int
+main (void)
+{
+ char *ptr;
+ {
+ char my_char[9];
+ ptr = &my_char[0];
+ }
+
+ *ptr = 'c';
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-7.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-7.c
new file mode 100644
index 00000000000..41152059160
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-7.c
@@ -0,0 +1,15 @@
+// { dg-do run }
+// { dg-additional-options "-fno-sanitize-address-use-after-scope" }
+
+int
+main (void)
+{
+ char *ptr;
+ {
+ char my_char[9];
+ ptr = &my_char[0];
+ }
+
+ *ptr = 'c';
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-9.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-9.c
new file mode 100644
index 00000000000..2e30deffa18
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-9.c
@@ -0,0 +1,20 @@
+// { dg-do run }
+// { dg-shouldfail "asan" }
+
+int
+main (int argc, char **argv)
+{
+ int *ptr = 0;
+
+ {
+ int a;
+ ptr = &a;
+ *ptr = 12345;
+ }
+
+ return *ptr;
+}
+
+// { dg-output "ERROR: AddressSanitizer: stack-use-after-scope on address.*(\n|\r\n|\r)" }
+// { dg-output "READ of size .*" }
+// { dg-output ".*'a' <== Memory access at offset \[0-9\]* is inside this variable.*" }
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-goto-1.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-goto-1.c
new file mode 100644
index 00000000000..c47a5e8db02
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-goto-1.c
@@ -0,0 +1,47 @@
+// { dg-do run }
+// { dg-additional-options "-fdump-tree-asan0" }
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+
+int main(int argc, char **argv)
+{
+ int a = 123;
+ int b = 123;
+ int c = 123;
+ int d = 123;
+ int e = 123;
+ int f = 123;
+
+ if (argc == 0)
+ {
+ int *ptr;
+ int *ptr2;
+ int *ptr3;
+ int *ptr4;
+ int *ptr5;
+ int *ptr6;
+ label:
+ {
+ ptr = &a;
+ *ptr = 1;
+ ptr2 = &b;
+ *ptr2 = 1;
+ ptr3 = &c;
+ *ptr3 = 1;
+ ptr4 = &d;
+ *ptr4 = 1;
+ ptr5 = &e;
+ *ptr5 = 1;
+ ptr6 = &f;
+ *ptr6 = 1;
+ return 0;
+ }
+ }
+ else
+ goto label;
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(2, &a, 4\\);" 2 "asan0" } } */
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(2, &c, 4\\);" 2 "asan0" } } */
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(2, &e, 4\\);" 2 "asan0" } } */
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-goto-2.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-goto-2.c
new file mode 100644
index 00000000000..73ef4e0eb1e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-goto-2.c
@@ -0,0 +1,25 @@
+// { dg-do run }
+// { dg-additional-options "-fdump-tree-asan0" }
+/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */
+
+int main(int argc, char **argv)
+{
+ int a = 123;
+
+ if (argc == 0)
+ {
+ int *ptr;
+ /* The label is not used in &label or goto label. Thus '&a' should be
+ marked just once. */
+ label:
+ {
+ ptr = &a;
+ *ptr = 1;
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(2, &a, 4\\);" 1 "asan0" } } */
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-switch-1.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-switch-1.c
new file mode 100644
index 00000000000..a8342686d4e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-switch-1.c
@@ -0,0 +1,25 @@
+// { dg-do run }
+// { dg-additional-options "-fdump-tree-gimple" }
+
+int
+main (int argc, char **argv)
+{
+ int *ptr = 0;
+
+ for (unsigned i = 0; i < 2; i++)
+ {
+ switch (argc)
+ {
+ int a;
+ default:
+ ptr = &a;
+ *ptr = 12345;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(2, &a, \[0-9\]\\);" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(1, &a, \[0-9\]\\);" 1 "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-switch-2.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-switch-2.c
new file mode 100644
index 00000000000..8aeca5a3b7a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-switch-2.c
@@ -0,0 +1,33 @@
+// { dg-do run }
+// { dg-additional-options "-fdump-tree-gimple" }
+
+int
+main (int argc, char **argv)
+{
+ int *ptr = 0;
+ int *ptr2 = 0;
+ int *ptr3 = 0;
+
+ for (unsigned i = 0; i < 2; i++)
+ {
+ switch (argc)
+ {
+ case 1111:;
+ int a, b, c;
+ default:
+ ptr = &a;
+ ptr2 = &b;
+ ptr3 = &c;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(2, &a, \[0-9\]\\);" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(2, &b, \[0-9\]\\);" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(2, &c, \[0-9\]\\);" 2 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(1, &a, \[0-9\]\\);" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(1, &b, \[0-9\]\\);" 1 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(1, &c, \[0-9\]\\);" 1 "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/asan/use-after-scope-switch-3.c b/gcc/testsuite/gcc.dg/asan/use-after-scope-switch-3.c
new file mode 100644
index 00000000000..828cb7c3b2a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/asan/use-after-scope-switch-3.c
@@ -0,0 +1,36 @@
+// { dg-do run }
+// { dg-additional-options "-fdump-tree-gimple" }
+
+int
+main (int argc, char **argv)
+{
+ int *ptr = 0;
+
+ for (unsigned i = 0; i < 2; i++)
+ {
+ switch (argc)
+ {
+ case 11111:;
+ int a;
+ ptr = &a;
+ break;
+ {
+ default:
+ ptr = &a;
+ *ptr = 12345;
+ case 222222:
+ my_label:
+ ptr = &a;
+ break;
+ }
+ }
+ }
+
+ if (argc == 333333)
+ goto my_label;
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(2, &a, \[0-9\]\\);" 4 "gimple" } } */
+/* { dg-final { scan-tree-dump-times "ASAN_MARK \\(1, &a, \[0-9\]\\);" 1 "gimple" } } */
diff --git a/gcc/testsuite/gcc.dg/cpp/trad/include.c b/gcc/testsuite/gcc.dg/cpp/trad/include.c
index 94d25f815c6..967476d3a1f 100644
--- a/gcc/testsuite/gcc.dg/cpp/trad/include.c
+++ b/gcc/testsuite/gcc.dg/cpp/trad/include.c
@@ -2,11 +2,5 @@
/* Test that macros are not expanded in the <> quotes of #inlcude. */
-/* vxWorksCommon.h uses the "#" operator to construct the name of an
- include file, thus making the file incompatible with -traditional-cpp.
- Newlib uses ## when including stdlib.h as of 2007-09-07. */
-/* { dg-do preprocess { target { { ! vxworks_kernel } && { ! newlib } } } } */
-
-#define __STDC__ 1 /* Stop complaints about non-ISO compilers. */
-#define stdlib 1
-#include <stdlib.h> /* { dg-bogus "o such file or directory" } */
+#define builtins 1
+#include <builtins.h> /* { dg-bogus "o such file or directory" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/trad/trad.exp b/gcc/testsuite/gcc.dg/cpp/trad/trad.exp
index 5f090ac54a0..01e1400b3c3 100644
--- a/gcc/testsuite/gcc.dg/cpp/trad/trad.exp
+++ b/gcc/testsuite/gcc.dg/cpp/trad/trad.exp
@@ -37,7 +37,7 @@ dg-init
# Main loop.
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
- "" $DEFAULT_TRADCPPFLAGS
+ "-I$srcdir/$subdir/" $DEFAULT_TRADCPPFLAGS
# All done.
dg-finish
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/pr71855.c b/gcc/testsuite/gcc.dg/debug/dwarf2/pr71855.c
index 4fd8b74f329..3842dbc0270 100644
--- a/gcc/testsuite/gcc.dg/debug/dwarf2/pr71855.c
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/pr71855.c
@@ -8,4 +8,4 @@ foo (const char *format, ...)
{
}
-// { dg-final { scan-assembler-times "DIE.*DW_TAG_unspecified_parameters" 1 } }
+// { dg-final { scan-assembler-times "DIE.*DW_TAG_unspecified_parameters" 1 { xfail { powerpc-ibm-aix* } } } }
diff --git a/gcc/testsuite/gcc.dg/debug/dwarf2/prod-options.c b/gcc/testsuite/gcc.dg/debug/dwarf2/prod-options.c
index e6bc1371f26..6577eff3548 100644
--- a/gcc/testsuite/gcc.dg/debug/dwarf2/prod-options.c
+++ b/gcc/testsuite/gcc.dg/debug/dwarf2/prod-options.c
@@ -4,7 +4,7 @@
as well. */
/* { dg-do compile } */
/* { dg-options "-O2 -gdwarf -dA -fdebug-prefix-map=a=b" } */
-/* { dg-final { scan-assembler "DW_AT_producer: \"GNU C" { target { { { ! *-*-solaris2* } || gas } && { ! hppa*64*-*-* } } } } } */
+/* { dg-final { scan-assembler "DW_AT_producer: \"GNU C" { target { { { ! *-*-solaris2* } || gas } && { { ! hppa*64*-*-* } && { ! powerpc-ibm-aix* } } } } } } */
/* { dg-final { scan-assembler "\"GNU C\[^\\n\\r\]+ DW_AT_producer" { target { { *-*-solaris2* && { ! gas } } || { hppa*64*-*-* } } } } } */
/* { dg-final { scan-assembler-not "debug-prefix-map" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-1-simode.c b/gcc/testsuite/gcc.dg/divmod-1-simode.c
new file mode 100644
index 00000000000..9e477997bcf
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-1-simode.c
@@ -0,0 +1,25 @@
+/* { dg-require-effective-target divmod_simode } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* div dominates mod. */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y) \
+{ \
+ bigtype q = x / y; \
+ if (cond) \
+ foo (); \
+ bigtype r = x % y; \
+ return q + r; \
+}
+
+FOO(SImode, SImode, 1)
+FOO(SImode, USImode, 2)
+FOO(USImode, USImode, 3)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-1.c b/gcc/testsuite/gcc.dg/divmod-1.c
new file mode 100644
index 00000000000..edcc2a107da
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-1.c
@@ -0,0 +1,32 @@
+/* { dg-require-effective-target divmod } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* div dominates mod. */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+typedef int DImode __attribute__((mode(DI)));
+typedef unsigned UDImode __attribute__((mode(DI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y) \
+{ \
+ bigtype q = x / y; \
+ if (cond) \
+ foo (); \
+ bigtype r = x % y; \
+ return q + r; \
+}
+
+FOO(SImode, DImode, 1)
+FOO(SImode, UDImode, 2)
+FOO(USImode, DImode, 3)
+FOO(USImode, UDImode, 4)
+FOO(DImode, DImode, 5)
+FOO(DImode, UDImode, 6)
+FOO(UDImode, UDImode, 7)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 7 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-2-simode.c b/gcc/testsuite/gcc.dg/divmod-2-simode.c
new file mode 100644
index 00000000000..fa28beb3cef
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-2-simode.c
@@ -0,0 +1,25 @@
+/* { dg-require-effective-target divmod_simode } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* mod dominates div. */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y) \
+{ \
+ bigtype r = x % y; \
+ if (cond) \
+ foo (); \
+ bigtype q = x / y; \
+ return q + r; \
+}
+
+FOO(SImode, SImode, 1)
+FOO(SImode, USImode, 2)
+FOO(USImode, USImode, 3)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-2.c b/gcc/testsuite/gcc.dg/divmod-2.c
new file mode 100644
index 00000000000..ded732e121d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-2.c
@@ -0,0 +1,32 @@
+/* { dg-require-effective-target divmod } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* mod dominates div. */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+typedef int DImode __attribute__((mode(DI)));
+typedef unsigned UDImode __attribute__((mode(DI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y) \
+{ \
+ bigtype r = x % y; \
+ if (cond) \
+ foo (); \
+ bigtype q = x / y; \
+ return q + r; \
+}
+
+FOO(SImode, DImode, 1)
+FOO(SImode, UDImode, 2)
+FOO(USImode, DImode, 3)
+FOO(USImode, UDImode, 4)
+FOO(DImode, DImode, 5)
+FOO(DImode, UDImode, 6)
+FOO(UDImode, UDImode, 7)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 7 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-3-simode.c b/gcc/testsuite/gcc.dg/divmod-3-simode.c
new file mode 100644
index 00000000000..9dee5bf603b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-3-simode.c
@@ -0,0 +1,23 @@
+/* { dg-require-effective-target divmod_simode } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* div comes before mod in same bb. */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y) \
+{ \
+ bigtype q = x / y; \
+ bigtype r = x % y; \
+ return q + r; \
+}
+
+FOO(SImode, SImode, 1)
+FOO(SImode, USImode, 2)
+FOO(USImode, USImode, 3)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-3.c b/gcc/testsuite/gcc.dg/divmod-3.c
new file mode 100644
index 00000000000..02aa367ac6e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-3.c
@@ -0,0 +1,30 @@
+/* { dg-require-effective-target divmod } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* div comes before mod in same bb. */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+typedef int DImode __attribute__((mode(DI)));
+typedef unsigned UDImode __attribute__((mode(DI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y) \
+{ \
+ bigtype q = x / y; \
+ bigtype r = x % y; \
+ return q + r; \
+}
+
+FOO(SImode, DImode, 1)
+FOO(SImode, UDImode, 2)
+FOO(USImode, DImode, 3)
+FOO(USImode, UDImode, 4)
+FOO(DImode, DImode, 5)
+FOO(DImode, UDImode, 6)
+FOO(UDImode, UDImode, 7)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 7 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-4-simode.c b/gcc/testsuite/gcc.dg/divmod-4-simode.c
new file mode 100644
index 00000000000..dbe29cb761d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-4-simode.c
@@ -0,0 +1,23 @@
+/* { dg-require-effective-target divmod_simode } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* mod comes before div in same bb. */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y) \
+{ \
+ bigtype r = x % y; \
+ bigtype q = x / y; \
+ return q + r; \
+}
+
+FOO(SImode, SImode, 1)
+FOO(SImode, USImode, 2)
+FOO(USImode, USImode, 3)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-4.c b/gcc/testsuite/gcc.dg/divmod-4.c
new file mode 100644
index 00000000000..861ecbdec4b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-4.c
@@ -0,0 +1,30 @@
+/* { dg-require-effective-target divmod } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* mod comes before div in same bb. */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+typedef int DImode __attribute__((mode(DI)));
+typedef unsigned UDImode __attribute__((mode(DI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y) \
+{ \
+ bigtype r = x % y; \
+ bigtype q = x / y; \
+ return q + r; \
+}
+
+FOO(SImode, DImode, 3)
+FOO(SImode, UDImode, 4)
+FOO(USImode, DImode, 6)
+FOO(USImode, UDImode, 7)
+FOO(DImode, DImode, 8)
+FOO(DImode, UDImode, 9)
+FOO(UDImode, UDImode, 10)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 7 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-5.c b/gcc/testsuite/gcc.dg/divmod-5.c
new file mode 100644
index 00000000000..8a8cee50ae2
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-5.c
@@ -0,0 +1,19 @@
+/* { dg-require-effective-target divmod_simode } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+/* div and mod are not in same bb and
+ bb's containing div and mod don't dominate each other. */
+
+int f(int x, int y)
+{
+ int q = 0;
+ int r = 0;
+ extern int cond;
+
+ if (cond)
+ q = x / y;
+
+ r = x % y;
+ return q + r;
+}
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 0 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-6-simode.c b/gcc/testsuite/gcc.dg/divmod-6-simode.c
new file mode 100644
index 00000000000..1107f760b42
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-6-simode.c
@@ -0,0 +1,26 @@
+/* { dg-require-effective-target divmod_simode } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y) \
+{ \
+ bigtype q = x / y; \
+ bigtype r1 = 0, r2 = 0; \
+ if (cond) \
+ r1 = x % y; \
+ else \
+ r2 = x % y; \
+ return q + r1 + r2; \
+}
+
+FOO(SImode, SImode, 1)
+FOO(SImode, USImode, 2)
+FOO(USImode, USImode, 3)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 3 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-6.c b/gcc/testsuite/gcc.dg/divmod-6.c
new file mode 100644
index 00000000000..495ebaff805
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-6.c
@@ -0,0 +1,33 @@
+/* { dg-require-effective-target divmod } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+
+typedef int SImode __attribute__((mode(SI)));
+typedef unsigned USImode __attribute__((mode(SI)));
+
+typedef int DImode __attribute__((mode(DI)));
+typedef unsigned UDImode __attribute__((mode(DI)));
+
+extern int cond;
+void foo(void);
+
+#define FOO(smalltype, bigtype, no) \
+bigtype f_##no(smalltype x, bigtype y) \
+{ \
+ bigtype q = x / y; \
+ bigtype r1 = 0, r2 = 0; \
+ if (cond) \
+ r1 = x % y; \
+ else \
+ r2 = x % y; \
+ return q + r1 + r2; \
+}
+
+FOO(SImode, DImode, 3)
+FOO(SImode, UDImode, 4)
+FOO(USImode, DImode, 6)
+FOO(USImode, UDImode, 7)
+FOO(DImode, DImode, 8)
+FOO(DImode, UDImode, 9)
+FOO(UDImode, UDImode, 10)
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 7 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/divmod-7.c b/gcc/testsuite/gcc.dg/divmod-7.c
new file mode 100644
index 00000000000..faa90b3ac8f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/divmod-7.c
@@ -0,0 +1,21 @@
+/* { dg-require-effective-target divmod_simode } */
+/* { dg-options "-O2 -fdump-tree-widening_mul-details" } */
+
+int f(int x, int y)
+{
+ int q = 0, r1 = 0, r2 = 0;
+ extern int cond;
+
+ if (cond)
+ q = x / y;
+ else
+ {
+ r1 = x % y;
+ return q + r1;
+ }
+
+ r2 = x % y;
+ return q + r2;
+}
+
+/* { dg-final { scan-tree-dump-times "DIVMOD" 1 "widening_mul" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/pr78121.c b/gcc/testsuite/gcc.dg/ipa/pr78121.c
new file mode 100644
index 00000000000..4a0ae187256
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/pr78121.c
@@ -0,0 +1,16 @@
+/* PR ipa/78121 */
+/* { dg-do compile } */
+/* { dg-options "-ansi -O2 -fdump-ipa-cp-details" } */
+
+void fn2 (unsigned char c);
+int a;
+static void fn1(c) unsigned char c;
+{
+ if (a)
+ fn2 (c);
+ fn1('#');
+}
+
+void fn3() { fn1 (267); }
+
+/* { dg-final { scan-ipa-dump-times "Setting value range of param 0 \\\[11, 35\\\]" 1 "cp" } } */
diff --git a/gcc/testsuite/gcc.dg/ipa/vrp7.c b/gcc/testsuite/gcc.dg/ipa/vrp7.c
new file mode 100644
index 00000000000..e4e0bc66a64
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ipa/vrp7.c
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-ipa-cp-details" } */
+
+volatile int cond;
+int abs (int);
+
+static __attribute__((noinline, noclone))
+int foo (int i)
+{
+ if (i < 5)
+ __builtin_abort ();
+ return 0;
+}
+
+static __attribute__((noinline, noclone))
+int bar (int j)
+{
+ foo (~j);
+ foo (abs (j));
+ foo (j);
+ return 0;
+}
+
+int main ()
+{
+ for (unsigned int i = 0; i < 10; ++i)
+ bar (i);
+
+ return 0;
+}
+
+/* { dg-final { scan-ipa-dump-times "Setting value range of param 0 \\\[-10, 9\\\]" 1 "cp" } } */
diff --git a/gcc/testsuite/gcc.dg/lto/pr60449_0.c b/gcc/testsuite/gcc.dg/lto/pr60449_0.c
index a430830cbed..5b878a640db 100644
--- a/gcc/testsuite/gcc.dg/lto/pr60449_0.c
+++ b/gcc/testsuite/gcc.dg/lto/pr60449_0.c
@@ -1,4 +1,5 @@
/* { dg-lto-do link } */
+/* { dg-skip-if "Needs gettimeofday" { "avr-*-*" } } */
extern int printf (const char *__restrict __format, ...);
typedef long int __time_t;
diff --git a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c
index c93d1718b64..e0c2600b400 100644
--- a/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c
+++ b/gcc/testsuite/gcc.dg/no_profile_instrument_function-attr-1.c
@@ -19,5 +19,5 @@ int main ()
/* { dg-final { scan-tree-dump-times "__gcov0\\.main.* = PROF_edge_counter" 1 "optimized"} } */
/* { dg-final { scan-tree-dump-times "__gcov_indirect_call_profiler_v2" 1 "optimized" } } */
-/* { dg-final { scan-tree-dump-times "__gcov_time_profiler" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "__gcov_time_profiler_counter = " 1 "optimized" } } */
/* { dg-final { scan-tree-dump-times "__gcov_init" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pr35691-1.c b/gcc/testsuite/gcc.dg/pr35691-1.c
new file mode 100644
index 00000000000..125923dd24c
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr35691-1.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-forwprop-details" } */
+
+int foo(int z0, unsigned z1)
+{
+ int t0 = (z0 == 0);
+ int t1 = (z1 == 0);
+ int t2 = (t0 & t1);
+ return t2;
+}
+
+/* { dg-final { scan-tree-dump "gimple_simplified to _\[0-9\]* = \\(int\\) z1_\[0-9\]*\\(D\\);" "forwprop1" } } */
diff --git a/gcc/testsuite/gcc.dg/pr35691-2.c b/gcc/testsuite/gcc.dg/pr35691-2.c
new file mode 100644
index 00000000000..70f68a685d7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr35691-2.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-forwprop-details" } */
+
+int foo(int z0, unsigned z1)
+{
+ int t0 = (z0 != 0);
+ int t1 = (z1 != 0);
+ int t2 = (t0 | t1);
+ return t2;
+}
+
+/* { dg-final { scan-tree-dump "gimple_simplified to _\[0-9\]* = \\(int\\) z1_\[0-9\]*\\(D\\);" "forwprop1" } } */
diff --git a/gcc/testsuite/gcc.dg/pr65779.c b/gcc/testsuite/gcc.dg/pr65779.c
index 7d5c522d042..814cb2cdeef 100644
--- a/gcc/testsuite/gcc.dg/pr65779.c
+++ b/gcc/testsuite/gcc.dg/pr65779.c
@@ -1,6 +1,7 @@
/* PR debug/65779 */
/* { dg-do assemble } */
/* { dg-options "-O2 -fcompare-debug" } */
+/* { dg-xfail-if "" { powerpc-ibm-aix* } { "*" } { "" } } */
unsigned long
foo (unsigned long x, unsigned char *y, unsigned int z)
diff --git a/gcc/testsuite/gcc.dg/pr70405.c b/gcc/testsuite/gcc.dg/pr70405.c
index bff390ff06d..a2bc96ac241 100644
--- a/gcc/testsuite/gcc.dg/pr70405.c
+++ b/gcc/testsuite/gcc.dg/pr70405.c
@@ -2,6 +2,7 @@
/* { dg-do compile } */
/* { dg-options "-O2 -fcompare-debug" } */
/* { dg-additional-options "-mavx512f" { target i?86-*-* x86_64-*-* } } */
+/* { dg-xfail-if "" { powerpc-ibm-aix* } { "*" } { "" } } */
typedef short V __attribute__ ((vector_size (32)));
diff --git a/gcc/testsuite/gcc.dg/pr77834.c b/gcc/testsuite/gcc.dg/pr77834.c
new file mode 100644
index 00000000000..a9085b95393
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr77834.c
@@ -0,0 +1,18 @@
+/* PR target/77834 */
+/* { dg-do compile } */
+/* { dg-options "-O -ftree-pre -Wno-psabi" } */
+/* { dg-additional-options "-mstringop-strategy=libcall" { target i?86-*-* x86_64-*-* } } */
+
+typedef int V __attribute__ ((vector_size (64)));
+
+V
+foo (V u, V v, int w)
+{
+ do
+ {
+ if (u[0]) v ^= u[w];
+ }
+ while ((V) { 0, u[w] }[1]);
+ u = (V) { v[v[0]], u[u[0]] };
+ return v + u;
+}
diff --git a/gcc/testsuite/gcc.dg/pr77860.c b/gcc/testsuite/gcc.dg/pr77860.c
new file mode 100644
index 00000000000..04346b16e77
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr77860.c
@@ -0,0 +1,13 @@
+/* PR tree-optimization/77860 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fno-tree-vrp -fno-tree-forwprop -Wno-psabi" } */
+
+typedef unsigned short V __attribute__((vector_size (16)));
+
+V
+foo (V x, V y)
+{
+ V a = -x;
+ V b = -y;
+ return a * b;
+}
diff --git a/gcc/testsuite/gcc.dg/pr78148.c b/gcc/testsuite/gcc.dg/pr78148.c
new file mode 100644
index 00000000000..c3c9b2e9a89
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr78148.c
@@ -0,0 +1,31 @@
+/* PR target/78148 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fcompare-debug" } */
+
+struct A { int a, b; };
+struct B { char c, d; };
+extern void bar (struct A, struct B);
+struct C { char e, f; } a;
+struct D
+{
+ int g;
+ struct C h[4];
+};
+struct D *e;
+
+struct D
+foo (void)
+{
+ int b;
+ struct B c;
+ struct A d;
+ d.b = c.c = c.d = 0;
+ bar (d, c);
+}
+
+void
+baz ()
+{
+ e->h[0].e = e->h[0].f = 0;
+ foo ();
+}
diff --git a/gcc/testsuite/gcc.dg/pr78185.c b/gcc/testsuite/gcc.dg/pr78185.c
new file mode 100644
index 00000000000..405f7489dae
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr78185.c
@@ -0,0 +1,28 @@
+/* { dg-do run { target *-*-linux* *-*-gnu* } } */
+/* { dg-options "-O" } */
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+
+static char var1 = 0L;
+static char *var2 = &var1;
+
+void do_exit (int i)
+{
+ exit (0);
+}
+
+int main(void)
+{
+ struct sigaction s;
+ sigemptyset (&s.sa_mask);
+ s.sa_handler = do_exit;
+ s.sa_flags = 0;
+ sigaction (SIGALRM, &s, NULL);
+ alarm (1);
+ /* The following loop is infinite, the division by zero should not
+ be hoisted out of it. */
+ for (; (var1 == 0 ? 0 : (100 / var1)) == *var2; );
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/store_merging_1.c b/gcc/testsuite/gcc.dg/store_merging_1.c
index 35f4d82e6b2..4cc43dfd9e1 100644
--- a/gcc/testsuite/gcc.dg/store_merging_1.c
+++ b/gcc/testsuite/gcc.dg/store_merging_1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-require-effective-target non_strict_align } */
+/* { dg-require-effective-target store_merge } */
/* { dg-options "-O2 -fdump-tree-store-merging" } */
struct bar {
diff --git a/gcc/testsuite/gcc.dg/store_merging_2.c b/gcc/testsuite/gcc.dg/store_merging_2.c
index 8e2acf39089..8cd29f4243c 100644
--- a/gcc/testsuite/gcc.dg/store_merging_2.c
+++ b/gcc/testsuite/gcc.dg/store_merging_2.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-require-effective-target non_strict_align } */
+/* { dg-require-effective-target store_merge } */
/* { dg-options "-O2 -fdump-tree-store-merging" } */
struct bar
diff --git a/gcc/testsuite/gcc.dg/store_merging_4.c b/gcc/testsuite/gcc.dg/store_merging_4.c
index a3d67697d64..719c2c038e4 100644
--- a/gcc/testsuite/gcc.dg/store_merging_4.c
+++ b/gcc/testsuite/gcc.dg/store_merging_4.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-require-effective-target non_strict_align } */
+/* { dg-require-effective-target store_merge } */
/* { dg-options "-O2 -fdump-tree-store-merging" } */
/* Check that we can merge interleaving stores that are guaranteed
diff --git a/gcc/testsuite/gcc.dg/store_merging_5.c b/gcc/testsuite/gcc.dg/store_merging_5.c
index 4ffe512b842..e6c349767bc 100644
--- a/gcc/testsuite/gcc.dg/store_merging_5.c
+++ b/gcc/testsuite/gcc.dg/store_merging_5.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-require-effective-target non_strict_align } */
+/* { dg-require-effective-target store_merge } */
/* { dg-options "-O2 -fdump-tree-store-merging" } */
/* Make sure that non-aliasing non-constant interspersed stores do not
diff --git a/gcc/testsuite/gcc.dg/store_merging_6.c b/gcc/testsuite/gcc.dg/store_merging_6.c
index 42b5c4f92dc..314829da6d3 100644
--- a/gcc/testsuite/gcc.dg/store_merging_6.c
+++ b/gcc/testsuite/gcc.dg/store_merging_6.c
@@ -1,5 +1,5 @@
/* { dg-do run } */
-/* { dg-require-effective-target non_strict_align } */
+/* { dg-require-effective-target store_merge } */
/* { dg-options "-O2 -fdump-tree-store-merging" } */
/* Check that we can widen accesses to bitfields. */
diff --git a/gcc/testsuite/gcc.dg/store_merging_7.c b/gcc/testsuite/gcc.dg/store_merging_7.c
index 4be352fef4a..c744ece6407 100644
--- a/gcc/testsuite/gcc.dg/store_merging_7.c
+++ b/gcc/testsuite/gcc.dg/store_merging_7.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-require-effective-target non_strict_align } */
+/* { dg-require-effective-target store_merge } */
/* { dg-options "-O2 -fdump-tree-store-merging" } */
/* Check that we can merge consecutive array members through the pointer.
diff --git a/gcc/testsuite/gcc.dg/store_merging_8.c b/gcc/testsuite/gcc.dg/store_merging_8.c
new file mode 100644
index 00000000000..e710a544ff0
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/store_merging_8.c
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target store_merge } */
+/* { dg-options "-O2 -fdump-tree-store-merging" } */
+
+struct baz {
+ struct bar {
+ int a;
+ char b;
+ char c;
+ char d;
+ char e;
+ char f;
+ char g;
+ } a[4];
+} x;
+struct baz *xx = &x;
+
+void
+foo1 (int i)
+{
+ x.a[i].b = 0;
+ x.a[i].a = 0;
+ x.a[i].c = 0;
+ x.a[i].d = 0;
+ x.a[i].e = 0;
+}
+
+void
+foo2 (int i)
+{
+ x.a[i].b = 0;
+ x.a[i].a = 0;
+ x.a[i].c = 1;
+ x.a[i].d = 0;
+ x.a[i].e = 0;
+}
+
+/* { dg-final { scan-tree-dump-times "Merging successful" 2 "store-merging" } } */
diff --git a/gcc/testsuite/gcc.dg/torture/fp-int-convert.h b/gcc/testsuite/gcc.dg/torture/fp-int-convert.h
index 59773e34fa8..bbe96668d0b 100644
--- a/gcc/testsuite/gcc.dg/torture/fp-int-convert.h
+++ b/gcc/testsuite/gcc.dg/torture/fp-int-convert.h
@@ -53,6 +53,8 @@ do { \
TEST_I_F_VAL (U, F, HVAL1U (P, U), P_OK (P, U)); \
TEST_I_F_VAL (U, F, HVAL1U (P, U) + 1, P_OK (P, U)); \
TEST_I_F_VAL (U, F, HVAL1U (P, U) - 1, P_OK (P, U)); \
+ TEST_I_F_VAL (I, F, WVAL0S (I), 1); \
+ TEST_I_F_VAL (I, F, -WVAL0S (I), 1); \
} while (0)
#define P_OK(P, T) ((P) >= sizeof(T) * CHAR_BIT)
@@ -74,6 +76,7 @@ do { \
? (S)1 \
: (((S)1 << (sizeof(S) * CHAR_BIT - 2)) \
+ ((S)3 << (sizeof(S) * CHAR_BIT - 2 - P))))
+#define WVAL0S(S) (S)((S)1 << (sizeof(S) * CHAR_BIT / 2 - 1))
#define TEST_I_F_VAL(IT, FT, VAL, PREC_OK) \
do { \
diff --git a/gcc/testsuite/gcc.dg/torture/pr77309.c b/gcc/testsuite/gcc.dg/torture/pr77309.c
new file mode 100644
index 00000000000..5bdbc0a0b83
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr77309.c
@@ -0,0 +1,14 @@
+/* { dg-do run } */
+
+int a, b;
+
+int main ()
+{
+ long c = 1 % (2 ^ b);
+ c = -c & ~(~(b ^ ~b) || a);
+
+ if (c >= 0)
+ __builtin_abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr78218.c b/gcc/testsuite/gcc.dg/torture/pr78218.c
new file mode 100644
index 00000000000..b3e2892429d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/torture/pr78218.c
@@ -0,0 +1,24 @@
+/* { dg-do run } */
+
+struct
+{
+ int v;
+} a[2];
+
+int b;
+
+void __attribute__((noinline,noclone))
+check ()
+{
+ if (a[0].v != 1)
+ __builtin_abort ();
+}
+
+int main ()
+{
+ a[1].v = 1;
+ a[0] = a[1];
+ a[1].v = 0;
+ check (a);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-prof/time-profiler-3.c b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-3.c
new file mode 100644
index 00000000000..69ce0260828
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-prof/time-profiler-3.c
@@ -0,0 +1,22 @@
+/* { dg-options "-O2 -fdump-ipa-profile -fprofile-update=atomic" } */
+/* { dg-require-effective-target profile_update_atomic } */
+
+__attribute__ ((noinline))
+int foo()
+{
+ return 0;
+}
+
+__attribute__ ((noinline))
+int bar()
+{
+ return 1;
+}
+
+int main ()
+{
+ return foo ();
+}
+/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Read tp_first_run: 0" 1 "profile"} } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Read tp_first_run: 1" 1 "profile"} } */
+/* { dg-final-use-not-autofdo { scan-ipa-dump-times "Read tp_first_run: 2" 1 "profile"} } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-ub.c b/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-ub.c
index df0ede2ba5e..e1658d183c3 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-ub.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/builtins-folding-gimple-ub.c
@@ -17,6 +17,10 @@ main (void)
if (__builtin_memchr (foo1, 'x', 1000)) /* Not folded away. */
__builtin_abort ();
+ /* STRNCMP. */
+ if (strncmp ("a", "b", -1)) /* { dg-warning "implicit declaration of function" } */
+ __builtin_abort ();
+
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c
new file mode 100644
index 00000000000..ac3018ef533
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-15.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int
+foo (int i)
+{
+ if (i > 0)
+ i = -i;
+ return i;
+}
+
+/* { dg-final { scan-tree-dump-not "ABS" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c
index cc7370cad4e..c896857748c 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c
@@ -4,7 +4,7 @@
immediate successors of the basic block. */
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fno-tree-dominator-opts -fdisable-tree-evrp -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
extern void bar (int);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c
index e8b62c2ca1f..950371ba55d 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-dce2 -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1 -fdump-tree-dce2 -fdelete-null-pointer-checks" } */
int
foo (int *p)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr54245.c b/gcc/testsuite/gcc.dg/tree-ssa/pr54245.c
deleted file mode 100644
index b96e3e51f5b..00000000000
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr54245.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-slsr-details" } */
-
-#include <stdio.h>
-
-#define W1 22725
-#define W2 21407
-#define W3 19266
-#define W6 8867
-
-void idct_row(short *row, int *dst)
-{
- int a0, a1, b0, b1;
-
- a0 = W1 * row[0];
- a1 = a0;
-
- a0 += W2 * row[2];
- a1 += W6 * row[2];
-
- b0 = W1 * row[1];
- b1 = W3 * row[1];
-
- dst[0] = a0 + b0;
- dst[1] = a0 - b0;
- dst[2] = a1 + b1;
- dst[3] = a1 - b1;
-}
-
-static short block[8] = { 1, 2, 3, 4 };
-
-int main(void)
-{
- int out[4];
- int i;
-
- idct_row(block, out);
-
- for (i = 0; i < 4; i++)
- printf("%d\n", out[i]);
-
- return !(out[2] == 87858 && out[3] == 10794);
-}
-
-/* For now, disable inserting an initializer when the multiplication will
- take place in a smaller type than originally. This test may be deleted
- in future when this case is handled more precisely. */
-/* { dg-final { scan-tree-dump-times "Inserting initializer" 0 "slsr" { target { ! int16 } } } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c b/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c
index 7df8f8affbd..42898e72d4e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c
@@ -1,5 +1,5 @@
/* { dg-do compile { target { ! keeps_null_pointer_checks } } } */
-/* { dg-options "-O2 -fdump-tree-vrp1 -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1 -fdelete-null-pointer-checks" } */
extern void eliminate (void);
extern void* f1 (void *a, void *b) __attribute__((nonnull));
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr71347.c b/gcc/testsuite/gcc.dg/tree-ssa/pr71347.c
index 428e41bc3bc..d2f7f059f33 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr71347.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr71347.c
@@ -14,4 +14,4 @@ void foo (void)
}
/* Load of X[i - i] can be omitted by reusing X[i] in previous iteration. */
-/* { dg-final { scan-tree-dump-not ".* = MEM.*;" "optimized" { xfail { ia64-*-* arm*-*-* m68k*-*-* } } } } */
+/* { dg-final { scan-tree-dump-not ".* = MEM.*;" "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c b/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c
index 2bd60aad546..585b660886b 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/slsr-8.c
@@ -4,7 +4,7 @@
/* { dg-options "-O3 -fdump-tree-optimized" } */
int*
-f (int s, int *c)
+f (int s, int *c, int *d)
{
int a1, a2, a3, *x1, *x2, *x3;
@@ -14,10 +14,16 @@ f (int s, int *c)
x2 = c - a2;
a3 = 6 * s;
x3 = c - a3;
- return x1 ? x2 : x3;
+ return x1 == d ? x2 : x3;
}
+/* Note that since some branch prediction heuristics changed, the
+ calculations of x2 and x3 are pushed downward into the legs
+ of the conditional, changing the code presented to SLSR.
+ However, this proves to be a useful test for introducing an
+ initializer with a cast, so we'll keep it as is. */
+
/* There are 4 ' * ' instances in the decls (since "int * iftmp.0;" is
- added), 1 parm, 2 in the code. The second one in the code can be
- a widening mult. */
-/* { dg-final { scan-tree-dump-times " w?\\* " 7 "optimized" } } */
+ added), 2 parms, 3 in the code. The second one in the code may
+ be a widening multiply (for example, on AArch64). */
+/* { dg-final { scan-tree-dump-times " w?\\* " 9 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c
index 023b4eb3b94..c2da30b4b68 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
+/* { dg-options "-O2 -fno-tree-fre -fdisable-tree-evrp -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
/* Compile with -fno-tree-fre -O2 to prevent CSEing *p. */
int
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp111.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp111.c
new file mode 100644
index 00000000000..2511c1964bb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp111.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-evrp" } */
+
+void foo (void *p) __attribute__((nonnull(1)));
+
+void bar (void *p)
+{
+ foo (p);
+ if (!p)
+ __builtin_abort ();
+}
+
+/* { dg-final { scan-tree-dump-not "abort" "evrp" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-pr78205.c b/gcc/testsuite/gcc.dg/vect/bb-slp-pr78205.c
new file mode 100644
index 00000000000..e02502a3fc1
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-pr78205.c
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-require-effective-target vect_double } */
+/* { dg-additional-options "-fdump-tree-optimized" } */
+
+double x[2], a[4], b[4], c[5];
+
+void foo ()
+{
+ a[0] = c[0];
+ a[1] = c[1];
+ a[2] = c[0];
+ a[3] = c[1];
+ b[0] = c[2];
+ b[1] = c[3];
+ b[2] = c[2];
+ b[3] = c[3];
+ x[0] = c[4];
+ x[1] = c[4];
+}
+
+/* We may not vectorize the store to x[] as it accesses c out-of bounds
+ but we do want to vectorize the other two store groups. */
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized" 1 "slp2" } } */
+/* { dg-final { scan-tree-dump-times "x\\\[\[0-1\]\\\] = " 2 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr56541.c b/gcc/testsuite/gcc.dg/vect/pr56541.c
index 16b8d7cb75b..d5def6899e4 100644
--- a/gcc/testsuite/gcc.dg/vect/pr56541.c
+++ b/gcc/testsuite/gcc.dg/vect/pr56541.c
@@ -24,4 +24,4 @@ void foo()
}
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail { ! vect_cond_mixed } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bswap32.c b/gcc/testsuite/gcc.dg/vect/vect-bswap32.c
index 17132baf57b..7f3a915ee97 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-bswap32.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-bswap32.c
@@ -1,4 +1,4 @@
-/* { dg-require-effective-target vect_bswap } */
+/* { dg-additional-options "-msse4" { target sse4_runtime } } */
#include "tree-vect.h"
@@ -42,4 +42,4 @@ main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_bswap || sse4_runtime } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-bswap64.c b/gcc/testsuite/gcc.dg/vect/vect-bswap64.c
index 745a7e73265..b9e421d1de4 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-bswap64.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-bswap64.c
@@ -1,4 +1,4 @@
-/* { dg-require-effective-target vect_bswap } */
+/* { dg-additional-options "-msse4" { target sse4_runtime } } */
#include "tree-vect.h"
@@ -42,4 +42,4 @@ main (void)
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { vect_bswap || sse4_runtime } } } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-cond-2.c b/gcc/testsuite/gcc.dg/vect/vect-cond-2.c
index 9a628567214..d7da8034f0c 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-cond-2.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-cond-2.c
@@ -39,8 +39,6 @@ int main (void)
return 0;
}
-/* The order of computation should not be changed for cond_expr, therefore,
- it cannot be vectorized in reduction. */
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { xfail *-*-* } } } */
+/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-nb-iter-ub-2.c b/gcc/testsuite/gcc.dg/vect/vect-nb-iter-ub-2.c
index bc07b4bea0f..4e13702621f 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-nb-iter-ub-2.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-nb-iter-ub-2.c
@@ -3,7 +3,7 @@
#include "tree-vect.h"
int ii[32];
-char cc[66] =
+char cc[66] __attribute__((aligned(1))) =
{ 0, 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0, 9, 0,
10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0, 17, 0, 18, 0, 19, 0,
20, 0, 21, 0, 22, 0, 23, 0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0,
diff --git a/gcc/testsuite/gcc.dg/visibility-14.c b/gcc/testsuite/gcc.dg/visibility-14.c
index 1c01f8399db..e1d85f0ed25 100644
--- a/gcc/testsuite/gcc.dg/visibility-14.c
+++ b/gcc/testsuite/gcc.dg/visibility-14.c
@@ -2,7 +2,7 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
/* { dg-require-visibility "" } */
-/* { dg-final { scan-hidden "foo" } } */
+/* { dg-final { scan-hidden "foo" { xfail *-*-aix* } } } */
extern void foo(void) __attribute__ ((visibility ("hidden")));
int f () {
diff --git a/gcc/testsuite/gcc.dg/visibility-15.c b/gcc/testsuite/gcc.dg/visibility-15.c
index 8d331d76cae..4e69fa1db4c 100644
--- a/gcc/testsuite/gcc.dg/visibility-15.c
+++ b/gcc/testsuite/gcc.dg/visibility-15.c
@@ -2,7 +2,7 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
/* { dg-require-visibility "" } */
-/* { dg-final { scan-hidden "foo" } } */
+/* { dg-final { scan-hidden "foo" { xfail *-*-aix* } } } */
extern void foo(void) __attribute__ ((visibility ("hidden")));
typedef void (*foo_t)(void);
diff --git a/gcc/testsuite/gcc.dg/visibility-16.c b/gcc/testsuite/gcc.dg/visibility-16.c
index 52a25cdef81..dcd5448d182 100644
--- a/gcc/testsuite/gcc.dg/visibility-16.c
+++ b/gcc/testsuite/gcc.dg/visibility-16.c
@@ -2,7 +2,7 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
/* { dg-require-visibility "" } */
-/* { dg-final { scan-hidden "foo" } } */
+/* { dg-final { scan-hidden "foo" { xfail *-*-aix* } } } */
extern int foo __attribute__ ((visibility ("hidden")));
int f () {
diff --git a/gcc/testsuite/gcc.dg/visibility-17.c b/gcc/testsuite/gcc.dg/visibility-17.c
index 0ff3e83de4b..dc90d35839f 100644
--- a/gcc/testsuite/gcc.dg/visibility-17.c
+++ b/gcc/testsuite/gcc.dg/visibility-17.c
@@ -2,7 +2,7 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
/* { dg-require-visibility "" } */
-/* { dg-final { scan-hidden "foo" } } */
+/* { dg-final { scan-hidden "foo" { xfail *-*-aix* } } } */
extern int foo __attribute__ ((visibility ("hidden")));
int *f () {
diff --git a/gcc/testsuite/gcc.dg/visibility-18.c b/gcc/testsuite/gcc.dg/visibility-18.c
index f54c73b198a..653e3b1971f 100644
--- a/gcc/testsuite/gcc.dg/visibility-18.c
+++ b/gcc/testsuite/gcc.dg/visibility-18.c
@@ -2,7 +2,7 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
/* { dg-require-visibility "" } */
-/* { dg-final { scan-hidden "foo" } } */
+/* { dg-final { scan-hidden "foo" { xfail *-*-aix* } } } */
extern int foo __attribute__ ((visibility ("hidden")));
int *test = &foo;
diff --git a/gcc/testsuite/gcc.dg/visibility-19.c b/gcc/testsuite/gcc.dg/visibility-19.c
index 3c2455fb291..2b0b9beb401 100644
--- a/gcc/testsuite/gcc.dg/visibility-19.c
+++ b/gcc/testsuite/gcc.dg/visibility-19.c
@@ -2,7 +2,7 @@
/* { dg-do compile } */
/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */
/* { dg-require-visibility "" } */
-/* { dg-final { scan-hidden "foo" } } */
+/* { dg-final { scan-hidden "foo" { xfail *-*-aix* } } } */
extern void foo(void) __attribute__ ((visibility ("hidden")));
typedef void (*foo_t)(void);
diff --git a/gcc/testsuite/gcc.target/arm/simd/vmaxnm_f32_1.c b/gcc/testsuite/gcc.target/arm/simd/vmaxnm_f32_1.c
new file mode 100644
index 00000000000..79a3b970398
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vmaxnm_f32_1.c
@@ -0,0 +1,159 @@
+/* Test the `vmaxnmf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_v8_neon_hw } */
+/* { dg-options "-save-temps -O3 -march=armv8-a" } */
+/* { dg-add-options arm_v8_neon } */
+
+#include "arm_neon.h"
+
+extern void abort ();
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__regular_input1 ()
+{
+ float32_t a1[] = {1,2};
+ float32_t b1[] = {3,4};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != b1[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__regular_input2 ()
+{
+ float32_t a1[] = {3,2};
+ float32_t b1[] = {1,4};
+ float32_t e[] = {3,4};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__quiet_NaN_one_arg ()
+{
+ /* When given a quiet NaN, vmaxnm returns the other operand.
+ In this test case we have NaNs in only one operand. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {1,2};
+ float32_t b1[] = {n,n};
+ float32_t e[] = {1,2};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__quiet_NaN_both_args ()
+{
+ /* When given a quiet NaN, vmaxnm returns the other operand.
+ In this test case we have NaNs in both operands. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,2};
+ float32_t b1[] = {1,n};
+ float32_t e[] = {1,2};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__zero_both_args ()
+{
+ /* For 0 and -0, vmaxnm returns 0. Since 0 == -0, check sign bit. */
+ float32_t a1[] = {0.0, 0.0};
+ float32_t b1[] = {-0.0, -0.0};
+ float32_t e[] = {0.0, 0.0};
+
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+
+ float32_t actual1[2];
+ vst1_f32 (actual1, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual1[i] != e[i] || __builtin_signbit (actual1[i]) != 0)
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__inf_both_args ()
+{
+ /* The max of inf and inf is inf. The max of -inf and -inf is -inf. */
+ float32_t inf = __builtin_huge_valf ();
+ float32_t a1[] = {inf, -inf};
+ float32_t b1[] = {inf, -inf};
+ float32_t e[] = {inf, -inf};
+
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+
+ float32_t actual1[2];
+ vst1_f32 (actual1, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual1[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnm_f32__two_quiet_NaNs_both_args ()
+{
+ /* When given 2 NaNs, return a NaN. Since a NaN is not equal to anything,
+ not even another NaN, use __builtin_isnan () to check. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,n};
+ float32_t b1[] = {n,n};
+ float32_t e[] = {n,n};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vmaxnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (!__builtin_isnan (actual[i]))
+ abort ();
+}
+
+int
+main ()
+{
+ test_vmaxnm_f32__regular_input1 ();
+ test_vmaxnm_f32__regular_input2 ();
+ test_vmaxnm_f32__quiet_NaN_one_arg ();
+ test_vmaxnm_f32__quiet_NaN_both_args ();
+ test_vmaxnm_f32__zero_both_args ();
+ test_vmaxnm_f32__inf_both_args ();
+ test_vmaxnm_f32__two_quiet_NaNs_both_args ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "vmaxnm\.f32\t\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+\n" 7 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vmaxnmq_f32_1.c b/gcc/testsuite/gcc.target/arm/simd/vmaxnmq_f32_1.c
new file mode 100644
index 00000000000..07ea7098c52
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vmaxnmq_f32_1.c
@@ -0,0 +1,160 @@
+/* Test the `vmaxnmqf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_v8_neon_hw } */
+/* { dg-options "-save-temps -O3 -march=armv8-a" } */
+/* { dg-add-options arm_v8_neon } */
+
+#include "arm_neon.h"
+
+extern void abort ();
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__regular_input1 ()
+{
+ float32_t a1[] = {1,2,5,6};
+ float32_t b1[] = {3,4,7,8};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != b1[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__regular_input2 ()
+{
+ float32_t a1[] = {3,2,7,6};
+ float32_t b1[] = {1,4,5,8};
+ float32_t e[] = {3,4,7,8};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__quiet_NaN_one_arg ()
+{
+ /* When given a quiet NaN, vmaxnmq returns the other operand.
+ In this test case we have NaNs in only one operand. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {1,2,3,4};
+ float32_t b1[] = {n,n,n,n};
+ float32_t e[] = {1,2,3,4};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__quiet_NaN_both_args ()
+{
+ /* When given a quiet NaN, vmaxnmq returns the other operand.
+ In this test case we have NaNs in both operands. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,2,n,4};
+ float32_t b1[] = {1,n,3,n};
+ float32_t e[] = {1,2,3,4};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__zero_both_args ()
+{
+ /* For 0 and -0, vmaxnmq returns 0. Since 0 == -0, check sign bit. */
+ float32_t a1[] = {0.0, 0.0, -0.0, -0.0};
+ float32_t b1[] = {-0.0, -0.0, 0.0, 0.0};
+ float32_t e[] = {0.0, 0.0, 0.0, 0.0};
+
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+
+ float32_t actual1[4];
+ vst1q_f32 (actual1, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual1[i] != e[i] || __builtin_signbit (actual1[i]) != 0)
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__inf_both_args ()
+{
+ /* The max of inf and inf is inf. The max of -inf and -inf is -inf. */
+ float32_t inf = __builtin_huge_valf ();
+ float32_t a1[] = {inf, -inf, inf, inf};
+ float32_t b1[] = {inf, -inf, -inf, -inf};
+ float32_t e[] = {inf, -inf, inf, inf};
+
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+
+ float32_t actual1[4];
+ vst1q_f32 (actual1, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual1[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vmaxnmq_f32__two_quiet_NaNs_both_args ()
+{
+ /* When given 2 NaNs, return a NaN. Since a NaN is not equal to anything,
+ not even another NaN, use __builtin_isnan () to check. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,n,n,n};
+ float32_t b1[] = {n,n,n,n};
+ float32_t e[] = {n,n};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vmaxnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (!__builtin_isnan (actual[i]))
+ abort ();
+}
+
+int
+main ()
+{
+ test_vmaxnmq_f32__regular_input1 ();
+ test_vmaxnmq_f32__regular_input2 ();
+ test_vmaxnmq_f32__quiet_NaN_one_arg ();
+ test_vmaxnmq_f32__quiet_NaN_both_args ();
+ test_vmaxnmq_f32__zero_both_args ();
+ test_vmaxnmq_f32__inf_both_args ();
+ test_vmaxnmq_f32__two_quiet_NaNs_both_args ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "vmaxnm\.f32\t\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+\n" 7 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vminnm_f32_1.c b/gcc/testsuite/gcc.target/arm/simd/vminnm_f32_1.c
new file mode 100644
index 00000000000..7ebed5d228d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vminnm_f32_1.c
@@ -0,0 +1,159 @@
+/* Test the `vminnmf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_v8_neon_hw } */
+/* { dg-options "-save-temps -O3 -march=armv8-a" } */
+/* { dg-add-options arm_v8_neon } */
+
+#include "arm_neon.h"
+
+extern void abort ();
+
+void __attribute__ ((noinline))
+test_vminnm_f32__regular_input1 ()
+{
+ float32_t a1[] = {1,2};
+ float32_t b1[] = {3,4};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != a1[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__regular_input2 ()
+{
+ float32_t a1[] = {3,2};
+ float32_t b1[] = {1,4};
+ float32_t e[] = {1,2};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__quiet_NaN_one_arg ()
+{
+ /* When given a quiet NaN, vminnm returns the other operand.
+ In this test case we have NaNs in only one operand. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {1,2};
+ float32_t b1[] = {n,n};
+ float32_t e[] = {1,2};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__quiet_NaN_both_args ()
+{
+ /* When given a quiet NaN, vminnm returns the other operand.
+ In this test case we have NaNs in both operands. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,2};
+ float32_t b1[] = {1,n};
+ float32_t e[] = {1,2};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__zero_both_args ()
+{
+ /* For 0 and -0, vminnm returns -0. Since 0 == -0, check sign bit. */
+ float32_t a1[] = {0.0,0.0};
+ float32_t b1[] = {-0.0, -0.0};
+ float32_t e[] = {-0.0, -0.0};
+
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+
+ float32_t actual1[2];
+ vst1_f32 (actual1, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual1[i] != e[i] || __builtin_signbit (actual1[i]) == 0)
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__inf_both_args ()
+{
+ /* The min of inf and inf is inf. The min of -inf and -inf is -inf. */
+ float32_t inf = __builtin_huge_valf ();
+ float32_t a1[] = {inf, -inf};
+ float32_t b1[] = {inf, -inf};
+ float32_t e[] = {inf, -inf};
+
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+
+ float32_t actual1[2];
+ vst1_f32 (actual1, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (actual1[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnm_f32__two_quiet_NaNs_both_args ()
+{
+ /* When given 2 NaNs, return a NaN. Since a NaN is not equal to anything,
+ not even another NaN, use __builtin_isnan () to check. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,n};
+ float32_t b1[] = {n,n};
+ float32_t e[] = {n,n};
+ float32x2_t a = vld1_f32 (a1);
+ float32x2_t b = vld1_f32 (b1);
+ float32x2_t c = vminnm_f32 (a, b);
+ float32_t actual[2];
+ vst1_f32 (actual, c);
+
+ for (int i = 0; i < 2; ++i)
+ if (!__builtin_isnan (actual[i]))
+ abort ();
+}
+
+int
+main ()
+{
+ test_vminnm_f32__regular_input1 ();
+ test_vminnm_f32__regular_input2 ();
+ test_vminnm_f32__quiet_NaN_one_arg ();
+ test_vminnm_f32__quiet_NaN_both_args ();
+ test_vminnm_f32__zero_both_args ();
+ test_vminnm_f32__inf_both_args ();
+ test_vminnm_f32__two_quiet_NaNs_both_args ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "vminnm\.f32\t\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+, ?\[dD\]\[0-9\]+\n" 7 } } */
diff --git a/gcc/testsuite/gcc.target/arm/simd/vminnmq_f32_1.c b/gcc/testsuite/gcc.target/arm/simd/vminnmq_f32_1.c
new file mode 100644
index 00000000000..892fb7a0aa0
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/simd/vminnmq_f32_1.c
@@ -0,0 +1,159 @@
+/* Test the `vminnmqf32' ARM Neon intrinsic. */
+
+/* { dg-do run } */
+/* { dg-require-effective-target arm_v8_neon_hw } */
+/* { dg-options "-save-temps -O3 -march=armv8-a" } */
+/* { dg-add-options arm_v8_neon } */
+
+#include "arm_neon.h"
+
+extern void abort ();
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__regular_input1 ()
+{
+ float32_t a1[] = {1,2,5,6};
+ float32_t b1[] = {3,4,7,8};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != a1[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__regular_input2 ()
+{
+ float32_t a1[] = {3,2,7,6};
+ float32_t b1[] = {1,4,5,8};
+ float32_t e[] = {1,2,5,6};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__quiet_NaN_one_arg ()
+{
+ /* When given a quiet NaN, vminnmq returns the other operand.
+ In this test case we have NaNs in only one operand. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {1,2,3,4};
+ float32_t b1[] = {n,n,n,n};
+ float32_t e[] = {1,2,3,4};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__quiet_NaN_both_args ()
+{
+ /* When given a quiet NaN, vminnmq returns the other operand.
+ In this test case we have NaNs in both operands. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,2,n,4};
+ float32_t b1[] = {1,n,3,n};
+ float32_t e[] = {1,2,3,4};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__zero_both_args ()
+{
+ /* For 0 and -0, vminnmq returns -0. Since 0 == -0, check sign bit. */
+ float32_t a1[] = {0.0, 0.0, -0.0, -0.0};
+ float32_t b1[] = {-0.0, -0.0, 0.0, 0.0};
+ float32_t e[] = {-0.0, -0.0, -0.0, -0.0};
+
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+
+ float32_t actual1[4];
+ vst1q_f32 (actual1, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual1[i] != e[i] || __builtin_signbit (actual1[i]) == 0)
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__inf_both_args ()
+{
+ /* The min of inf and inf is inf. The min of -inf and -inf is -inf. */
+ float32_t inf = __builtin_huge_valf ();
+ float32_t a1[] = {inf, -inf, inf, inf};
+ float32_t b1[] = {inf, -inf, -inf, -inf};
+ float32_t e[] = {inf, -inf, -inf, -inf};
+
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+
+ float32_t actual1[4];
+ vst1q_f32 (actual1, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (actual1[i] != e[i])
+ abort ();
+}
+
+void __attribute__ ((noinline))
+test_vminnmq_f32__two_quiet_NaNs_both_args ()
+{
+ /* When given 2 NaNs, return a NaN. Since a NaN is not equal to anything,
+ not even another NaN, use __builtin_isnan () to check. */
+ float32_t n = __builtin_nanf ("");
+ float32_t a1[] = {n,n,n,n};
+ float32_t b1[] = {n,n,n,n};
+ float32_t e[] = {n,n};
+ float32x4_t a = vld1q_f32 (a1);
+ float32x4_t b = vld1q_f32 (b1);
+ float32x4_t c = vminnmq_f32 (a, b);
+ float32_t actual[4];
+ vst1q_f32 (actual, c);
+
+ for (int i = 0; i < 4; ++i)
+ if (!__builtin_isnan (actual[i]))
+ abort ();
+}
+
+int
+main ()
+{
+ test_vminnmq_f32__regular_input1 ();
+ test_vminnmq_f32__regular_input2 ();
+ test_vminnmq_f32__quiet_NaN_one_arg ();
+ test_vminnmq_f32__quiet_NaN_both_args ();
+ test_vminnmq_f32__zero_both_args ();
+ test_vminnmq_f32__inf_both_args ();
+ test_vminnmq_f32__two_quiet_NaNs_both_args ();
+ return 0;
+}
+
+/* { dg-final { scan-assembler-times "vminnm\.f32\t\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+, ?\[qQ\]\[0-9\]+\n" 7 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr70799-2.c b/gcc/testsuite/gcc.target/i386/pr70799-2.c
new file mode 100644
index 00000000000..47810511f97
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr70799-2.c
@@ -0,0 +1,17 @@
+/* PR target/pr70799 */
+/* { dg-do compile { target { ia32 } } } */
+/* { dg-options "-O2 -march=slm -mno-stackrealign" } */
+/* { dg-final { scan-assembler "psllq" } } */
+/* { dg-final { scan-assembler "psrlq" } } */
+
+unsigned long long a, b;
+
+void test1 (void)
+{
+ a = b << 21;
+}
+
+void test2 (void)
+{
+ a = b >> 21;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr71529.C b/gcc/testsuite/gcc.target/i386/pr71529.C
deleted file mode 100644
index 3169101e1a7..00000000000
--- a/gcc/testsuite/gcc.target/i386/pr71529.C
+++ /dev/null
@@ -1,22 +0,0 @@
-/* PR71529 */
-/* { dg-do compile { target { ! x32 } } } */
-/* { dg-options "-fcheck-pointer-bounds -mmpx -O2" } */
-
-class c1
-{
- public:
- virtual ~c1 ();
-};
-
-class c2
-{
- public:
- virtual ~c2 ();
-};
-
-class c3 : c1, c2 { };
-
-int main (int, char **)
-{
- c3 obj;
-}
diff --git a/gcc/testsuite/gcc.target/i386/pr78035.c b/gcc/testsuite/gcc.target/i386/pr78035.c
new file mode 100644
index 00000000000..2e673a8ce2d
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78035.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+extern int a;
+extern int b;
+extern int c;
+
+int foo(int choose_a)
+{
+ int *p;
+ if (choose_a)
+ p = &a;
+ else
+ p = &b;
+ return p != &c;
+}
+
+int bar ()
+{
+ return &a != &c;
+}
+
+/* We should not optimize away either comparison. */
+/* { dg-final { scan-assembler-times "cmp" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/pr78227-1.c b/gcc/testsuite/gcc.target/i386/pr78227-1.c
new file mode 100644
index 00000000000..9dc97dd738f
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78227-1.c
@@ -0,0 +1,30 @@
+/* PR target/78227 */
+/* { dg-do compile } */
+/* { dg-options "-mavx512f -O0 -Wno-psabi" } */
+
+typedef int V __attribute__((vector_size (64)));
+typedef long long int W __attribute__((vector_size (64)));
+
+V
+foo1 (V v)
+{
+ return v > 0;
+}
+
+V
+bar1 (V v)
+{
+ return v != 0;
+}
+
+W
+foo2 (W w)
+{
+ return w > 0;
+}
+
+W
+bar2 (W w)
+{
+ return w != 0;
+}
diff --git a/gcc/testsuite/gcc.target/i386/pr78227-2.c b/gcc/testsuite/gcc.target/i386/pr78227-2.c
new file mode 100644
index 00000000000..c557c8f12b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr78227-2.c
@@ -0,0 +1,30 @@
+/* PR target/78227 */
+/* { dg-do compile } */
+/* { dg-options "-mavx512bw -O0 -Wno-psabi" } */
+
+typedef signed char V __attribute__((vector_size (64)));
+typedef short int W __attribute__((vector_size (64)));
+
+V
+foo1 (V v)
+{
+ return v > 0;
+}
+
+V
+bar1 (V v)
+{
+ return v != 0;
+}
+
+W
+foo2 (W w)
+{
+ return w > 0;
+}
+
+W
+bar2 (W w)
+{
+ return w != 0;
+}
diff --git a/gcc/testsuite/gcc.target/mips/mips.exp b/gcc/testsuite/gcc.target/mips/mips.exp
index 7c241400b73..39f44ffc9d6 100644
--- a/gcc/testsuite/gcc.target/mips/mips.exp
+++ b/gcc/testsuite/gcc.target/mips/mips.exp
@@ -1176,7 +1176,8 @@ proc mips-dg-options { args } {
|| [mips_have_test_option_p options "-mpaired-single"]
|| [mips_have_test_option_p options "-mnan=legacy"]
|| [mips_have_test_option_p options "-mabs=legacy"]
- || [mips_have_test_option_p options "!HAS_LSA"]) } {
+ || [mips_have_test_option_p options "!HAS_LSA"]
+ || [mips_have_test_option_p options "-mbranch-likely"]) } {
if { $gp_size == 32 } {
mips_make_test_option options "-mips32r5"
} else {
@@ -1345,6 +1346,7 @@ proc mips-dg-options { args } {
mips_make_test_option options "-mno-paired-single"
mips_make_test_option options "-mnan=2008"
mips_make_test_option options "-mabs=2008"
+ mips_make_test_option options "-mno-branch-likely"
}
if { [regexp {^-march=(octeon|loongson)} $arch] } {
mips_make_test_option options "-mno-micromips"
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-add-1.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-1.c
new file mode 100644
index 00000000000..4ffdb81e709
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-1.c
@@ -0,0 +1,46 @@
+/* Verify that overloaded built-ins for vec_add with char
+ inputs produce the right results. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec" } */
+
+#include <altivec.h>
+
+vector signed char
+test1 (vector bool char x, vector signed char y)
+{
+ return vec_add (x, y);
+}
+
+vector signed char
+test2 (vector signed char x, vector bool char y)
+{
+ return vec_add (x, y);
+}
+
+vector signed char
+test3 (vector signed char x, vector signed char y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned char
+test4 (vector bool char x, vector unsigned char y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned char
+test5 (vector unsigned char x, vector bool char y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned char
+test6 (vector unsigned char x, vector unsigned char y)
+{
+ return vec_add (x, y);
+}
+
+/* { dg-final { scan-assembler-times "vaddubm" 6 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-add-2.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-2.c
new file mode 100644
index 00000000000..c3b5e1d4aec
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-2.c
@@ -0,0 +1,46 @@
+/* Verify that overloaded built-ins for vec_add with short
+ inputs produce the right results. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec" } */
+
+#include <altivec.h>
+
+vector signed short
+test1 (vector bool short x, vector signed short y)
+{
+ return vec_add (x, y);
+}
+
+vector signed short
+test2 (vector signed short x, vector bool short y)
+{
+ return vec_add (x, y);
+}
+
+vector signed short
+test3 (vector signed short x, vector signed short y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned short
+test4 (vector bool short x, vector unsigned short y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned short
+test5 (vector unsigned short x, vector bool short y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned short
+test6 (vector unsigned short x, vector unsigned short y)
+{
+ return vec_add (x, y);
+}
+
+/* { dg-final { scan-assembler-times "vadduhm" 6 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-add-3.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-3.c
new file mode 100644
index 00000000000..bb7e644caad
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-3.c
@@ -0,0 +1,46 @@
+/* Verify that overloaded built-ins for vec_add with int
+ inputs produce the right results. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec" } */
+
+#include <altivec.h>
+
+vector signed int
+test1 (vector bool int x, vector signed int y)
+{
+ return vec_add (x, y);
+}
+
+vector signed int
+test2 (vector signed int x, vector bool int y)
+{
+ return vec_add (x, y);
+}
+
+vector signed int
+test3 (vector signed int x, vector signed int y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned int
+test4 (vector bool int x, vector unsigned int y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned int
+test5 (vector unsigned int x, vector bool int y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned int
+test6 (vector unsigned int x, vector unsigned int y)
+{
+ return vec_add (x, y);
+}
+
+/* { dg-final { scan-assembler-times "vadduwm" 6 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-add-4.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-4.c
new file mode 100644
index 00000000000..389a20ccfd2
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-4.c
@@ -0,0 +1,46 @@
+/* Verify that overloaded built-ins for vec_add with long long
+ inputs produce the right results. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-maltivec -mvsx -mpower8-vector" } */
+
+#include <altivec.h>
+
+vector signed long long
+test1 (vector bool long long x, vector signed long long y)
+{
+ return vec_add (x, y);
+}
+
+vector signed long long
+test2 (vector signed long long x, vector bool long long y)
+{
+ return vec_add (x, y);
+}
+
+vector signed long long
+test3 (vector signed long long x, vector signed long long y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned long long
+test4 (vector bool long long x, vector unsigned long long y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned long long
+test5 (vector unsigned long long x, vector bool long long y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned long long
+test6 (vector unsigned long long x, vector unsigned long long y)
+{
+ return vec_add (x, y);
+}
+
+/* { dg-final { scan-assembler-times "vaddudm" 6 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-add-5.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-5.c
new file mode 100644
index 00000000000..cc1d8c443a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-5.c
@@ -0,0 +1,16 @@
+/* Verify that overloaded built-ins for vec_add with float
+ inputs produce the right results. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec -mno-vsx" } */
+
+#include <altivec.h>
+
+vector float
+test1 (vector float x, vector float y)
+{
+ return vec_add (x, y);
+}
+
+/* { dg-final { scan-assembler-times "vaddfp" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-add-6.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-6.c
new file mode 100644
index 00000000000..559b3e15a4a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-6.c
@@ -0,0 +1,23 @@
+/* Verify that overloaded built-ins for vec_add with float and
+ double inputs for VSX produce the right results. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_vsx_ok } */
+/* { dg-options "-maltivec -mvsx" } */
+
+#include <altivec.h>
+
+vector float
+test1 (vector float x, vector float y)
+{
+ return vec_add (x, y);
+}
+
+vector double
+test2 (vector double x, vector double y)
+{
+ return vec_add (x, y);
+}
+
+/* { dg-final { scan-assembler-times "xvaddsp" 1 } } */
+/* { dg-final { scan-assembler-times "xvadddp" 1 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/fold-vec-add-7.c b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-7.c
new file mode 100644
index 00000000000..185a90340c6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/fold-vec-add-7.c
@@ -0,0 +1,23 @@
+/* Verify that overloaded built-ins for vec_add with __int128
+ inputs produce the right results. */
+
+/* { dg-do compile } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-options "-maltivec -mvsx -mpower8-vector" } */
+/* { dg-additional-options "-maix64" { target powerpc-ibm-aix* } } */
+
+#include "altivec.h"
+
+vector signed __int128
+test1 (vector signed __int128 x, vector signed __int128 y)
+{
+ return vec_add (x, y);
+}
+
+vector unsigned __int128
+test2 (vector unsigned __int128 x, vector unsigned __int128 y)
+{
+ return vec_add (x, y);
+}
+
+/* { dg-final { scan-assembler-times "vadduqm" 2 } } */
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-extract-4.c b/gcc/testsuite/gcc.target/powerpc/vsx-extract-4.c
new file mode 100644
index 00000000000..3b498f4bc2a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-extract-4.c
@@ -0,0 +1,76 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-O2 -mcpu=power8" } */
+
+/* { dg-final { scan-assembler-times "vspltw" 6 } } */
+/* { dg-final { scan-assembler-times "xvcvsxwdp" 4 } } */
+/* { dg-final { scan-assembler-times "xvcvuxwdp" 4 } } */
+/* { dg-final { scan-assembler-not "mtvsrd" } } */
+/* { dg-final { scan-assembler-not "mtvsrwa" } } */
+/* { dg-final { scan-assembler-not "mtvsrwz" } } */
+/* { dg-final { scan-assembler-not "mfvsrd" } } */
+/* { dg-final { scan-assembler-not "mfvsrwz" } } */
+
+#include <altivec.h>
+
+#ifndef TYPE
+#define TYPE double
+#endif
+
+TYPE
+foo_0s (vector int v)
+{
+ int i = vec_extract (v, 0);
+ return (TYPE) i;
+}
+
+TYPE
+foo_1s (vector int v)
+{
+ int i = vec_extract (v, 1);
+ return (TYPE) i;
+}
+
+TYPE
+foo_2s (vector int v)
+{
+ int i = vec_extract (v, 2);
+ return (TYPE) i;
+}
+
+TYPE
+foo_3s (vector int v)
+{
+ int i = vec_extract (v, 3);
+ return (TYPE) i;
+}
+
+TYPE
+foo_0u (vector unsigned int v)
+{
+ unsigned int u = vec_extract (v, 0);
+ return (TYPE) u;
+}
+
+TYPE
+foo_1u (vector unsigned int v)
+{
+ unsigned int u = vec_extract (v, 1);
+ return (TYPE) u;
+}
+
+TYPE
+foo_2u (vector unsigned int v)
+{
+ unsigned int u = vec_extract (v, 2);
+ return (TYPE) u;
+}
+
+TYPE
+foo_3u (vector unsigned int v)
+{
+ unsigned int u = vec_extract (v, 3);
+ return (TYPE) u;
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/vsx-extract-5.c b/gcc/testsuite/gcc.target/powerpc/vsx-extract-5.c
new file mode 100644
index 00000000000..1338c6b1de5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/vsx-extract-5.c
@@ -0,0 +1,77 @@
+/* { dg-do compile { target { powerpc*-*-* && lp64 } } } */
+/* { dg-skip-if "" { powerpc*-*-darwin* } { "*" } { "" } } */
+/* { dg-require-effective-target powerpc_p8vector_ok } */
+/* { dg-skip-if "do not override -mcpu" { powerpc*-*-* } { "-mcpu=*" } { "-mcpu=power8" } } */
+/* { dg-options "-O2 -mcpu=power8" } */
+
+/* { dg-final { scan-assembler-times "vspltw" 6 } } */
+/* { dg-final { scan-assembler-times "xvcvsxwdp" 4 } } */
+/* { dg-final { scan-assembler-times "xvcvuxwdp" 4 } } */
+/* { dg-final { scan-assembler-times "frsp\|xsrsp" 8 } } */
+/* { dg-final { scan-assembler-not "mtvsrd" } } */
+/* { dg-final { scan-assembler-not "mtvsrwa" } } */
+/* { dg-final { scan-assembler-not "mtvsrwz" } } */
+/* { dg-final { scan-assembler-not "mfvsrd" } } */
+/* { dg-final { scan-assembler-not "mfvsrwz" } } */
+
+#include <altivec.h>
+
+#ifndef TYPE
+#define TYPE float
+#endif
+
+TYPE
+foo_0s (vector int v)
+{
+ int i = vec_extract (v, 0);
+ return (TYPE) i;
+}
+
+TYPE
+foo_1s (vector int v)
+{
+ int i = vec_extract (v, 1);
+ return (TYPE) i;
+}
+
+TYPE
+foo_2s (vector int v)
+{
+ int i = vec_extract (v, 2);
+ return (TYPE) i;
+}
+
+TYPE
+foo_3s (vector int v)
+{
+ int i = vec_extract (v, 3);
+ return (TYPE) i;
+}
+
+TYPE
+foo_0u (vector unsigned int v)
+{
+ unsigned int u = vec_extract (v, 0);
+ return (TYPE) u;
+}
+
+TYPE
+foo_1u (vector unsigned int v)
+{
+ unsigned int u = vec_extract (v, 1);
+ return (TYPE) u;
+}
+
+TYPE
+foo_2u (vector unsigned int v)
+{
+ unsigned int u = vec_extract (v, 2);
+ return (TYPE) u;
+}
+
+TYPE
+foo_3u (vector unsigned int v)
+{
+ unsigned int u = vec_extract (v, 3);
+ return (TYPE) u;
+}
diff --git a/gcc/testsuite/gcc.target/sparc/overflow-3.c b/gcc/testsuite/gcc.target/sparc/overflow-3.c
index 31b326486ee..8cb24f52f7b 100644
--- a/gcc/testsuite/gcc.target/sparc/overflow-3.c
+++ b/gcc/testsuite/gcc.target/sparc/overflow-3.c
@@ -5,40 +5,39 @@
#include <stdbool.h>
#include <stdint.h>
-bool my_uadd_overflow (uint64_t a, uint64_t b, uint64_t *res)
+bool my_uadd_overflow (uint32_t a, uint32_t b, uint32_t *res)
{
return __builtin_add_overflow (a, b, res);
}
-bool my_usub_overflow (uint64_t a, uint64_t b, uint64_t *res)
+bool my_usub_overflow (uint32_t a, uint32_t b, uint32_t *res)
{
return __builtin_sub_overflow (a, b, res);
}
-bool my_uneg_overflow (uint64_t a, uint64_t *res)
+bool my_uneg_overflow (uint32_t a, uint32_t *res)
{
return __builtin_sub_overflow (0, a, res);
}
-bool my_add_overflow (int64_t a, int64_t b, int64_t *res)
+bool my_add_overflow (int32_t a, int32_t b, int32_t *res)
{
return __builtin_add_overflow (a, b, res);
}
-bool my_sub_overflow (int64_t a, int64_t b, int64_t *res)
+bool my_sub_overflow (int32_t a, int32_t b, int32_t *res)
{
return __builtin_sub_overflow (a, b, res);
}
-bool my_neg_overflow (int64_t a, int64_t *res)
+bool my_neg_overflow (int32_t a, int32_t *res)
{
return __builtin_sub_overflow (0, a, res);
}
/* { dg-final { scan-assembler-times "addcc\t%" 2 } } */
/* { dg-final { scan-assembler-times "subcc\t%" 4 } } */
-/* { dg-final { scan-assembler-times "movlu\t%" 1 } } */
-/* { dg-final { scan-assembler-times "blu" 2 } } */
+/* { dg-final { scan-assembler-times "addx\t%" 3 } } */
/* { dg-final { scan-assembler-times "bvs" 3 } } */
/* { dg-final { scan-assembler-not "cmp\t%" } } */
/* { dg-final { scan-assembler-not "save\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/overflow-4.c b/gcc/testsuite/gcc.target/sparc/overflow-4.c
new file mode 100644
index 00000000000..31b326486ee
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/overflow-4.c
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+bool my_uadd_overflow (uint64_t a, uint64_t b, uint64_t *res)
+{
+ return __builtin_add_overflow (a, b, res);
+}
+
+bool my_usub_overflow (uint64_t a, uint64_t b, uint64_t *res)
+{
+ return __builtin_sub_overflow (a, b, res);
+}
+
+bool my_uneg_overflow (uint64_t a, uint64_t *res)
+{
+ return __builtin_sub_overflow (0, a, res);
+}
+
+bool my_add_overflow (int64_t a, int64_t b, int64_t *res)
+{
+ return __builtin_add_overflow (a, b, res);
+}
+
+bool my_sub_overflow (int64_t a, int64_t b, int64_t *res)
+{
+ return __builtin_sub_overflow (a, b, res);
+}
+
+bool my_neg_overflow (int64_t a, int64_t *res)
+{
+ return __builtin_sub_overflow (0, a, res);
+}
+
+/* { dg-final { scan-assembler-times "addcc\t%" 2 } } */
+/* { dg-final { scan-assembler-times "subcc\t%" 4 } } */
+/* { dg-final { scan-assembler-times "movlu\t%" 1 } } */
+/* { dg-final { scan-assembler-times "blu" 2 } } */
+/* { dg-final { scan-assembler-times "bvs" 3 } } */
+/* { dg-final { scan-assembler-not "cmp\t%" } } */
+/* { dg-final { scan-assembler-not "save\t%" } } */
diff --git a/gcc/testsuite/gcc.target/sparc/overflow-5.c b/gcc/testsuite/gcc.target/sparc/overflow-5.c
new file mode 100644
index 00000000000..501ce04f7a1
--- /dev/null
+++ b/gcc/testsuite/gcc.target/sparc/overflow-5.c
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-options "-O -mvis3" } */
+/* { dg-require-effective-target lp64 } */
+
+#include <stdbool.h>
+#include <stdint.h>
+
+bool my_uadd_overflow (uint64_t a, uint64_t b, uint64_t *res)
+{
+ return __builtin_add_overflow (a, b, res);
+}
+
+bool my_usub_overflow (uint64_t a, uint64_t b, uint64_t *res)
+{
+ return __builtin_sub_overflow (a, b, res);
+}
+
+bool my_uneg_overflow (uint64_t a, uint64_t *res)
+{
+ return __builtin_sub_overflow (0, a, res);
+}
+
+bool my_add_overflow (int64_t a, int64_t b, int64_t *res)
+{
+ return __builtin_add_overflow (a, b, res);
+}
+
+bool my_sub_overflow (int64_t a, int64_t b, int64_t *res)
+{
+ return __builtin_sub_overflow (a, b, res);
+}
+
+bool my_neg_overflow (int64_t a, int64_t *res)
+{
+ return __builtin_sub_overflow (0, a, res);
+}
+
+/* { dg-final { scan-assembler-times "addcc\t%" 2 } } */
+/* { dg-final { scan-assembler-times "subcc\t%" 4 } } */
+/* { dg-final { scan-assembler-times "addxc\t%" 3 } } */
+/* { dg-final { scan-assembler-times "bvs" 3 } } */
+/* { dg-final { scan-assembler-not "cmp\t%" } } */
+/* { dg-final { scan-assembler-not "save\t%" } } */
diff --git a/gcc/testsuite/gfortran.dg/allocate_with_source_14.f03 b/gcc/testsuite/gfortran.dg/allocate_with_source_14.f03
index 36c1245ccdd..fd2db7439fe 100644
--- a/gcc/testsuite/gfortran.dg/allocate_with_source_14.f03
+++ b/gcc/testsuite/gfortran.dg/allocate_with_source_14.f03
@@ -210,5 +210,5 @@ program main
call v%free()
deallocate(av)
end program
-! { dg-final { scan-tree-dump-times "__builtin_malloc" 23 "original" } }
+! { dg-final { scan-tree-dump-times "__builtin_malloc" 22 "original" } }
! { dg-final { scan-tree-dump-times "__builtin_free" 29 "original" } }
diff --git a/gcc/testsuite/gfortran.dg/associate_23.f90 b/gcc/testsuite/gfortran.dg/associate_23.f90
new file mode 100644
index 00000000000..b4d58ffd2b7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/associate_23.f90
@@ -0,0 +1,36 @@
+! { dg-do run }
+!
+! Tests the fix for PR64933
+!
+! Contributed by Olivier Marsden <olivier.marsden@ecmwf.int>
+!
+program test_this
+ implicit none
+ character(len = 15) :: char_var, char_var_dim (3)
+ character(len = 80) :: buffer
+
+! Original failing case reported in PR
+ ASSOCIATE(should_work=>char_var)
+ should_work = "test succesful"
+ write (buffer, *) should_work(5:14)
+ END ASSOCIATE
+
+ if (trim (buffer) .ne. " succesful") call abort
+
+! Found to be failing during debugging
+ ASSOCIATE(should_work=>char_var_dim)
+ should_work = ["test SUCCESFUL", "test_SUCCESFUL", "test.SUCCESFUL"]
+ write (buffer, *) should_work(:)(5:14)
+ END ASSOCIATE
+
+ if (trim (buffer) .ne. " SUCCESFUL_SUCCESFUL.SUCCESFUL") call abort
+
+! Found to be failing during debugging
+ ASSOCIATE(should_work=>char_var_dim(1:2))
+ should_work = ["test SUCCESFUL", "test_SUCCESFUL", "test.SUCCESFUL"]
+ write (buffer, *) should_work(:)(5:14)
+ END ASSOCIATE
+
+ if (trim (buffer) .ne. " SUCCESFUL_SUCCESFUL") call abort
+
+end program
diff --git a/gcc/testsuite/gfortran.dg/class_58.f90 b/gcc/testsuite/gfortran.dg/class_58.f90
new file mode 100644
index 00000000000..20b601a2f51
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_58.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+!
+! PR 68440: [OOP] ICE on declaring class variable with wrong attribute
+!
+! Contributed by Gerhard Steinmetz <gerhard.steinmetz.fortran@t-online.de>
+
+subroutine s
+ type t
+ end type
+ class(t), parameter :: x = t() ! { dg-error "cannot have the PARAMETER attribute" }
+ class(t), parameter :: y = x ! { dg-error "cannot have the PARAMETER attribute" }
+ class(t) :: z = x ! { dg-error "must be dummy, allocatable or pointer" }
+end
diff --git a/gcc/testsuite/gfortran.dg/class_59.f90 b/gcc/testsuite/gfortran.dg/class_59.f90
new file mode 100644
index 00000000000..e077ef8dc30
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/class_59.f90
@@ -0,0 +1,25 @@
+! { dg-do compile }
+!
+! PR 71894: [OOP] ICE in gfc_add_component_ref, at fortran/class.c:227
+!
+! Contributed by Gerhard Steinmetz <gerhard.steinmetz.fortran@t-online.de>
+
+subroutine s1
+ type t
+ integer :: n
+ end type
+ type(t) :: x
+ class(t) :: y ! { dg-error "must be dummy, allocatable or pointer" }
+ x = y
+end
+
+subroutine s2
+ type t
+ end type
+ class(t) :: x ! { dg-error "must be dummy, allocatable or pointer" }
+ class(t), allocatable :: y
+ select type (y)
+ type is (t)
+ y = x
+ end select
+end
diff --git a/gcc/testsuite/gfortran.dg/dec_exp_1.f90 b/gcc/testsuite/gfortran.dg/dec_exp_1.f90
new file mode 100644
index 00000000000..c8b395aa9ce
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_exp_1.f90
@@ -0,0 +1,35 @@
+! { dg-do run }
+! { dg-options "-fdec" }
+!
+! Test support for providing a default exponent of zero when unspecified in
+! real constants with -fdec.
+!
+
+subroutine asserteq (rexp, ract, msg)
+ real, intent(in) :: rexp, ract
+ character(*), intent(in) :: msg
+ if (rexp .ne. ract) then
+ write (*, '(A,F12.6,F12.6)') msg, rexp, ract
+ call abort()
+ endif
+end subroutine
+
+implicit none
+
+real, parameter :: r1 = 8e0
+real, parameter :: r2 = 8e ! { equivalent to 8e0 }
+real, volatile :: r3, r4
+character(2) :: s
+r3 = 8e ! { equivalent to 8e0 }
+s = '8e'
+
+read (s, *) r4
+
+call asserteq (r1, r2, "[const]")
+call asserteq (r1, r3, "[vol. ]")
+call asserteq (r1, r4, "[read ]")
+
+r4 = 8e + 48e
+call asserteq (56e, r4, "[sum ]")
+
+end
diff --git a/gcc/testsuite/gfortran.dg/dec_exp_2.f90 b/gcc/testsuite/gfortran.dg/dec_exp_2.f90
new file mode 100644
index 00000000000..9137aabc4b3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_exp_2.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! { dg-options "" }
+!
+! Make sure we still see an error for missing exponents without -fdec.
+!
+
+implicit none
+
+real, parameter :: r1 = 8e ! { dg-error "Missing exponent" }
+real, volatile :: r2
+r2 = 8e ! { dg-error "Missing exponent" }
+
+end
diff --git a/gcc/testsuite/gfortran.dg/dec_exp_3.f90 b/gcc/testsuite/gfortran.dg/dec_exp_3.f90
new file mode 100644
index 00000000000..34835a77b32
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_exp_3.f90
@@ -0,0 +1,15 @@
+! { dg-do run "xfail *-*-*" }
+! { dg-options "" }
+!
+! Make sure we still see an error for missing exponents without -fdec.
+!
+
+implicit none
+
+real :: r
+character(2) :: s
+s = '8e'
+
+read (s, *) r ! { XFAIL "Bad real number" }
+
+end
diff --git a/gcc/testsuite/gfortran.dg/dec_parameter_1.f b/gcc/testsuite/gfortran.dg/dec_parameter_1.f
new file mode 100644
index 00000000000..69ffa53c806
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_parameter_1.f
@@ -0,0 +1,64 @@
+ ! { dg-do run }
+ ! { dg-options "-ffixed-form -std=legacy" }
+ !
+ ! Test DEC-style PARAMETER statements without parentheses in
+ ! fixed form.
+ !
+
+ subroutine sub1(t, x, y)
+ implicit real(8) (A-H,O-Z)
+ parameter (pi_1 = 3.141592654d0, f_1 = 3.d08)
+ parameter pi_2 = 3.141592654d0, f_2 = 3.d08
+ ! Note that if the parameter statements above are matched
+ ! incorrectly as assignments, the below specification
+ ! statements will be considered out-of-order and we see
+ ! 'unexpected specification statement'. A PARAMETER
+ ! statement should still be a specification statement.
+
+ real(8), intent(in) :: t
+ real(8), intent(out) :: x, y
+
+ real(8), volatile :: two
+ two = 2.0d0
+ x = two * pi_1 * f_1 * t
+ y = two * pi_2 * f_2 * t
+ z = two * pi_3 * f_3 * t
+ return
+ end subroutine
+
+ subroutine sub2(t, x, y, z)
+ implicit none
+ real(8) :: pi_1, pi_2, f_1, f_2
+ parameter (pi_1 = 3.141592654d0, f_1 = 3.d08)
+ parameter pi_2 = 3.141592654d0, f_2 = 3.d08
+ real(8), parameter :: pi_3 = 3.141592654d0, f_3 = 3.d08
+ ! Ditto sub1
+
+ real(8), intent(in) :: t
+ real(8), intent(out) :: x, y, z
+
+ real(8), volatile :: two
+ two = 2.0d0
+ x = two * pi_1 * f_1 * t
+ y = two * pi_2 * f_2 * t
+ z = two * pi_3 * f_3 * t
+ end subroutine
+
+ implicit none
+ real(8) :: x1, x2, y1, y2, z2
+ real(8), volatile :: t
+ t = 1.5e-6
+
+ call sub1(t, x1, y1)
+ call sub2(t, x2, y2, z2)
+
+ write(*,'(4D18.5)') t, x1, y1
+ write(*,'(4D18.5)') t, x2, y2, z2
+
+ if (x1 .ne. x2 .or. y1 .ne. y2
+ & .or. x1 .ne. y1 .or. x2 .ne. y2
+ & .or. y2 .ne. z2) then
+ call abort()
+ endif
+
+ end
diff --git a/gcc/testsuite/gfortran.dg/dec_parameter_2.f90 b/gcc/testsuite/gfortran.dg/dec_parameter_2.f90
new file mode 100644
index 00000000000..280f0007f93
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_parameter_2.f90
@@ -0,0 +1,63 @@
+! { dg-do run }
+! { dg-options "-ffree-form -std=legacy" }
+!
+! Test DEC-style PARAMETER statements without parentheses in free form.
+!
+
+subroutine sub1(t, x, y)
+ implicit real(8) (A-H,O-Z)
+ parameter (pi_1 = 3.141592654d0, f_1 = 3.d08)
+ parameter pi_2 = 3.141592654d0, f_2 = 3.d08 ! legacy PARAMETER
+ ! Note that if the parameter statements above are matched
+ ! incorrectly as assignments, the below specification
+ ! statements will be considered out-of-order and we see
+ ! 'unexpected specification statement'. A PARAMETER
+ ! statement should still be a specification statement.
+
+ real(8), intent(in) :: t
+ real(8), intent(out) :: x, y
+
+ real(8), volatile :: two
+ two = 2.0d0
+ x = two * pi_1 * f_1 * t
+ y = two * pi_2 * f_2 * t
+ z = two * pi_3 * f_3 * t
+ return
+end subroutine
+
+subroutine sub2(t, x, y, z)
+ implicit none
+ real(8) :: pi_1, pi_2, f_1, f_2
+ parameter (pi_1 = 3.141592654d0, f_1 = 3.d08)
+ parameter pi_2 = 3.141592654d0, f_2 = 3.d08 ! legacy PARAMETER
+ real(8), parameter :: pi_3 = 3.141592654d0, f_3 = 3.d08
+ ! Ditto sub1
+
+ real(8), intent(in) :: t
+ real(8), intent(out) :: x, y, z
+
+ real(8), volatile :: two
+ two = 2.0d0
+ x = two * pi_1 * f_1 * t
+ y = two * pi_2 * f_2 * t
+ z = two * pi_3 * f_3 * t
+end subroutine
+
+implicit none
+real(8) :: x1, x2, y1, y2, z2
+real(8), volatile :: t
+t = 1.5e-6
+
+call sub1(t, x1, y1)
+call sub2(t, x2, y2, z2)
+
+write(*,'(4D18.5)') t, x1, y1
+write(*,'(4D18.5)') t, x2, y2, z2
+
+if (x1 .ne. x2 .or. y1 .ne. y2 &
+ .or. x1 .ne. y1 .or. x2 .ne. y2 &
+ .or. y2 .ne. z2) then
+ call abort()
+endif
+
+end
diff --git a/gcc/testsuite/gfortran.dg/dec_parameter_3.f90 b/gcc/testsuite/gfortran.dg/dec_parameter_3.f90
new file mode 100644
index 00000000000..92f0f61bb66
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_parameter_3.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! { dg-options "-ffree-form -std=gnu" }
+!
+! Test warnings for DEC-style PARAMETER statements with std=gnu.
+!
+
+subroutine sub()
+ implicit real(8) (A-Z)
+ parameter pi = 3.1415926535d0 ! { dg-warning "Legacy Extension: PARAMETER" }
+ print *, pi
+end subroutine
+
+end
diff --git a/gcc/testsuite/gfortran.dg/dec_parameter_4.f90 b/gcc/testsuite/gfortran.dg/dec_parameter_4.f90
new file mode 100644
index 00000000000..280d56c424f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/dec_parameter_4.f90
@@ -0,0 +1,13 @@
+! { dg-do compile }
+! { dg-options "-ffree-form -std=f95" }
+!
+! Test errors for DEC-style PARAMETER statements with a real standard.
+!
+
+subroutine sub()
+ implicit real(8) (A-Z)
+ parameter pi = 3.1415926535d0 ! { dg-error "Legacy Extension: PARAMETER" }
+ print *, pi
+end subroutine
+
+end
diff --git a/gcc/testsuite/gfortran.dg/elemental_optional_args_6.f90 b/gcc/testsuite/gfortran.dg/elemental_optional_args_6.f90
index ad1c252fb00..2dece646dde 100644
--- a/gcc/testsuite/gfortran.dg/elemental_optional_args_6.f90
+++ b/gcc/testsuite/gfortran.dg/elemental_optional_args_6.f90
@@ -1,4 +1,5 @@
! { dg-do run }
+! { dg-options "-Wpedantic" }
!
! PR fortran/53692
!
diff --git a/gcc/testsuite/gfortran.dg/fmt_l.f90 b/gcc/testsuite/gfortran.dg/fmt_l.f90
index 9dc4f570473..0fd195515fc 100644
--- a/gcc/testsuite/gfortran.dg/fmt_l.f90
+++ b/gcc/testsuite/gfortran.dg/fmt_l.f90
@@ -52,34 +52,34 @@ program test_l
end program test_l
! { dg-output "At line 14 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 15 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 19 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 20 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 24 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 25 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 29 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 30 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 34 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 35 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 39 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 40 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 44 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 45 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 49 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
! { dg-output "At line 50 of file.*" }
-! { dg-output "Fortran runtime warning: Positive width required in format(\n|\r\n|\r)" }
+! { dg-output "Fortran runtime warning: Positive width required with L descriptor(\n|\r\n|\r)" }
diff --git a/gcc/testsuite/gfortran.dg/fmt_l0.f90 b/gcc/testsuite/gfortran.dg/fmt_l0.f90
new file mode 100644
index 00000000000..fab1ffb1ce9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_l0.f90
@@ -0,0 +1,12 @@
+! { dg-do run }
+! { dg-options "-std=gnu -pedantic" }
+! Test the GNU extension of a L format descriptor without width
+! PR libfortran/54679
+program main
+ implicit none
+ character(len=20) :: str
+ character(len=60) :: format2 = "(2(1x,l0,1x))"
+ write(str,format2)
+end program main
+! { dg-output "At line 9 of file.*" }
+! { dg-output "Fortran runtime warning: Zero width after L descriptor(\n|\r\n|\r)" }
diff --git a/gcc/testsuite/gfortran.dg/fmt_t_9.f b/gcc/testsuite/gfortran.dg/fmt_t_9.f
new file mode 100644
index 00000000000..bfe0361d0e1
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/fmt_t_9.f
@@ -0,0 +1,41 @@
+! { dg-options "-ffixed-line-length-none -std=gnu" }
+! { dg-do run }
+! PR78123 Short reads with T edit descriptor not padding correctly
+ PROGRAM tformat
+C
+ INTEGER MXFLTL
+ PARAMETER (MXFLTL = 99999)
+ INTEGER IFLGHT, NFLCYC, IFLTSQ(MXFLTL), IDXBLK, LMAX, LMIN, I
+C
+ OPEN(29, status='scratch')
+ WRITE(29, '(a)') " 1 1 1 TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT 72 122 4"
+ WRITE(29, '(a)') ""
+ WRITE(29, '(a)') " 451 402012011201120112011200120112011201120112011201120111971201120112011201120112011201"
+ WRITE(29, '(a)') " 451 4020 866 866 866 866 866 866 866 866 865 866 865 866 866 866 866 866 866 866 865 866"
+ REWIND(29)
+C The error occurs in the following loop:
+ 10 CONTINUE
+ READ(29,1010 ) IDXBLK, LMAX, LMIN
+1010 FORMAT(8X,I4,T51,2I5) ! wrong if this format is used
+c write(6,fmt='("IDXBLK,LMAX,LMIN=",3I5)')IDXBLK,LMAX,LMIN
+ IF (IDXBLK .EQ. 0) GO TO 20
+ GO TO 10
+C
+ 20 CONTINUE
+ READ(29,1040,END=100) IFLGHT, NFLCYC,
+ & (IFLTSQ(I), I=1,NFLCYC)
+1040 FORMAT(I5,I5,2X,(T13,20I4))
+c write(6,fmt='(2i6)') IFLGHT,NFLCYC
+c write(6,fmt='(20I4)') (IFLTSQ(I), I=1,NFLCYC)
+c write(6,*) "Program is correct"
+ close(29)
+ if (IFLGHT.ne.451) call abort
+ if (NFLCYC.ne.40) call abort
+ stop
+C
+ 100 CONTINUE
+C write(6,*) "End of file encountered (wrong)"
+ close (29)
+ call abort
+ STOP
+ END
diff --git a/gcc/testsuite/gfortran.dg/implicit_class_1.f90 b/gcc/testsuite/gfortran.dg/implicit_class_1.f90
index 2ab90405eb0..380942cfdba 100644
--- a/gcc/testsuite/gfortran.dg/implicit_class_1.f90
+++ b/gcc/testsuite/gfortran.dg/implicit_class_1.f90
@@ -1,4 +1,5 @@
! { dg-do run }
+! { dg-skip-if "" { powerpc-ibm-aix* } { "*" } { "" } }
!
! PR 56500: [OOP] "IMPLICIT CLASS(...)" wrongly rejected
!
diff --git a/gcc/testsuite/gfortran.dg/move_alloc_17.f90 b/gcc/testsuite/gfortran.dg/move_alloc_17.f90
new file mode 100644
index 00000000000..acede0f901b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/move_alloc_17.f90
@@ -0,0 +1,21 @@
+! { dg-do compile }
+!
+! The call to MOVE_ALLOC below caused a seg fault in runtime.
+! This was discussed in:
+! https://groups.google.com/forum/#!topic/comp.lang.fortran/ZVLqXFYDZ0M
+! Richard Maine proposed that the code violated the restrictions on
+! actual arguments in F2003 12.4.1.7 and so the fix asserts that the
+! TO and FROM arguments cannot be the same object or subobjects thereof.
+!
+!
+program test_move_alloc
+ type :: linked_list
+ type(linked_list), allocatable :: link
+ integer :: value
+ end type linked_list
+ type(linked_list) :: test
+
+ allocate(test % link)
+ allocate(test % link % link)
+ call move_alloc(test % link, test % link % link) ! { dg-error "aliasing restrictions" }
+end program test_move_alloc
diff --git a/gcc/testsuite/gfortran.dg/move_alloc_18.f90 b/gcc/testsuite/gfortran.dg/move_alloc_18.f90
new file mode 100644
index 00000000000..bc72d5d1f87
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/move_alloc_18.f90
@@ -0,0 +1,21 @@
+! { dg-do compile }
+!
+! Test that the anti-aliasing restriction does not knock out valid code.
+!
+! Contributed by Andrew Balwin on
+! https://groups.google.com/forum/#!topic/comp.lang.fortran/oiXdl1LPb_s
+!
+ PROGRAM TEST
+ IMPLICIT NONE
+
+ TYPE FOOBAR
+ INTEGER, ALLOCATABLE :: COMP(:)
+ END TYPE
+
+ TYPE (FOOBAR) :: MY_ARRAY(6)
+
+ ALLOCATE (MY_ARRAY(1)%COMP(10))
+
+ CALL MOVE_ALLOC (MY_ARRAY(1)%COMP, MY_ARRAY(2)%COMP)
+
+ END PROGRAM TEST
diff --git a/gcc/testsuite/gfortran.dg/pr67219.f90 b/gcc/testsuite/gfortran.dg/pr67219.f90
new file mode 100644
index 00000000000..26d5f3f5cae
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pr67219.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! PR 67149 - this used to throw a spurious error.
+function foo(bar)
+ integer(8) :: foo
+ integer(4), intent(in) :: bar
+ integer(4), parameter :: huge_4 = huge(0_4)
+ foo = (huge_4 - int(bar,kind=8))
+end function
diff --git a/gcc/testsuite/gfortran.dg/pr70937.f90 b/gcc/testsuite/gfortran.dg/pr70937.f90
index 3fb17bd227e..265029b833d 100644
--- a/gcc/testsuite/gfortran.dg/pr70937.f90
+++ b/gcc/testsuite/gfortran.dg/pr70937.f90
@@ -1,4 +1,5 @@
! { dg-do compile }
+! { dg-require-effective-target lto }
! { dg-options "-flto" }
SUBROUTINE dbcsr_test_read_args(narg, args)
CHARACTER(len=*), DIMENSION(:), &
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_comp_46.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_comp_46.f90
new file mode 100644
index 00000000000..c01b8221210
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_comp_46.f90
@@ -0,0 +1,29 @@
+! { dg-do compile }
+!
+! PR 77596: [F03] procedure pointer component with implicit interface can point to a function
+!
+! Contributed by toK <t.kondic@leeds.ac.uk>
+
+program xxx
+ implicit none
+
+ type tf
+ procedure(), nopass, pointer :: fp
+ end type tf
+
+ call ass()
+
+contains
+
+ integer function ff(x)
+ integer, intent(in) :: x
+ ff = x + 1
+ end function ff
+
+ subroutine ass()
+ type(tf) :: p
+ p%fp=>ff ! { dg-error "is not a subroutine" }
+ call p%fp(3)
+ end subroutine ass
+
+end
diff --git a/gcc/testsuite/gfortran.dg/select_type_39.f03 b/gcc/testsuite/gfortran.dg/select_type_39.f03
new file mode 100644
index 00000000000..08d619536ab
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/select_type_39.f03
@@ -0,0 +1,20 @@
+! { dg-do run }
+!
+! Tests the fix for PR67564 comment #9.
+!
+! Contributed by Neil Carlson <neil.n.carlson@gmail.com>
+!
+class(*), allocatable :: val(:)
+call get_value (val)
+select type (val)
+type is (character(*))
+ if (size (val) .ne. 2) call abort
+ if (len(val) .ne. 3) call abort
+ if (any (val .ne. ['foo','bar'])) call abort
+end select
+contains
+ subroutine get_value (value)
+ class(*), allocatable, intent(out) :: value(:)
+ allocate(value, source=['foo','bar'])
+ end subroutine
+end
diff --git a/gcc/testsuite/gfortran.dg/warn_argument_mismatch_1.f90 b/gcc/testsuite/gfortran.dg/warn_argument_mismatch_1.f90
new file mode 100644
index 00000000000..6a663e66b5f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/warn_argument_mismatch_1.f90
@@ -0,0 +1,34 @@
+! { dg-do compile }
+! { dg-options "-Wno-argument-mismatch" }
+!
+! No warnings should be output here with -Wno-argument-mismatch.
+!
+
+subroutine s1(x)
+ implicit none
+ integer, intent(in) :: x
+ print *, x
+end subroutine
+
+subroutine s2(x)
+ implicit none
+ integer, intent(in) :: x(1)
+ print *, x
+end subroutine
+
+subroutine s3(x)
+ implicit none
+ integer, intent(in) :: x(2)
+ print *, x
+end subroutine
+
+implicit none
+integer :: x, y(1)
+real :: r
+
+call s1(r)
+call s1(y)
+call s2(x)
+call s3(y)
+
+end
diff --git a/gcc/testsuite/gfortran.dg/warn_conversion_9.f90 b/gcc/testsuite/gfortran.dg/warn_conversion_9.f90
new file mode 100644
index 00000000000..794eeef99b6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/warn_conversion_9.f90
@@ -0,0 +1,7 @@
+! { dg-do compile }
+! { dg-options "-Wconversion" }
+! PR 78221 - used to give a spurious warning
+complex, parameter :: i = (0.,1.)
+complex :: t
+t = (i)
+end
diff --git a/gcc/testsuite/gfortran.dg/where_5.f90 b/gcc/testsuite/gfortran.dg/where_5.f90
new file mode 100644
index 00000000000..5ada63d6a5d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/where_5.f90
@@ -0,0 +1,15 @@
+! { dg-do compile }
+! { dg-options "-Wcharacter-truncation" }
+subroutine where_ice (i,j)
+
+ implicit none
+
+ character(8) :: y(10,10,2)
+
+ integer :: i
+ integer :: j
+
+ character(12) :: txt(5)
+ where (txt(1:3) /= '' ) y(1:3,i,j) = txt(1:3) ! { dg-warning "CHARACTER expression will be truncated" }
+
+end subroutine where_ice
diff --git a/gcc/testsuite/gfortran.dg/where_6.f90 b/gcc/testsuite/gfortran.dg/where_6.f90
new file mode 100644
index 00000000000..c7c43db8423
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/where_6.f90
@@ -0,0 +1,15 @@
+! { dg-do compile }
+! { dg-options "-Wcharacter-truncation" }
+subroutine where_ice (i,j)
+
+ implicit none
+
+ character(8) :: y(10,10,2)
+
+ integer :: i
+ integer :: j
+
+ character(12) :: txt(5)
+ if (.true.) where (txt(1:3) /= '' ) y(1:3,i,j) = txt(1:3) ! { dg-warning "CHARACTER expression will be truncated" }
+
+end subroutine where_ice
diff --git a/gcc/testsuite/lib/scanasm.exp b/gcc/testsuite/lib/scanasm.exp
index 07b8f7d834d..707f63bea24 100644
--- a/gcc/testsuite/lib/scanasm.exp
+++ b/gcc/testsuite/lib/scanasm.exp
@@ -103,6 +103,7 @@ proc hidden-scan-for { symbol } {
set objformat [gcc_target_object_format]
switch $objformat {
+ coff { return "$symbol\[,\d\]*hidden" }
elf { return "hidden\[ \t_\]*$symbol" }
mach-o { return "private_extern\[ \t_\]*_?$symbol" }
default { return "" }
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index d2fe96ebeeb..ce60cce9cae 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -462,9 +462,7 @@ proc check_gc_sections_available { } {
}
# Check if the ld used by gcc supports --gc-sections.
- set gcc_spec [${tool}_target_compile "-dumpspecs" "" "none" ""]
- regsub ".*\n\\*linker:\[ \t\]*\n(\[^ \t\n\]*).*" "$gcc_spec" {\1} linker
- set gcc_ld [lindex [${tool}_target_compile "-print-prog-name=$linker" "" "none" ""] 0]
+ set gcc_ld [lindex [${tool}_target_compile "-print-prog-name=ld" "" "none" ""] 0]
set ld_output [remote_exec host "$gcc_ld" "--help"]
if { [ string first "--gc-sections" $ld_output ] >= 0 } {
set gc_sections_available_saved 1
@@ -533,7 +531,7 @@ proc check_profiling_available { test_what } {
}
if { $test_what == "-fauto-profile" } {
- if { ! ([istarget x86_64-*-linux*] || [istarget i?86-*-linux*]) } {
+ if { !([istarget i?86-*-linux*] || [istarget x86_64-*-linux*]) } {
verbose "autofdo only supported on linux"
return 0
}
@@ -1524,7 +1522,7 @@ proc check_750cl_hw_available { } {
proc check_sse_os_support_available { } {
return [check_cached_effective_target sse_os_support_available {
# If this is not the right target then we can skip the test.
- if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} elseif { [istarget i?86-*-solaris2*] } {
# The Solaris 2 kernel doesn't save and restore SSE registers
@@ -1548,7 +1546,7 @@ proc check_sse_os_support_available { } {
proc check_avx_os_support_available { } {
return [check_cached_effective_target avx_os_support_available {
# If this is not the right target then we can skip the test.
- if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
# Check that OS has AVX and SSE saving enabled.
@@ -1571,7 +1569,7 @@ proc check_avx_os_support_available { } {
proc check_sse_hw_available { } {
return [check_cached_effective_target sse_hw_available {
# If this is not the right target then we can skip the test.
- if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
check_runtime_nocache sse_hw_available {
@@ -1671,7 +1669,7 @@ proc check_mips_msa_hw_available { } {
proc check_sse2_hw_available { } {
return [check_cached_effective_target sse2_hw_available {
# If this is not the right target then we can skip the test.
- if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
check_runtime_nocache sse2_hw_available {
@@ -1694,7 +1692,7 @@ proc check_sse2_hw_available { } {
proc check_sse4_hw_available { } {
return [check_cached_effective_target sse4_hw_available {
# If this is not the right target then we can skip the test.
- if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
check_runtime_nocache sse4_hw_available {
@@ -1717,7 +1715,7 @@ proc check_sse4_hw_available { } {
proc check_avx_hw_available { } {
return [check_cached_effective_target avx_hw_available {
# If this is not the right target then we can skip the test.
- if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
expr 0
} else {
check_runtime_nocache avx_hw_available {
@@ -2622,8 +2620,7 @@ proc check_effective_target___float128 { } {
return [check_ppc_float128_sw_available]
}
if { [istarget ia64-*-*]
- || [istarget i?86-*-*]
- || [istarget x86_64-*-*] } {
+ || [istarget i?86-*-*] || [istarget x86_64-*-*] } {
return 1
}
return 0
@@ -2779,9 +2776,8 @@ proc check_effective_target_vect_cmdline_needed { } {
set et_vect_cmdline_needed_saved 1
if { [istarget alpha*-*-*]
|| [istarget ia64-*-*]
- || (([istarget x86_64-*-*] || [istarget i?86-*-*])
- && ([check_effective_target_x32]
- || [check_effective_target_lp64]))
+ || (([istarget i?86-*-*] || [istarget x86_64-*-*])
+ && ![is-effective-target ia32])
|| ([istarget powerpc*-*-*]
&& ([check_effective_target_powerpc_spe]
|| [check_effective_target_powerpc_altivec]))
@@ -2811,16 +2807,16 @@ proc check_effective_target_vect_int { } {
set et_vect_int_saved($et_index) 0
if { [istarget i?86-*-*] || [istarget x86_64-*-*]
|| ([istarget powerpc*-*-*]
- && ![istarget powerpc-*-linux*paired*])
- || [istarget spu-*-*]
- || [istarget sparc*-*-*]
- || [istarget alpha*-*-*]
- || [istarget ia64-*-*]
- || [istarget aarch64*-*-*]
- || [check_effective_target_arm32]
- || ([istarget mips*-*-*]
- && ([et-is-effective-target mips_loongson]
- || [et-is-effective-target mips_msa])) } {
+ && ![istarget powerpc-*-linux*paired*])
+ || [istarget spu-*-*]
+ || [istarget sparc*-*-*]
+ || [istarget alpha*-*-*]
+ || [istarget ia64-*-*]
+ || [istarget aarch64*-*-*]
+ || [check_effective_target_arm32]
+ || ([istarget mips*-*-*]
+ && ([et-is-effective-target mips_loongson]
+ || [et-is-effective-target mips_msa])) } {
set et_vect_int_saved($et_index) 1
}
}
@@ -2843,13 +2839,13 @@ proc check_effective_target_vect_intfloat_cvt { } {
} else {
set et_vect_intfloat_cvt_saved($et_index) 0
if { [istarget i?86-*-*] || [istarget x86_64-*-*]
- || ([istarget powerpc*-*-*]
- && ![istarget powerpc-*-linux*paired*])
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok])
- || ([istarget mips*-*-*]
- && [et-is-effective-target mips_msa]) } {
- set et_vect_intfloat_cvt_saved($et_index) 1
+ || ([istarget powerpc*-*-*]
+ && ![istarget powerpc-*-linux*paired*])
+ || ([istarget arm*-*-*]
+ && [check_effective_target_arm_neon_ok])
+ || ([istarget mips*-*-*]
+ && [et-is-effective-target mips_msa]) } {
+ set et_vect_intfloat_cvt_saved($et_index) 1
}
}
@@ -2885,14 +2881,14 @@ proc check_effective_target_vect_uintfloat_cvt { } {
} else {
set et_vect_uintfloat_cvt_saved($et_index) 0
if { [istarget i?86-*-*] || [istarget x86_64-*-*]
- || ([istarget powerpc*-*-*]
- && ![istarget powerpc-*-linux*paired*])
- || [istarget aarch64*-*-*]
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok])
- || ([istarget mips*-*-*]
- && [et-is-effective-target mips_msa]) } {
- set et_vect_uintfloat_cvt_saved($et_index) 1
+ || ([istarget powerpc*-*-*]
+ && ![istarget powerpc-*-linux*paired*])
+ || [istarget aarch64*-*-*]
+ || ([istarget arm*-*-*]
+ && [check_effective_target_arm_neon_ok])
+ || ([istarget mips*-*-*]
+ && [et-is-effective-target mips_msa]) } {
+ set et_vect_uintfloat_cvt_saved($et_index) 1
}
}
@@ -2915,13 +2911,13 @@ proc check_effective_target_vect_floatint_cvt { } {
} else {
set et_vect_floatint_cvt_saved($et_index) 0
if { [istarget i?86-*-*] || [istarget x86_64-*-*]
- || ([istarget powerpc*-*-*]
- && ![istarget powerpc-*-linux*paired*])
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok])
- || ([istarget mips*-*-*]
- && [et-is-effective-target mips_msa]) } {
- set et_vect_floatint_cvt_saved($et_index) 1
+ || ([istarget powerpc*-*-*]
+ && ![istarget powerpc-*-linux*paired*])
+ || ([istarget arm*-*-*]
+ && [check_effective_target_arm_neon_ok])
+ || ([istarget mips*-*-*]
+ && [et-is-effective-target mips_msa]) } {
+ set et_vect_floatint_cvt_saved($et_index) 1
}
}
@@ -2969,14 +2965,13 @@ proc check_effective_target_vect_simd_clones { } {
verbose "check_effective_target_vect_simd_clones: using cached result" 2
} else {
set et_vect_simd_clones_saved($et_index) 0
- if { [istarget i?86-*-*] || [istarget x86_64-*-*] } {
- # On i?86/x86_64 #pragma omp declare simd builds a sse2, avx, avx2
- # and avx512f clone. Only the right clone for the specified arch
- # will be chosen, but still we need to at least be able to assemble
- # avx512f.
- if { [check_effective_target_avx512f] } {
- set et_vect_simd_clones_saved($et_index) 1
- }
+ # On i?86/x86_64 #pragma omp declare simd builds a sse2, avx,
+ # avx2 and avx512f clone. Only the right clone for the
+ # specified arch will be chosen, but still we need to at least
+ # be able to assemble avx512f.
+ if { (([istarget i?86-*-*] || [istarget x86_64-*-*])
+ && [check_effective_target_avx512f]) } {
+ set et_vect_simd_clones_saved($et_index) 1
}
}
@@ -4781,7 +4776,7 @@ proc check_effective_target_vect_shift { } {
} else {
set et_vect_shift_saved($et_index) 0
if { ([istarget powerpc*-*-*]
- && ![istarget powerpc-*-linux*paired*])
+ && ![istarget powerpc-*-linux*paired*])
|| [istarget ia64-*-*]
|| [istarget i?86-*-*] || [istarget x86_64-*-*]
|| [istarget aarch64*-*-*]
@@ -4899,16 +4894,16 @@ proc check_effective_target_vect_float { } {
} else {
set et_vect_float_saved($et_index) 0
if { [istarget i?86-*-*] || [istarget x86_64-*-*]
- || [istarget powerpc*-*-*]
- || [istarget spu-*-*]
- || [istarget mips-sde-elf]
- || [istarget mipsisa64*-*-*]
- || [istarget ia64-*-*]
- || [istarget aarch64*-*-*]
- || ([istarget mips*-*-*]
- && [et-is-effective-target mips_msa])
- || [check_effective_target_arm32] } {
- set et_vect_float_saved($et_index) 1
+ || [istarget powerpc*-*-*]
+ || [istarget spu-*-*]
+ || [istarget mips-sde-elf]
+ || [istarget mipsisa64*-*-*]
+ || [istarget ia64-*-*]
+ || [istarget aarch64*-*-*]
+ || ([istarget mips*-*-*]
+ && [et-is-effective-target mips_msa])
+ || [check_effective_target_arm32] } {
+ set et_vect_float_saved($et_index) 1
}
}
@@ -4929,22 +4924,18 @@ proc check_effective_target_vect_double { } {
verbose "check_effective_target_vect_double: using cached result" 2
} else {
set et_vect_double_saved($et_index) 0
- if { [istarget i?86-*-*] || [istarget x86_64-*-*]
- || [istarget aarch64*-*-*] } {
- if { [check_no_compiler_messages vect_double assembly {
- #ifdef __tune_atom__
- # error No double vectorizer support.
- #endif
- }] } {
- set et_vect_double_saved($et_index) 1
- } else {
- set et_vect_double_saved($et_index) 0
- }
- } elseif { [istarget spu-*-*]
- || ([istarget powerpc*-*-*] && [check_vsx_hw_available])
- || ([istarget mips*-*-*]
- && [et-is-effective-target mips_msa]) } {
- set et_vect_double_saved($et_index) 1
+ if { (([istarget i?86-*-*] || [istarget x86_64-*-*])
+ && [check_no_compiler_messages vect_double assembly {
+ #ifdef __tune_atom__
+ # error No double vectorizer support.
+ #endif
+ }])
+ || [istarget aarch64*-*-*]
+ || [istarget spu-*-*]
+ || ([istarget powerpc*-*-*] && [check_vsx_hw_available])
+ || ([istarget mips*-*-*]
+ && [et-is-effective-target mips_msa]) } {
+ set et_vect_double_saved($et_index) 1
}
}
@@ -4966,8 +4957,8 @@ proc check_effective_target_vect_long_long { } {
} else {
set et_vect_long_long_saved($et_index) 0
if { [istarget i?86-*-*] || [istarget x86_64-*-*]
- || ([istarget mips*-*-*]
- && [et-is-effective-target mips_msa]) } {
+ || ([istarget mips*-*-*]
+ && [et-is-effective-target mips_msa]) } {
set et_vect_long_long_saved($et_index) 1
}
}
@@ -5296,12 +5287,12 @@ proc check_effective_target_vect_widen_mult_hi_to_si { } {
set et_vect_widen_mult_hi_to_si_saved($et_index) 0
}
if { [istarget powerpc*-*-*]
- || [istarget spu-*-*]
- || [istarget ia64-*-*]
- || [istarget aarch64*-*-*]
- || [istarget i?86-*-*] || [istarget x86_64-*-*]
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok]) } {
+ || [istarget spu-*-*]
+ || [istarget ia64-*-*]
+ || [istarget aarch64*-*-*]
+ || [istarget i?86-*-*] || [istarget x86_64-*-*]
+ || ([istarget arm*-*-*]
+ && [check_effective_target_arm_neon_ok]) } {
set et_vect_widen_mult_hi_to_si_saved($et_index) 1
}
}
@@ -5351,12 +5342,12 @@ proc check_effective_target_vect_widen_mult_hi_to_si_pattern { } {
} else {
set et_vect_widen_mult_hi_to_si_pattern_saved($et_index) 0
if { [istarget powerpc*-*-*]
- || [istarget spu-*-*]
- || [istarget ia64-*-*]
- || [istarget i?86-*-*] || [istarget x86_64-*-*]
- || ([istarget arm*-*-*]
- && [check_effective_target_arm_neon_ok]
- && [check_effective_target_arm_little_endian]) } {
+ || [istarget spu-*-*]
+ || [istarget ia64-*-*]
+ || [istarget i?86-*-*] || [istarget x86_64-*-*]
+ || ([istarget arm*-*-*]
+ && [check_effective_target_arm_neon_ok]
+ && [check_effective_target_arm_little_endian]) } {
set et_vect_widen_mult_hi_to_si_pattern_saved($et_index) 1
}
}
@@ -5523,7 +5514,7 @@ proc check_effective_target_vect_usad_char { } {
verbose "check_effective_target_vect_usad_char: using cached result" 2
} else {
set et_vect_usad_char_saved($et_index) 0
- if { ([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
+ if { [istarget i?86-*-*] || [istarget x86_64-*-*] } {
set et_vect_usad_char_saved($et_index) 1
}
}
@@ -5668,16 +5659,13 @@ proc check_effective_target_vect_hw_misalign { } {
proc check_effective_target_vect_aligned_arrays { } {
set et_vect_aligned_arrays 0
- if { ([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
- if { ([is-effective-target lp64]
- && ( ![check_avx_available]
- || [check_prefer_avx128])) } {
- set et_vect_aligned_arrays 1
- }
- }
- if [istarget spu-*-*] {
+ if { (([istarget i?86-*-*] || [istarget x86_64-*-*])
+ && !([is-effective-target ia32]
+ || ([check_avx_available] && ![check_prefer_avx128])))
+ || [istarget spu-*-*] } {
set et_vect_aligned_arrays 1
}
+
verbose "check_effective_target_vect_aligned_arrays:\
returning $et_vect_aligned_arrays" 2
return $et_vect_aligned_arrays
@@ -5991,7 +5979,7 @@ proc check_effective_target_vect_interleave { } {
|| ([istarget mips*-*-*]
&& ([et-is-effective-target mpaired_single]
|| [et-is-effective-target mips_msa])) } {
- set et_vect_interleave_saved($et_index) 1
+ set et_vect_interleave_saved($et_index) 1
}
}
@@ -6037,14 +6025,11 @@ proc check_effective_target_vect_multiple_sizes { } {
global et_index
set et_vect_multiple_sizes_saved($et_index) 0
- if { ([istarget aarch64*-*-*]
- || ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok])) } {
- set et_vect_multiple_sizes_saved($et_index) 1
- }
- if { ([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
- if { ([check_avx_available] && ![check_prefer_avx128]) } {
+ if { [istarget aarch64*-*-*]
+ || ([istarget arm*-*-*] && [check_effective_target_arm_neon_ok])
+ || (([istarget i?86-*-*] || [istarget x86_64-*-*])
+ && ([check_avx_available] && ![check_prefer_avx128])) } {
set et_vect_multiple_sizes_saved($et_index) 1
- }
}
verbose "check_effective_target_vect_multiple_sizes:\
@@ -6107,7 +6092,7 @@ proc check_effective_target_sqrt_insn { } {
verbose "check_effective_target_hw_sqrt: using cached result" 2
} else {
set et_sqrt_insn_saved 0
- if { [istarget x86_64-*-*]
+ if { [istarget i?86-*-*] || [istarget x86_64-*-*]
|| [istarget powerpc*-*-*]
|| [istarget aarch64*-*-*]
|| ([istarget arm*-*-*] && [check_effective_target_arm_vfp_ok]) } {
@@ -6145,8 +6130,8 @@ proc check_effective_target_vect_call_sqrtf { } {
proc check_effective_target_vect_call_lrint { } {
set et_vect_call_lrint 0
- if { ([istarget i?86-*-*] || [istarget x86_64-*-*])
- && [check_effective_target_ilp32] } {
+ if { (([istarget i?86-*-*] || [istarget x86_64-*-*])
+ && [check_effective_target_ilp32]) } {
set et_vect_call_lrint 1
}
@@ -6420,10 +6405,9 @@ proc check_effective_target_section_anchors { } {
# Return 1 if the target supports atomic operations on "int_128" values.
proc check_effective_target_sync_int_128 { } {
- if { ([istarget x86_64-*-*] || [istarget i?86-*-*])
- && ![is-effective-target ia32] } {
- return 1
- } elseif { [istarget spu-*-*] } {
+ if { (([istarget i?86-*-*] || [istarget x86_64-*-*])
+ && ![is-effective-target ia32])
+ || [istarget spu-*-*] } {
return 1
} else {
return 0
@@ -6434,21 +6418,21 @@ proc check_effective_target_sync_int_128 { } {
# and can execute them.
proc check_effective_target_sync_int_128_runtime { } {
- if { ([istarget x86_64-*-*] || [istarget i?86-*-*])
- && ![is-effective-target ia32] } {
- return [check_cached_effective_target sync_int_128_available {
- check_runtime_nocache sync_int_128_available {
- #include "cpuid.h"
- int main ()
- {
- unsigned int eax, ebx, ecx, edx;
- if (__get_cpuid (1, &eax, &ebx, &ecx, &edx))
- return !(ecx & bit_CMPXCHG16B);
- return 1;
- }
- } ""
- }]
- } elseif { [istarget spu-*-*] } {
+ if { (([istarget i?86-*-*] || [istarget x86_64-*-*])
+ && ![is-effective-target ia32]
+ && [check_cached_effective_target sync_int_128_available {
+ check_runtime_nocache sync_int_128_available {
+ #include "cpuid.h"
+ int main ()
+ {
+ unsigned int eax, ebx, ecx, edx;
+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+ return !(ecx & bit_CMPXCHG16B);
+ return 1;
+ }
+ } ""
+ }])
+ || [istarget spu-*-*] } {
return 1
} else {
return 0
@@ -6461,7 +6445,7 @@ proc check_effective_target_sync_int_128_runtime { } {
# Note: 32bit s390 targets require -mzarch in dg-options.
proc check_effective_target_sync_long_long { } {
- if { [istarget x86_64-*-*] || [istarget i?86-*-*])
+ if { [istarget i?86-*-*] || [istarget x86_64-*-*])
|| [istarget aarch64*-*-*]
|| [istarget arm*-*-*]
|| [istarget alpha*-*-*]
@@ -6480,46 +6464,43 @@ proc check_effective_target_sync_long_long { } {
# Note: 32bit x86 targets require -march=pentium in dg-options.
proc check_effective_target_sync_long_long_runtime { } {
- if { [istarget x86_64-*-*] || [istarget i?86-*-*] } {
- return [check_cached_effective_target sync_long_long_available {
- check_runtime_nocache sync_long_long_available {
- #include "cpuid.h"
- int main ()
- {
- unsigned int eax, ebx, ecx, edx;
- if (__get_cpuid (1, &eax, &ebx, &ecx, &edx))
- return !(edx & bit_CMPXCHG8B);
- return 1;
- }
- } ""
- }]
- } elseif { [istarget aarch64*-*-*] } {
- return 1
- } elseif { [istarget arm*-*-linux-*] } {
- return [check_runtime sync_longlong_runtime {
- #include <stdlib.h>
- int main ()
- {
- long long l1;
-
- if (sizeof (long long) != 8)
- exit (1);
+ if { (([istarget x86_64-*-*] || [istarget i?86-*-*])
+ && [check_cached_effective_target sync_long_long_available {
+ check_runtime_nocache sync_long_long_available {
+ #include "cpuid.h"
+ int main ()
+ {
+ unsigned int eax, ebx, ecx, edx;
+ if (__get_cpuid (1, &eax, &ebx, &ecx, &edx))
+ return !(edx & bit_CMPXCHG8B);
+ return 1;
+ }
+ } ""
+ }])
+ || [istarget aarch64*-*-*]
+ || ([istarget arm*-*-linux-*]
+ && [check_runtime sync_longlong_runtime {
+ #include <stdlib.h>
+ int main ()
+ {
+ long long l1;
- /* Just check for native; checking for kernel fallback is tricky. */
- asm volatile ("ldrexd r0,r1, [%0]" : : "r" (&l1) : "r0", "r1");
+ if (sizeof (long long) != 8)
+ exit (1);
- exit (0);
- }
- } "" ]
- } elseif { [istarget alpha*-*-*] } {
- return 1
- } elseif { ([istarget sparc*-*-*]
- && [check_effective_target_lp64]
- && [check_effective_target_ultrasparc_hw]) } {
- return 1
- } elseif { [istarget spu-*-*] } {
- return 1
- } elseif { [istarget powerpc*-*-*] && [check_effective_target_lp64] } {
+ /* Just check for native;
+ checking for kernel fallback is tricky. */
+ asm volatile ("ldrexd r0,r1, [%0]"
+ : : "r" (&l1) : "r0", "r1");
+ exit (0);
+ }
+ } "" ])
+ || [istarget alpha*-*-*]
+ || ([istarget sparc*-*-*]
+ && [check_effective_target_lp64]
+ && [check_effective_target_ultrasparc_hw])
+ || [istarget spu-*-*]
+ || ([istarget powerpc*-*-*] && [check_effective_target_lp64]) } {
return 1
} else {
return 0
@@ -6541,18 +6522,15 @@ proc check_effective_target_bswap { } {
|| [istarget m68k-*-*]
|| [istarget powerpc*-*-*]
|| [istarget rs6000-*-*]
- || [istarget s390*-*-*] } {
- set et_bswap_saved 1
- } else {
- if { [istarget arm*-*-*]
+ || [istarget s390*-*-*]
+ || ([istarget arm*-*-*]
&& [check_no_compiler_messages_nocache arm_v6_or_later object {
#if __ARM_ARCH < 6
#error not armv6 or later
#endif
int i;
- } ""] } {
+ } ""]) } {
set et_bswap_saved 1
- }
}
}
@@ -7231,7 +7209,7 @@ proc check_effective_target_avx512f { } {
# Return 1 if avx instructions can be compiled.
proc check_effective_target_avx { } {
- if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
return 0
}
return [check_no_compiler_messages avx object {
@@ -7897,7 +7875,7 @@ proc check_effective_target_pie_copyreloc { } {
global tool
global GCC_UNDER_TEST
- if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
return 0
}
@@ -7949,7 +7927,7 @@ proc check_effective_target_got32x_reloc { } {
global tool
global GCC_UNDER_TEST
- if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
return 0
}
@@ -8000,7 +7978,7 @@ proc check_effective_target_tls_get_addr_via_got { } {
global tool
global GCC_UNDER_TEST
- if { !([istarget x86_64-*-*] || [istarget i?86-*-*]) } {
+ if { !([istarget i?86-*-*] || [istarget x86_64-*-*]) } {
return 0
}
@@ -8094,3 +8072,55 @@ proc check_effective_target_profile_update_atomic {} {
int main (void) { return 0; }
} "-fprofile-update=atomic -fprofile-generate"]
}
+
+#For versions of ARM architectures that have hardware div insn,
+#disable the divmod transform
+
+proc check_effective_target_arm_divmod_simode { } {
+ return [check_no_compiler_messages arm_divmod assembly {
+ #ifdef __ARM_ARCH_EXT_IDIV__
+ #error has div insn
+ #endif
+ int i;
+ }]
+}
+
+# Return 1 if target supports divmod hardware insn or divmod libcall.
+
+proc check_effective_target_divmod { } {
+ #TODO: Add checks for all targets that have either hardware divmod insn
+ # or define libfunc for divmod.
+ if { [istarget arm*-*-*]
+ || [istarget i?86-*-*] || [istarget x86_64-*-*] } {
+ return 1
+ }
+ return 0
+}
+
+# Return 1 if target supports divmod for SImode. The reason for
+# separating this from check_effective_target_divmod is that
+# some versions of ARM architecture define div instruction
+# only for simode, and for these archs, we do not want to enable
+# divmod transform for simode.
+
+proc check_effective_target_divmod_simode { } {
+ if { [istarget arm*-*-*] } {
+ return [check_effective_target_arm_divmod_simode]
+ }
+
+ return [check_effective_target_divmod]
+}
+
+# Return 1 if store merging optimization is applicable for target.
+# Store merging is not profitable for targets like the avr which
+# can load/store only one byte at a time. Use int size as a proxy
+# for the number of bytes the target can write, and skip for targets
+# with a smallish (< 32) size.
+
+proc check_effective_target_store_merge { } {
+ if { [is-effective-target non_strict_align ] && [is-effective-target int32plus] } {
+ return 1
+ }
+
+ return 0
+}
diff --git a/gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm b/gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm
index 45b6e702481..744a017bef6 100644
--- a/gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm
+++ b/gcc/testsuite/obj-c++.dg/lto/trivial-1_0.mm
@@ -1,7 +1,7 @@
/* { dg-lto-do run } */
/* { dg-skip-if "Needs OBJC2 ABI" { "*-*-darwin*" && lp64 } { "*" } { "" } } */
extern "C" {
-extern int printf (char *,...) ;
+extern int printf (const char *,...) ;
extern void abort (void) ;
}
diff --git a/gcc/tree-call-cdce.c b/gcc/tree-call-cdce.c
index 8df9b08010f..861834d3663 100644
--- a/gcc/tree-call-cdce.c
+++ b/gcc/tree-call-cdce.c
@@ -807,15 +807,20 @@ shrink_wrap_one_built_in_call_with_conds (gcall *bi_call, vec <gimple *> conds,
can_guard_call_p. */
join_tgt_in_edge_from_call = find_fallthru_edge (bi_call_bb->succs);
gcc_assert (join_tgt_in_edge_from_call);
- free_dominance_info (CDI_DOMINATORS);
+ /* We don't want to handle PHIs. */
+ if (EDGE_COUNT (join_tgt_in_edge_from_call->dest->preds) > 1)
+ join_tgt_bb = split_edge (join_tgt_in_edge_from_call);
+ else
+ join_tgt_bb = join_tgt_in_edge_from_call->dest;
}
else
- join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
+ {
+ join_tgt_in_edge_from_call = split_block (bi_call_bb, bi_call);
+ join_tgt_bb = join_tgt_in_edge_from_call->dest;
+ }
bi_call_bsi = gsi_for_stmt (bi_call);
- join_tgt_bb = join_tgt_in_edge_from_call->dest;
-
/* Now it is time to insert the first conditional expression
into bi_call_bb and split this bb so that bi_call is
shrink-wrapped. */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index de5e5757080..6899d2a8736 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -1045,6 +1045,7 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
copy_body_data *id = (copy_body_data *) data;
tree fn = id->src_fn;
tree new_block;
+ bool copied = false;
/* Begin by recognizing trees that we'll completely rewrite for the
inlining context. Our output for these trees is completely
@@ -1241,10 +1242,40 @@ copy_tree_body_r (tree *tp, int *walk_subtrees, void *data)
*walk_subtrees = 0;
return NULL;
}
+ else if (TREE_CODE (*tp) == COND_EXPR)
+ {
+ tree cond = TREE_OPERAND (*tp, 0);
+ walk_tree (&cond, copy_tree_body_r, data, NULL);
+ tree folded = fold (cond);
+ if (TREE_CODE (folded) == INTEGER_CST)
+ {
+ /* Only copy the taken branch; for a C++ base constructor clone
+ inherited from a virtual base, copying the other branch leads
+ to references to parameters that were optimized away. */
+ tree branch = (integer_nonzerop (folded)
+ ? TREE_OPERAND (*tp, 1)
+ : TREE_OPERAND (*tp, 2));
+ tree type = TREE_TYPE (*tp);
+ if (VOID_TYPE_P (type)
+ || type == TREE_TYPE (branch))
+ {
+ *tp = branch;
+ return copy_tree_body_r (tp, walk_subtrees, data);
+ }
+ }
+ /* Avoid copying the condition twice. */
+ copy_tree_r (tp, walk_subtrees, NULL);
+ TREE_OPERAND (*tp, 0) = cond;
+ walk_tree (&TREE_OPERAND (*tp, 1), copy_tree_body_r, data, NULL);
+ walk_tree (&TREE_OPERAND (*tp, 2), copy_tree_body_r, data, NULL);
+ *walk_subtrees = 0;
+ copied = true;
+ }
/* Here is the "usual case". Copy this tree node, and then
tweak some special cases. */
- copy_tree_r (tp, walk_subtrees, NULL);
+ if (!copied)
+ copy_tree_r (tp, walk_subtrees, NULL);
/* If EXPR has block defined, map it to newly constructed block.
When inlining we want EXPRs without block appear in the block
diff --git a/gcc/tree-profile.c b/gcc/tree-profile.c
index abeee92204e..d18b954a385 100644
--- a/gcc/tree-profile.c
+++ b/gcc/tree-profile.c
@@ -56,9 +56,9 @@ static GTY(()) tree tree_interval_profiler_fn;
static GTY(()) tree tree_pow2_profiler_fn;
static GTY(()) tree tree_one_value_profiler_fn;
static GTY(()) tree tree_indirect_call_profiler_fn;
-static GTY(()) tree tree_time_profiler_fn;
static GTY(()) tree tree_average_profiler_fn;
static GTY(()) tree tree_ior_profiler_fn;
+static GTY(()) tree tree_time_profiler_counter;
static GTY(()) tree ic_void_ptr_var;
@@ -75,7 +75,7 @@ static GTY(()) tree ptr_void;
static void
init_ic_make_global_vars (void)
{
- tree gcov_type_ptr;
+ tree gcov_type_ptr;
ptr_void = build_pointer_type (void_type_node);
@@ -119,7 +119,7 @@ init_ic_make_global_vars (void)
/* Create the type and function decls for the interface with gcov. */
void
-gimple_init_edge_profiler (void)
+gimple_init_gcov_profiler (void)
{
tree interval_profiler_fn_type;
tree pow2_profiler_fn_type;
@@ -127,7 +127,6 @@ gimple_init_edge_profiler (void)
tree gcov_type_ptr;
tree ic_profiler_fn_type;
tree average_profiler_fn_type;
- tree time_profiler_fn_type;
const char *profiler_fn_name;
const char *fn_name;
@@ -201,17 +200,17 @@ gimple_init_edge_profiler (void)
= tree_cons (get_identifier ("leaf"), NULL,
DECL_ATTRIBUTES (tree_indirect_call_profiler_fn));
- /* void (*) (gcov_type *, gcov_type, void *) */
- time_profiler_fn_type
- = build_function_type_list (void_type_node,
- gcov_type_ptr, NULL_TREE);
- fn_name = concat ("__gcov_time_profiler", fn_suffix, NULL);
- tree_time_profiler_fn = build_fn_decl (fn_name, time_profiler_fn_type);
- free (CONST_CAST (char *, fn_name));
- TREE_NOTHROW (tree_time_profiler_fn) = 1;
- DECL_ATTRIBUTES (tree_time_profiler_fn)
- = tree_cons (get_identifier ("leaf"), NULL,
- DECL_ATTRIBUTES (tree_time_profiler_fn));
+ tree_time_profiler_counter
+ = build_decl (UNKNOWN_LOCATION, VAR_DECL,
+ get_identifier ("__gcov_time_profiler_counter"),
+ get_gcov_type ());
+ TREE_PUBLIC (tree_time_profiler_counter) = 1;
+ DECL_EXTERNAL (tree_time_profiler_counter) = 1;
+ TREE_STATIC (tree_time_profiler_counter) = 1;
+ DECL_ARTIFICIAL (tree_time_profiler_counter) = 1;
+ DECL_INITIAL (tree_time_profiler_counter) = NULL;
+
+ varpool_node::finalize_decl (tree_time_profiler_counter);
/* void (*) (gcov_type *, gcov_type) */
average_profiler_fn_type
@@ -239,7 +238,6 @@ gimple_init_edge_profiler (void)
DECL_ASSEMBLER_NAME (tree_pow2_profiler_fn);
DECL_ASSEMBLER_NAME (tree_one_value_profiler_fn);
DECL_ASSEMBLER_NAME (tree_indirect_call_profiler_fn);
- DECL_ASSEMBLER_NAME (tree_time_profiler_fn);
DECL_ASSEMBLER_NAME (tree_average_profiler_fn);
DECL_ASSEMBLER_NAME (tree_ior_profiler_fn);
}
@@ -426,7 +424,7 @@ gimple_gen_ic_func_profiler (void)
if (c_node->only_called_directly_p ())
return;
- gimple_init_edge_profiler ();
+ gimple_init_gcov_profiler ();
/* Insert code:
@@ -460,16 +458,75 @@ gimple_gen_ic_func_profiler (void)
counter position and GSI is the iterator we place the counter. */
void
-gimple_gen_time_profiler (unsigned tag, unsigned base,
- gimple_stmt_iterator &gsi)
+gimple_gen_time_profiler (unsigned tag, unsigned base)
{
- tree ref_ptr = tree_coverage_counter_addr (tag, base);
- gcall *call;
+ tree type = get_gcov_type ();
+ basic_block cond_bb
+ = split_edge (single_succ_edge (ENTRY_BLOCK_PTR_FOR_FN (cfun)));
+
+ basic_block update_bb = split_edge (single_succ_edge (cond_bb));
+
+ edge true_edge = single_succ_edge (cond_bb);
+ true_edge->flags = EDGE_TRUE_VALUE;
+ true_edge->probability = PROB_VERY_UNLIKELY;
+ edge e
+ = make_edge (cond_bb, single_succ_edge (update_bb)->dest, EDGE_FALSE_VALUE);
+ e->probability = REG_BR_PROB_BASE - true_edge->probability;
+
+ gimple_stmt_iterator gsi = gsi_start_bb (cond_bb);
+ tree original_ref = tree_coverage_counter_ref (tag, base);
+ tree ref = force_gimple_operand_gsi (&gsi, original_ref, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+ tree one = build_int_cst (type, 1);
- ref_ptr = force_gimple_operand_gsi (&gsi, ref_ptr,
- true, NULL_TREE, true, GSI_SAME_STMT);
- call = gimple_build_call (tree_time_profiler_fn, 1, ref_ptr);
- gsi_insert_before (&gsi, call, GSI_NEW_STMT);
+ /* Emit: if (counters[0] != 0). */
+ gcond *cond = gimple_build_cond (EQ_EXPR, ref, build_int_cst (type, 0),
+ NULL, NULL);
+ gsi_insert_before (&gsi, cond, GSI_NEW_STMT);
+
+ gsi = gsi_start_bb (update_bb);
+
+ /* Emit: counters[0] = ++__gcov_time_profiler_counter. */
+ if (flag_profile_update == PROFILE_UPDATE_ATOMIC)
+ {
+ tree ptr = make_temp_ssa_name (build_pointer_type (type), NULL,
+ "time_profiler_counter_ptr");
+ tree addr = build1 (ADDR_EXPR, TREE_TYPE (ptr),
+ tree_time_profiler_counter);
+ gassign *assign = gimple_build_assign (ptr, NOP_EXPR, addr);
+ gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
+ tree f = builtin_decl_explicit (LONG_LONG_TYPE_SIZE > 32
+ ? BUILT_IN_ATOMIC_ADD_FETCH_8:
+ BUILT_IN_ATOMIC_ADD_FETCH_4);
+ gcall *stmt = gimple_build_call (f, 3, ptr, one,
+ build_int_cst (integer_type_node,
+ MEMMODEL_RELAXED));
+ tree result_type = TREE_TYPE (TREE_TYPE (f));
+ tree tmp = make_temp_ssa_name (result_type, NULL, "time_profile");
+ gimple_set_lhs (stmt, tmp);
+ gsi_insert_after (&gsi, stmt, GSI_NEW_STMT);
+ tmp = make_temp_ssa_name (type, NULL, "time_profile");
+ assign = gimple_build_assign (tmp, NOP_EXPR,
+ gimple_call_lhs (stmt));
+ gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
+ assign = gimple_build_assign (original_ref, tmp);
+ gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
+ }
+ else
+ {
+ tree tmp = make_temp_ssa_name (type, NULL, "time_profile");
+ gassign *assign = gimple_build_assign (tmp, tree_time_profiler_counter);
+ gsi_insert_before (&gsi, assign, GSI_NEW_STMT);
+
+ tmp = make_temp_ssa_name (type, NULL, "time_profile");
+ assign = gimple_build_assign (tmp, PLUS_EXPR, gimple_assign_lhs (assign),
+ one);
+ gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
+ assign = gimple_build_assign (original_ref, tmp);
+ gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
+ assign = gimple_build_assign (tree_time_profiler_counter, tmp);
+ gsi_insert_after (&gsi, assign, GSI_NEW_STMT);
+ }
}
/* Output instructions as GIMPLE trees to increment the average histogram
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 26c9f9e894b..ebae6cfa6fe 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -32,12 +32,12 @@ along with GCC; see the file COPYING3. If not see
#include "tree-pretty-print.h"
#include "alias.h"
#include "fold-const.h"
-
#include "langhooks.h"
#include "dumpfile.h"
#include "tree-eh.h"
#include "tree-dfa.h"
#include "ipa-reference.h"
+#include "varasm.h"
/* Broad overview of how alias analysis on gimple works:
@@ -373,14 +373,18 @@ ptrs_compare_unequal (tree ptr1, tree ptr2)
/* We may not use restrict to optimize pointer comparisons.
See PR71062. So we have to assume that restrict-pointed-to
may be in fact obj1. */
- if (!pi || pi->pt.vars_contains_restrict)
+ if (!pi
+ || pi->pt.vars_contains_restrict
+ || pi->pt.vars_contains_interposable)
return false;
if (VAR_P (obj1)
&& (TREE_STATIC (obj1) || DECL_EXTERNAL (obj1)))
{
varpool_node *node = varpool_node::get (obj1);
/* If obj1 may bind to NULL give up (see below). */
- if (! node || ! node->nonzero_address ())
+ if (! node
+ || ! node->nonzero_address ()
+ || ! decl_binds_to_current_def_p (obj1))
return false;
}
return !pt_solution_includes (&pi->pt, obj1);
@@ -553,7 +557,12 @@ dump_points_to_solution (FILE *file, struct pt_solution *pt)
comma = ", ";
}
if (pt->vars_contains_restrict)
- fprintf (file, "%srestrict", comma);
+ {
+ fprintf (file, "%srestrict", comma);
+ comma = ", ";
+ }
+ if (pt->vars_contains_interposable)
+ fprintf (file, "%sinterposable", comma);
fprintf (file, ")");
}
}
diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
index 27a06fcca2c..810d83c978e 100644
--- a/gcc/tree-ssa-alias.h
+++ b/gcc/tree-ssa-alias.h
@@ -57,6 +57,8 @@ struct GTY(()) pt_solution
/* Nonzero if the vars bitmap includes a anonymous variable used to
represent storage pointed to by a restrict qualified pointer. */
unsigned int vars_contains_restrict : 1;
+ /* Nonzero if the vars bitmap includes an interposable variable. */
+ unsigned int vars_contains_interposable : 1;
/* Set of variables that this pointer may point to. */
bitmap vars;
diff --git a/gcc/tree-ssa-loop-im.c b/gcc/tree-ssa-loop-im.c
index 463db048cb6..0524e57564f 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -44,6 +44,7 @@ along with GCC; see the file COPYING3. If not see
#include "trans-mem.h"
#include "gimple-fold.h"
#include "tree-scalar-evolution.h"
+#include "tree-ssa-loop-niter.h"
/* TODO: Support for predicated code motion. I.e.
@@ -2369,8 +2370,16 @@ fill_always_executed_in_1 (struct loop *loop, sbitmap contains_call)
break;
FOR_EACH_EDGE (e, ei, bb->succs)
- if (!flow_bb_inside_loop_p (loop, e->dest))
- break;
+ {
+ /* If there is an exit from this BB. */
+ if (!flow_bb_inside_loop_p (loop, e->dest))
+ break;
+ /* Or we enter a possibly non-finite loop. */
+ if (flow_loop_nested_p (bb->loop_father,
+ e->dest->loop_father)
+ && ! finite_loop_p (e->dest->loop_father))
+ break;
+ }
if (e)
break;
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 0cea1a8472d..c315da88ce4 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -112,6 +112,9 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "internal-fn.h"
#include "case-cfn-macros.h"
+#include "optabs-libfuncs.h"
+#include "tree-eh.h"
+#include "targhooks.h"
/* This structure represents one basic block that either computes a
division, or is a common dominator for basic block that compute a
@@ -184,6 +187,9 @@ static struct
/* Number of fp fused multiply-add ops inserted. */
int fmas_inserted;
+
+ /* Number of divmod calls inserted. */
+ int divmod_calls_inserted;
} widen_mul_stats;
/* The instance of "struct occurrence" representing the highest
@@ -3793,6 +3799,213 @@ match_uaddsub_overflow (gimple_stmt_iterator *gsi, gimple *stmt,
return true;
}
+/* Return true if target has support for divmod. */
+
+static bool
+target_supports_divmod_p (optab divmod_optab, optab div_optab, machine_mode mode)
+{
+ /* If target supports hardware divmod insn, use it for divmod. */
+ if (optab_handler (divmod_optab, mode) != CODE_FOR_nothing)
+ return true;
+
+ /* Check if libfunc for divmod is available. */
+ rtx libfunc = optab_libfunc (divmod_optab, mode);
+ if (libfunc != NULL_RTX)
+ {
+ /* If optab_handler exists for div_optab, perhaps in a wider mode,
+ we don't want to use the libfunc even if it exists for given mode. */
+ for (machine_mode div_mode = mode;
+ div_mode != VOIDmode;
+ div_mode = GET_MODE_WIDER_MODE (div_mode))
+ if (optab_handler (div_optab, div_mode) != CODE_FOR_nothing)
+ return false;
+
+ return targetm.expand_divmod_libfunc != NULL;
+ }
+
+ return false;
+}
+
+/* Check if stmt is candidate for divmod transform. */
+
+static bool
+divmod_candidate_p (gassign *stmt)
+{
+ tree type = TREE_TYPE (gimple_assign_lhs (stmt));
+ enum machine_mode mode = TYPE_MODE (type);
+ optab divmod_optab, div_optab;
+
+ if (TYPE_UNSIGNED (type))
+ {
+ divmod_optab = udivmod_optab;
+ div_optab = udiv_optab;
+ }
+ else
+ {
+ divmod_optab = sdivmod_optab;
+ div_optab = sdiv_optab;
+ }
+
+ tree op1 = gimple_assign_rhs1 (stmt);
+ tree op2 = gimple_assign_rhs2 (stmt);
+
+ /* Disable the transform if either is a constant, since division-by-constant
+ may have specialized expansion. */
+ if (CONSTANT_CLASS_P (op1) || CONSTANT_CLASS_P (op2))
+ return false;
+
+ /* Exclude the case where TYPE_OVERFLOW_TRAPS (type) as that should
+ expand using the [su]divv optabs. */
+ if (TYPE_OVERFLOW_TRAPS (type))
+ return false;
+
+ if (!target_supports_divmod_p (divmod_optab, div_optab, mode))
+ return false;
+
+ return true;
+}
+
+/* This function looks for:
+ t1 = a TRUNC_DIV_EXPR b;
+ t2 = a TRUNC_MOD_EXPR b;
+ and transforms it to the following sequence:
+ complex_tmp = DIVMOD (a, b);
+ t1 = REALPART_EXPR(a);
+ t2 = IMAGPART_EXPR(b);
+ For conditions enabling the transform see divmod_candidate_p().
+
+ The pass has three parts:
+ 1) Find top_stmt which is trunc_div or trunc_mod stmt and dominates all
+ other trunc_div_expr and trunc_mod_expr stmts.
+ 2) Add top_stmt and all trunc_div and trunc_mod stmts dominated by top_stmt
+ to stmts vector.
+ 3) Insert DIVMOD call just before top_stmt and update entries in
+ stmts vector to use return value of DIMOVD (REALEXPR_PART for div,
+ IMAGPART_EXPR for mod). */
+
+static bool
+convert_to_divmod (gassign *stmt)
+{
+ if (stmt_can_throw_internal (stmt)
+ || !divmod_candidate_p (stmt))
+ return false;
+
+ tree op1 = gimple_assign_rhs1 (stmt);
+ tree op2 = gimple_assign_rhs2 (stmt);
+
+ imm_use_iterator use_iter;
+ gimple *use_stmt;
+ auto_vec<gimple *> stmts;
+
+ gimple *top_stmt = stmt;
+ basic_block top_bb = gimple_bb (stmt);
+
+ /* Part 1: Try to set top_stmt to "topmost" stmt that dominates
+ at-least stmt and possibly other trunc_div/trunc_mod stmts
+ having same operands as stmt. */
+
+ FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, op1)
+ {
+ if (is_gimple_assign (use_stmt)
+ && (gimple_assign_rhs_code (use_stmt) == TRUNC_DIV_EXPR
+ || gimple_assign_rhs_code (use_stmt) == TRUNC_MOD_EXPR)
+ && operand_equal_p (op1, gimple_assign_rhs1 (use_stmt), 0)
+ && operand_equal_p (op2, gimple_assign_rhs2 (use_stmt), 0))
+ {
+ if (stmt_can_throw_internal (use_stmt))
+ continue;
+
+ basic_block bb = gimple_bb (use_stmt);
+
+ if (bb == top_bb)
+ {
+ if (gimple_uid (use_stmt) < gimple_uid (top_stmt))
+ top_stmt = use_stmt;
+ }
+ else if (dominated_by_p (CDI_DOMINATORS, top_bb, bb))
+ {
+ top_bb = bb;
+ top_stmt = use_stmt;
+ }
+ }
+ }
+
+ tree top_op1 = gimple_assign_rhs1 (top_stmt);
+ tree top_op2 = gimple_assign_rhs2 (top_stmt);
+
+ stmts.safe_push (top_stmt);
+ bool div_seen = (gimple_assign_rhs_code (top_stmt) == TRUNC_DIV_EXPR);
+
+ /* Part 2: Add all trunc_div/trunc_mod statements domianted by top_bb
+ to stmts vector. The 2nd loop will always add stmt to stmts vector, since
+ gimple_bb (top_stmt) dominates gimple_bb (stmt), so the
+ 2nd loop ends up adding at-least single trunc_mod_expr stmt. */
+
+ FOR_EACH_IMM_USE_STMT (use_stmt, use_iter, top_op1)
+ {
+ if (is_gimple_assign (use_stmt)
+ && (gimple_assign_rhs_code (use_stmt) == TRUNC_DIV_EXPR
+ || gimple_assign_rhs_code (use_stmt) == TRUNC_MOD_EXPR)
+ && operand_equal_p (top_op1, gimple_assign_rhs1 (use_stmt), 0)
+ && operand_equal_p (top_op2, gimple_assign_rhs2 (use_stmt), 0))
+ {
+ if (use_stmt == top_stmt
+ || stmt_can_throw_internal (use_stmt)
+ || !dominated_by_p (CDI_DOMINATORS, gimple_bb (use_stmt), top_bb))
+ continue;
+
+ stmts.safe_push (use_stmt);
+ if (gimple_assign_rhs_code (use_stmt) == TRUNC_DIV_EXPR)
+ div_seen = true;
+ }
+ }
+
+ if (!div_seen)
+ return false;
+
+ /* Part 3: Create libcall to internal fn DIVMOD:
+ divmod_tmp = DIVMOD (op1, op2). */
+
+ gcall *call_stmt = gimple_build_call_internal (IFN_DIVMOD, 2, op1, op2);
+ tree res = make_temp_ssa_name (build_complex_type (TREE_TYPE (op1)),
+ call_stmt, "divmod_tmp");
+ gimple_call_set_lhs (call_stmt, res);
+
+ /* Insert the call before top_stmt. */
+ gimple_stmt_iterator top_stmt_gsi = gsi_for_stmt (top_stmt);
+ gsi_insert_before (&top_stmt_gsi, call_stmt, GSI_SAME_STMT);
+
+ widen_mul_stats.divmod_calls_inserted++;
+
+ /* Update all statements in stmts vector:
+ lhs = op1 TRUNC_DIV_EXPR op2 -> lhs = REALPART_EXPR<divmod_tmp>
+ lhs = op1 TRUNC_MOD_EXPR op2 -> lhs = IMAGPART_EXPR<divmod_tmp>. */
+
+ for (unsigned i = 0; stmts.iterate (i, &use_stmt); ++i)
+ {
+ tree new_rhs;
+
+ switch (gimple_assign_rhs_code (use_stmt))
+ {
+ case TRUNC_DIV_EXPR:
+ new_rhs = fold_build1 (REALPART_EXPR, TREE_TYPE (op1), res);
+ break;
+
+ case TRUNC_MOD_EXPR:
+ new_rhs = fold_build1 (IMAGPART_EXPR, TREE_TYPE (op1), res);
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
+ gimple_assign_set_rhs_from_tree (&gsi, new_rhs);
+ update_stmt (use_stmt);
+ }
+
+ return true;
+}
/* Find integer multiplications where the operands are extended from
smaller types, and replace the MULT_EXPR with a WIDEN_MULT_EXPR
@@ -3837,6 +4050,8 @@ pass_optimize_widening_mul::execute (function *fun)
bool cfg_changed = false;
memset (&widen_mul_stats, 0, sizeof (widen_mul_stats));
+ calculate_dominance_info (CDI_DOMINATORS);
+ renumber_gimple_stmt_uids ();
FOR_EACH_BB_FN (bb, fun)
{
@@ -3870,6 +4085,10 @@ pass_optimize_widening_mul::execute (function *fun)
match_uaddsub_overflow (&gsi, stmt, code);
break;
+ case TRUNC_MOD_EXPR:
+ convert_to_divmod (as_a<gassign *> (stmt));
+ break;
+
default:;
}
}
@@ -3916,6 +4135,8 @@ pass_optimize_widening_mul::execute (function *fun)
widen_mul_stats.maccs_inserted);
statistics_counter_event (fun, "fused multiply-adds inserted",
widen_mul_stats.fmas_inserted);
+ statistics_counter_event (fun, "divmod calls inserted",
+ widen_mul_stats.divmod_calls_inserted);
return cfg_changed ? TODO_cleanup_cfg : 0;
}
diff --git a/gcc/tree-ssa-phiopt.c b/gcc/tree-ssa-phiopt.c
index 3f3b88cfc61..63738d07e2e 100644
--- a/gcc/tree-ssa-phiopt.c
+++ b/gcc/tree-ssa-phiopt.c
@@ -1474,6 +1474,14 @@ abs_replacement (basic_block cond_bb, basic_block middle_bb,
else
negate = false;
+ /* If the code negates only iff positive then make sure to not
+ introduce undefined behavior when negating or computing the absolute.
+ ??? We could use range info if present to check for arg1 == INT_MIN. */
+ if (negate
+ && (ANY_INTEGRAL_TYPE_P (TREE_TYPE (arg1))
+ && ! TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg1))))
+ return false;
+
result = duplicate_ssa_name (result, NULL);
if (negate)
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 99e1b414070..5dcf6720605 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -924,7 +924,7 @@ eliminate_using_constants (enum tree_code opcode,
tree type = TREE_TYPE (oelast->op);
if (oelast->rank == 0
- && (INTEGRAL_TYPE_P (type) || FLOAT_TYPE_P (type)))
+ && (ANY_INTEGRAL_TYPE_P (type) || FLOAT_TYPE_P (type)))
{
switch (opcode)
{
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index fb364f1319d..28803826b43 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -39,6 +39,8 @@
#include "tree-dfa.h"
#include "params.h"
#include "gimple-walk.h"
+#include "varasm.h"
+
/* The idea behind this analyzer is to generate set constraints from the
program, then solve the resulting constraints in order to generate the
@@ -5566,7 +5568,7 @@ push_fields_onto_fieldstack (tree type, vec<fieldoff_s> *fieldstack,
&& offset + foff != 0)
{
fieldoff_s e
- = {0, offset + foff, false, false, false, false, NULL_TREE};
+ = {0, offset + foff, false, false, true, false, NULL_TREE};
pair = fieldstack->safe_push (e);
}
@@ -6360,6 +6362,13 @@ set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt,
&& fndecl
&& ! auto_var_in_fn_p (vi->decl, fndecl)))
pt->vars_contains_nonlocal = true;
+
+ /* If we have a variable that is interposable record that fact
+ for pointer comparison simplification. */
+ if (VAR_P (vi->decl)
+ && (TREE_STATIC (vi->decl) || DECL_EXTERNAL (vi->decl))
+ && ! decl_binds_to_current_def_p (vi->decl))
+ pt->vars_contains_interposable = true;
}
else if (TREE_CODE (vi->decl) == FUNCTION_DECL
@@ -7592,7 +7601,8 @@ make_pass_build_ealias (gcc::context *ctxt)
/* IPA PTA solutions for ESCAPED. */
struct pt_solution ipa_escaped_pt
- = { true, false, false, false, false, false, false, false, false, NULL };
+ = { true, false, false, false, false,
+ false, false, false, false, false, NULL };
/* Associate node with varinfo DATA. Worker for
cgraph_for_symbol_thunks_and_aliases. */
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index c99fa4069be..220dc302627 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -583,6 +583,7 @@ vect_slp_analyze_node_dependences (slp_instance instance, slp_tree node,
if (!dr_b)
return false;
+ bool dependent = false;
/* If we run into a store of this same instance (we've just
marked those) then delay dependence checking until we run
into the last store because this is where it will have
@@ -599,22 +600,21 @@ vect_slp_analyze_node_dependences (slp_instance instance, slp_tree node,
= STMT_VINFO_DATA_REF (vinfo_for_stmt (store));
ddr_p ddr = initialize_data_dependence_relation
(dr_a, store_dr, vNULL);
- if (vect_slp_analyze_data_ref_dependence (ddr))
- {
- free_dependence_relation (ddr);
- return false;
- }
+ dependent = vect_slp_analyze_data_ref_dependence (ddr);
free_dependence_relation (ddr);
+ if (dependent)
+ break;
}
}
-
- ddr_p ddr = initialize_data_dependence_relation (dr_a, dr_b, vNULL);
- if (vect_slp_analyze_data_ref_dependence (ddr))
+ else
{
+ ddr_p ddr = initialize_data_dependence_relation (dr_a,
+ dr_b, vNULL);
+ dependent = vect_slp_analyze_data_ref_dependence (ddr);
free_dependence_relation (ddr);
- return false;
}
- free_dependence_relation (ddr);
+ if (dependent)
+ return false;
}
}
return true;
@@ -773,10 +773,25 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
base = ref;
while (handled_component_p (base))
base = TREE_OPERAND (base, 0);
+ unsigned int base_alignment;
+ unsigned HOST_WIDE_INT base_bitpos;
+ get_object_alignment_1 (base, &base_alignment, &base_bitpos);
+ /* As data-ref analysis strips the MEM_REF down to its base operand
+ to form DR_BASE_ADDRESS and adds the offset to DR_INIT we have to
+ adjust things to make base_alignment valid as the alignment of
+ DR_BASE_ADDRESS. */
if (TREE_CODE (base) == MEM_REF)
- base = build2 (MEM_REF, TREE_TYPE (base), base_addr,
- build_int_cst (TREE_TYPE (TREE_OPERAND (base, 1)), 0));
- unsigned int base_alignment = get_object_alignment (base);
+ {
+ base_bitpos -= mem_ref_offset (base).to_short_addr () * BITS_PER_UNIT;
+ base_bitpos &= (base_alignment - 1);
+ }
+ if (base_bitpos != 0)
+ base_alignment = base_bitpos & -base_bitpos;
+ /* Also look at the alignment of the base address DR analysis
+ computed. */
+ unsigned int base_addr_alignment = get_pointer_alignment (base_addr);
+ if (base_addr_alignment > base_alignment)
+ base_alignment = base_addr_alignment;
if (base_alignment >= TYPE_ALIGN (TREE_TYPE (vectype)))
DR_VECT_AUX (dr)->base_element_aligned = true;
@@ -798,12 +813,9 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
if (base_alignment < TYPE_ALIGN (vectype))
{
- /* Strip an inner MEM_REF to a bare decl if possible. */
- if (TREE_CODE (base) == MEM_REF
- && integer_zerop (TREE_OPERAND (base, 1))
- && TREE_CODE (TREE_OPERAND (base, 0)) == ADDR_EXPR)
- base = TREE_OPERAND (TREE_OPERAND (base, 0), 0);
-
+ base = base_addr;
+ if (TREE_CODE (base) == ADDR_EXPR)
+ base = TREE_OPERAND (base, 0);
if (!vect_can_force_dr_alignment_p (base, TYPE_ALIGN (vectype)))
{
if (dump_enabled_p ())
@@ -816,6 +828,19 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
return true;
}
+ if (DECL_USER_ALIGN (base))
+ {
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_NOTE, vect_location,
+ "not forcing alignment of user-aligned "
+ "variable: ");
+ dump_generic_expr (MSG_NOTE, TDF_SLIM, base);
+ dump_printf (MSG_NOTE, "\n");
+ }
+ return true;
+ }
+
/* Force the alignment of the decl.
NOTE: This is the only change to the code we make during
the analysis phase, before deciding to vectorize the loop. */
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 9cca9b717a6..1cd9c7221b0 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -1225,6 +1225,27 @@ destroy_loop_vec_info (loop_vec_info loop_vinfo, bool clean_stmts)
swap_ssa_operands (stmt,
gimple_assign_rhs1_ptr (stmt),
gimple_assign_rhs2_ptr (stmt));
+ else if (code == COND_EXPR
+ && CONSTANT_CLASS_P (gimple_assign_rhs2 (stmt)))
+ {
+ tree cond_expr = gimple_assign_rhs1 (stmt);
+ enum tree_code cond_code = TREE_CODE (cond_expr);
+
+ if (TREE_CODE_CLASS (cond_code) == tcc_comparison)
+ {
+ bool honor_nans = HONOR_NANS (TREE_OPERAND (cond_expr,
+ 0));
+ cond_code = invert_tree_comparison (cond_code,
+ honor_nans);
+ if (cond_code != ERROR_MARK)
+ {
+ TREE_SET_CODE (cond_expr, cond_code);
+ swap_ssa_operands (stmt,
+ gimple_assign_rhs2_ptr (stmt),
+ gimple_assign_rhs3_ptr (stmt));
+ }
+ }
+ }
}
/* Free stmt_vec_info. */
@@ -3006,38 +3027,56 @@ vect_is_simple_reduction (loop_vec_info loop_info, gimple *phi,
&& (code == COND_EXPR
|| !def2 || gimple_nop_p (def2)
|| !flow_bb_inside_loop_p (loop, gimple_bb (def2))
- || (def2 && flow_bb_inside_loop_p (loop, gimple_bb (def2))
- && (is_gimple_assign (def2)
+ || (def2 && flow_bb_inside_loop_p (loop, gimple_bb (def2))
+ && (is_gimple_assign (def2)
|| is_gimple_call (def2)
- || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def2))
- == vect_induction_def
- || (gimple_code (def2) == GIMPLE_PHI
+ || STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def2))
+ == vect_induction_def
+ || (gimple_code (def2) == GIMPLE_PHI
&& STMT_VINFO_DEF_TYPE (vinfo_for_stmt (def2))
- == vect_internal_def
+ == vect_internal_def
&& !is_loop_header_bb_p (gimple_bb (def2)))))))
{
- if (check_reduction
- && orig_code != MINUS_EXPR)
- {
+ if (check_reduction && orig_code != MINUS_EXPR)
+ {
+ /* Check if we can swap operands (just for simplicity - so that
+ the rest of the code can assume that the reduction variable
+ is always the last (second) argument). */
if (code == COND_EXPR)
{
- /* No current known use where this case would be useful. */
- if (dump_enabled_p ())
- report_vect_op (MSG_NOTE, def_stmt,
- "detected reduction: cannot currently swap "
- "operands for cond_expr");
- return NULL;
+ /* Swap cond_expr by inverting the condition. */
+ tree cond_expr = gimple_assign_rhs1 (def_stmt);
+ enum tree_code invert_code = ERROR_MARK;
+ enum tree_code cond_code = TREE_CODE (cond_expr);
+
+ if (TREE_CODE_CLASS (cond_code) == tcc_comparison)
+ {
+ bool honor_nans = HONOR_NANS (TREE_OPERAND (cond_expr, 0));
+ invert_code = invert_tree_comparison (cond_code, honor_nans);
+ }
+ if (invert_code != ERROR_MARK)
+ {
+ TREE_SET_CODE (cond_expr, invert_code);
+ swap_ssa_operands (def_stmt,
+ gimple_assign_rhs2_ptr (def_stmt),
+ gimple_assign_rhs3_ptr (def_stmt));
+ }
+ else
+ {
+ if (dump_enabled_p ())
+ report_vect_op (MSG_NOTE, def_stmt,
+ "detected reduction: cannot swap operands "
+ "for cond_expr");
+ return NULL;
+ }
}
+ else
+ swap_ssa_operands (def_stmt, gimple_assign_rhs1_ptr (def_stmt),
+ gimple_assign_rhs2_ptr (def_stmt));
- /* Swap operands (just for simplicity - so that the rest of the code
- can assume that the reduction variable is always the last (second)
- argument). */
- if (dump_enabled_p ())
+ if (dump_enabled_p ())
report_vect_op (MSG_NOTE, def_stmt,
- "detected reduction: need to swap operands: ");
-
- swap_ssa_operands (def_stmt, gimple_assign_rhs1_ptr (def_stmt),
- gimple_assign_rhs2_ptr (def_stmt));
+ "detected reduction: need to swap operands: ");
if (CONSTANT_CLASS_P (gimple_assign_rhs1 (def_stmt)))
LOOP_VINFO_OPERANDS_SWAPPED (loop_info) = true;
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 5a611e42556..8d547681913 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -207,14 +207,20 @@ vect_get_place_in_interleaving_chain (gimple *stmt, gimple *first_stmt)
/* Get the defs for the rhs of STMT (collect them in OPRNDS_INFO), check that
they are of a valid type and that they match the defs of the first stmt of
- the SLP group (stored in OPRNDS_INFO). If there was a fatal error
- return -1, if the error could be corrected by swapping operands of the
- operation return 1, if everything is ok return 0. */
+ the SLP group (stored in OPRNDS_INFO). This function tries to match stmts
+ by swapping operands of STMT when possible. Non-zero *SWAP indicates swap
+ is required for cond_expr stmts. Specifically, *SWAP is 1 if STMT is cond
+ and operands of comparison need to be swapped; *SWAP is 2 if STMT is cond
+ and code of comparison needs to be inverted. If there is any operand swap
+ in this function, *SWAP is set to non-zero value.
+ If there was a fatal error return -1; if the error could be corrected by
+ swapping operands of father node of this one, return 1; if everything is
+ ok return 0. */
-static int
-vect_get_and_check_slp_defs (vec_info *vinfo,
+static int
+vect_get_and_check_slp_defs (vec_info *vinfo, unsigned char *swap,
gimple *stmt, unsigned stmt_num,
- vec<slp_oprnd_info> *oprnds_info)
+ vec<slp_oprnd_info> *oprnds_info)
{
tree oprnd;
unsigned int i, number_of_oprnds;
@@ -237,11 +243,12 @@ vect_get_and_check_slp_defs (vec_info *vinfo,
{
enum tree_code code = gimple_assign_rhs_code (stmt);
number_of_oprnds = gimple_num_ops (stmt) - 1;
+ /* Swap can only be done for cond_expr if asked to, otherwise we
+ could result in different comparison code to the first stmt. */
if (gimple_assign_rhs_code (stmt) == COND_EXPR
&& COMPARISON_CLASS_P (gimple_assign_rhs1 (stmt)))
{
first_op_cond = true;
- commutative = true;
number_of_oprnds++;
}
else
@@ -250,20 +257,24 @@ vect_get_and_check_slp_defs (vec_info *vinfo,
else
return -1;
- bool swapped = false;
+ bool swapped = (*swap != 0);
+ gcc_assert (!swapped || first_op_cond);
for (i = 0; i < number_of_oprnds; i++)
{
again:
if (first_op_cond)
{
- if (i == 0 || i == 1)
- oprnd = TREE_OPERAND (gimple_op (stmt, first_op_idx),
- swapped ? !i : i);
+ /* Map indicating how operands of cond_expr should be swapped. */
+ int maps[3][4] = {{0, 1, 2, 3}, {1, 0, 2, 3}, {0, 1, 3, 2}};
+ int *map = maps[*swap];
+
+ if (i < 2)
+ oprnd = TREE_OPERAND (gimple_op (stmt, first_op_idx), map[i]);
else
- oprnd = gimple_op (stmt, first_op_idx + i - 1);
+ oprnd = gimple_op (stmt, map[i]);
}
else
- oprnd = gimple_op (stmt, first_op_idx + (swapped ? !i : i));
+ oprnd = gimple_op (stmt, first_op_idx + (swapped ? !i : i));
oprnd_info = (*oprnds_info)[i];
@@ -431,9 +442,25 @@ again:
if (first_op_cond)
{
tree cond = gimple_assign_rhs1 (stmt);
- swap_ssa_operands (stmt, &TREE_OPERAND (cond, 0),
- &TREE_OPERAND (cond, 1));
- TREE_SET_CODE (cond, swap_tree_comparison (TREE_CODE (cond)));
+ enum tree_code code = TREE_CODE (cond);
+
+ /* Swap. */
+ if (*swap == 1)
+ {
+ swap_ssa_operands (stmt, &TREE_OPERAND (cond, 0),
+ &TREE_OPERAND (cond, 1));
+ TREE_SET_CODE (cond, swap_tree_comparison (code));
+ }
+ /* Invert. */
+ else
+ {
+ swap_ssa_operands (stmt, gimple_assign_rhs2_ptr (stmt),
+ gimple_assign_rhs3_ptr (stmt));
+ bool honor_nans = HONOR_NANS (TREE_OPERAND (cond, 0));
+ code = invert_tree_comparison (TREE_CODE (cond), honor_nans);
+ gcc_assert (code != ERROR_MARK);
+ TREE_SET_CODE (cond, code);
+ }
}
else
swap_ssa_operands (stmt, gimple_assign_rhs1_ptr (stmt),
@@ -446,6 +473,7 @@ again:
}
}
+ *swap = swapped;
return 0;
}
@@ -455,10 +483,17 @@ again:
true if they are, otherwise return false and indicate in *MATCHES
which stmts are not isomorphic to the first one. If MATCHES[0]
is false then this indicates the comparison could not be
- carried out or the stmts will never be vectorized by SLP. */
+ carried out or the stmts will never be vectorized by SLP.
+
+ Note COND_EXPR is possibly ismorphic to another one after swapping its
+ operands. Set SWAP[i] to 1 if stmt I is COND_EXPR and isomorphic to
+ the first stmt by swapping the two operands of comparison; set SWAP[i]
+ to 2 if stmt I is isormorphic to the first stmt by inverting the code
+ of comparison. Take A1 >= B1 ? X1 : Y1 as an exmple, it can be swapped
+ to (B1 <= A1 ? X1 : Y1); or be inverted to (A1 < B1) ? Y1 : X1. */
static bool
-vect_build_slp_tree_1 (vec_info *vinfo,
+vect_build_slp_tree_1 (vec_info *vinfo, unsigned char *swap,
vec<gimple *> stmts, unsigned int group_size,
unsigned nops, unsigned int *max_nunits,
bool *matches, bool *two_operators)
@@ -482,6 +517,7 @@ vect_build_slp_tree_1 (vec_info *vinfo,
/* For every stmt in NODE find its def stmt/s. */
FOR_EACH_VEC_ELT (stmts, i, stmt)
{
+ swap[i] = 0;
matches[i] = false;
if (dump_enabled_p ())
@@ -782,26 +818,44 @@ vect_build_slp_tree_1 (vec_info *vinfo,
return false;
}
- if (rhs_code == COND_EXPR)
- {
- tree cond_expr = gimple_assign_rhs1 (stmt);
+ if (rhs_code == COND_EXPR)
+ {
+ tree cond_expr = gimple_assign_rhs1 (stmt);
+ enum tree_code cond_code = TREE_CODE (cond_expr);
+ enum tree_code swap_code = ERROR_MARK;
+ enum tree_code invert_code = ERROR_MARK;
if (i == 0)
first_cond_code = TREE_CODE (cond_expr);
- else if (first_cond_code != TREE_CODE (cond_expr))
- {
- if (dump_enabled_p ())
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ else if (TREE_CODE_CLASS (cond_code) == tcc_comparison)
+ {
+ bool honor_nans = HONOR_NANS (TREE_OPERAND (cond_expr, 0));
+ swap_code = swap_tree_comparison (cond_code);
+ invert_code = invert_tree_comparison (cond_code, honor_nans);
+ }
+
+ if (first_cond_code == cond_code)
+ ;
+ /* Isomorphic can be achieved by swapping. */
+ else if (first_cond_code == swap_code)
+ swap[i] = 1;
+ /* Isomorphic can be achieved by inverting. */
+ else if (first_cond_code == invert_code)
+ swap[i] = 2;
+ else
+ {
+ if (dump_enabled_p ())
+ {
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
"Build SLP failed: different"
" operation");
- dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
+ dump_gimple_stmt (MSG_MISSED_OPTIMIZATION, TDF_SLIM,
stmt, 0);
- }
+ }
/* Mismatch. */
continue;
}
- }
+ }
}
matches[i] = true;
@@ -885,7 +939,8 @@ vect_build_slp_tree (vec_info *vinfo,
return NULL;
bool two_operators = false;
- if (!vect_build_slp_tree_1 (vinfo,
+ unsigned char *swap = XALLOCAVEC (unsigned char, group_size);
+ if (!vect_build_slp_tree_1 (vinfo, swap,
stmts, group_size, nops,
&this_max_nunits, matches, &two_operators))
return NULL;
@@ -905,18 +960,12 @@ vect_build_slp_tree (vec_info *vinfo,
slp_oprnd_info oprnd_info;
FOR_EACH_VEC_ELT (stmts, i, stmt)
{
- switch (vect_get_and_check_slp_defs (vinfo, stmt, i, &oprnds_info))
- {
- case 0:
- break;
- case -1:
- matches[0] = false;
- vect_free_oprnd_info (oprnds_info);
- return NULL;
- case 1:
- matches[i] = false;
- break;
- }
+ int res = vect_get_and_check_slp_defs (vinfo, &swap[i],
+ stmt, i, &oprnds_info);
+ if (res != 0)
+ matches[(res == -1) ? 0 : i] = false;
+ if (!matches[0])
+ break;
}
for (i = 0; i < group_size; ++i)
if (!matches[i])
@@ -1040,7 +1089,8 @@ vect_build_slp_tree (vec_info *vinfo,
operand order already. */
for (j = 0; j < group_size; ++j)
if (!matches[j]
- && STMT_VINFO_NUM_SLP_USES (vinfo_for_stmt (stmts[j])) != 0)
+ && (swap[j] != 0
+ || STMT_VINFO_NUM_SLP_USES (vinfo_for_stmt (stmts[j]))))
{
if (dump_enabled_p ())
{
@@ -1409,10 +1459,30 @@ vect_supported_load_permutation_p (slp_instance slp_instn)
SLP_TREE_LOAD_PERMUTATION (node).release ();
else
{
+ stmt_vec_info group_info
+ = vinfo_for_stmt (SLP_TREE_SCALAR_STMTS (node)[0]);
+ group_info = vinfo_for_stmt (GROUP_FIRST_ELEMENT (group_info));
+ unsigned nunits
+ = TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (group_info));
+ unsigned k, maxk = 0;
+ FOR_EACH_VEC_ELT (SLP_TREE_LOAD_PERMUTATION (node), j, k)
+ if (k > maxk)
+ maxk = k;
+ /* In BB vectorization we may not actually use a loaded vector
+ accessing elements in excess of GROUP_SIZE. */
+ if (maxk >= (GROUP_SIZE (group_info) & ~(nunits - 1)))
+ {
+ dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
+ "BB vectorization with gaps at the end of "
+ "a load is not supported\n");
+ return false;
+ }
+
/* Verify the permutation can be generated. */
vec<tree> tem;
+ unsigned n_perms;
if (!vect_transform_slp_perm_load (node, tem, NULL,
- 1, slp_instn, true))
+ 1, slp_instn, true, &n_perms))
{
dump_printf_loc (MSG_MISSED_OPTIMIZATION,
vect_location,
@@ -1425,11 +1495,13 @@ vect_supported_load_permutation_p (slp_instance slp_instn)
}
/* For loop vectorization verify we can generate the permutation. */
+ unsigned n_perms;
FOR_EACH_VEC_ELT (SLP_INSTANCE_LOADS (slp_instn), i, node)
if (node->load_permutation.exists ()
&& !vect_transform_slp_perm_load
(node, vNULL, NULL,
- SLP_INSTANCE_UNROLLING_FACTOR (slp_instn), slp_instn, true))
+ SLP_INSTANCE_UNROLLING_FACTOR (slp_instn), slp_instn, true,
+ &n_perms))
return false;
return true;
@@ -1498,14 +1570,38 @@ vect_analyze_slp_cost_1 (slp_instance instance, slp_tree node,
stmt = GROUP_FIRST_ELEMENT (stmt_info);
stmt_info = vinfo_for_stmt (stmt);
/* Record the cost for the permutation. */
- record_stmt_cost (body_cost_vec, ncopies_for_cost, vec_perm,
+ unsigned n_perms;
+ vect_transform_slp_perm_load (node, vNULL, NULL,
+ ncopies_for_cost, instance, true,
+ &n_perms);
+ record_stmt_cost (body_cost_vec, n_perms, vec_perm,
stmt_info, 0, vect_body);
- /* And adjust the number of loads performed. */
unsigned nunits
= TYPE_VECTOR_SUBPARTS (STMT_VINFO_VECTYPE (stmt_info));
- ncopies_for_cost
- = (GROUP_SIZE (stmt_info) - GROUP_GAP (stmt_info)
- + nunits - 1) / nunits;
+ /* And adjust the number of loads performed. This handles
+ redundancies as well as loads that are later dead. */
+ auto_sbitmap perm (GROUP_SIZE (stmt_info));
+ bitmap_clear (perm);
+ for (i = 0; i < SLP_TREE_LOAD_PERMUTATION (node).length (); ++i)
+ bitmap_set_bit (perm, SLP_TREE_LOAD_PERMUTATION (node)[i]);
+ ncopies_for_cost = 0;
+ bool load_seen = false;
+ for (i = 0; i < GROUP_SIZE (stmt_info); ++i)
+ {
+ if (i % nunits == 0)
+ {
+ if (load_seen)
+ ncopies_for_cost++;
+ load_seen = false;
+ }
+ if (bitmap_bit_p (perm, i))
+ load_seen = true;
+ }
+ if (load_seen)
+ ncopies_for_cost++;
+ gcc_assert (ncopies_for_cost
+ <= (GROUP_SIZE (stmt_info) - GROUP_GAP (stmt_info)
+ + nunits - 1) / nunits);
ncopies_for_cost *= SLP_INSTANCE_UNROLLING_FACTOR (instance);
}
/* Record the cost for the vector loads. */
@@ -3352,7 +3448,8 @@ vect_create_mask_and_perm (gimple *stmt,
bool
vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain,
gimple_stmt_iterator *gsi, int vf,
- slp_instance slp_node_instance, bool analyze_only)
+ slp_instance slp_node_instance, bool analyze_only,
+ unsigned *n_perms)
{
gimple *stmt = SLP_TREE_SCALAR_STMTS (node)[0];
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
@@ -3407,6 +3504,7 @@ vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain,
int first_vec_index = -1;
int second_vec_index = -1;
bool noop_p = true;
+ *n_perms = 0;
for (int j = 0; j < unroll_factor; j++)
{
@@ -3463,6 +3561,9 @@ vect_transform_slp_perm_load (slp_tree node, vec<tree> dr_chain,
return false;
}
+ if (! noop_p)
+ ++*n_perms;
+
if (!analyze_only)
{
tree mask_vec = NULL_TREE;
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 1d17156b0b6..b0b131d9245 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -1770,6 +1770,11 @@ get_group_load_store_type (gimple *stmt, tree vectype, bool slp,
" non-consecutive accesses\n");
return false;
}
+ /* If the access is aligned an overrun is fine. */
+ if (overrun_p
+ && aligned_access_p
+ (STMT_VINFO_DATA_REF (vinfo_for_stmt (first_stmt))))
+ overrun_p = false;
if (overrun_p && !can_overrun_p)
{
if (dump_enabled_p ())
@@ -1789,6 +1794,10 @@ get_group_load_store_type (gimple *stmt, tree vectype, bool slp,
/* If there is a gap at the end of the group then these optimizations
would access excess elements in the last iteration. */
bool would_overrun_p = (gap != 0);
+ /* If the access is aligned an overrun is fine. */
+ if (would_overrun_p
+ && aligned_access_p (STMT_VINFO_DATA_REF (stmt_info)))
+ would_overrun_p = false;
if (!STMT_VINFO_STRIDED_P (stmt_info)
&& (can_overrun_p || !would_overrun_p)
&& compare_step_with_zero (stmt) > 0)
@@ -2423,6 +2432,116 @@ vectorizable_mask_load_store (gimple *stmt, gimple_stmt_iterator *gsi,
return true;
}
+/* Check and perform vectorization of BUILT_IN_BSWAP{16,32,64}. */
+
+static bool
+vectorizable_bswap (gimple *stmt, gimple_stmt_iterator *gsi,
+ gimple **vec_stmt, slp_tree slp_node,
+ tree vectype_in, enum vect_def_type *dt)
+{
+ tree op, vectype;
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ unsigned ncopies, nunits;
+
+ op = gimple_call_arg (stmt, 0);
+ vectype = STMT_VINFO_VECTYPE (stmt_info);
+ nunits = TYPE_VECTOR_SUBPARTS (vectype);
+
+ /* Multiple types in SLP are handled by creating the appropriate number of
+ vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
+ case of SLP. */
+ if (slp_node)
+ ncopies = 1;
+ else
+ ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
+
+ gcc_assert (ncopies >= 1);
+
+ tree char_vectype = get_same_sized_vectype (char_type_node, vectype_in);
+ if (! char_vectype)
+ return false;
+
+ unsigned char *elts
+ = XALLOCAVEC (unsigned char, TYPE_VECTOR_SUBPARTS (char_vectype));
+ unsigned char *elt = elts;
+ unsigned word_bytes = TYPE_VECTOR_SUBPARTS (char_vectype) / nunits;
+ for (unsigned i = 0; i < nunits; ++i)
+ for (unsigned j = 0; j < word_bytes; ++j)
+ *elt++ = (i + 1) * word_bytes - j - 1;
+
+ if (! can_vec_perm_p (TYPE_MODE (char_vectype), false, elts))
+ return false;
+
+ if (! vec_stmt)
+ {
+ STMT_VINFO_TYPE (stmt_info) = call_vec_info_type;
+ if (dump_enabled_p ())
+ dump_printf_loc (MSG_NOTE, vect_location, "=== vectorizable_bswap ==="
+ "\n");
+ if (! PURE_SLP_STMT (stmt_info))
+ {
+ add_stmt_cost (stmt_info->vinfo->target_cost_data,
+ 1, vector_stmt, stmt_info, 0, vect_prologue);
+ add_stmt_cost (stmt_info->vinfo->target_cost_data,
+ ncopies, vec_perm, stmt_info, 0, vect_body);
+ }
+ return true;
+ }
+
+ tree *telts = XALLOCAVEC (tree, TYPE_VECTOR_SUBPARTS (char_vectype));
+ for (unsigned i = 0; i < TYPE_VECTOR_SUBPARTS (char_vectype); ++i)
+ telts[i] = build_int_cst (char_type_node, elts[i]);
+ tree bswap_vconst = build_vector (char_vectype, telts);
+
+ /* Transform. */
+ vec<tree> vec_oprnds = vNULL;
+ gimple *new_stmt = NULL;
+ stmt_vec_info prev_stmt_info = NULL;
+ for (unsigned j = 0; j < ncopies; j++)
+ {
+ /* Handle uses. */
+ if (j == 0)
+ vect_get_vec_defs (op, NULL, stmt, &vec_oprnds, NULL, slp_node, -1);
+ else
+ vect_get_vec_defs_for_stmt_copy (dt, &vec_oprnds, NULL);
+
+ /* Arguments are ready. create the new vector stmt. */
+ unsigned i;
+ tree vop;
+ FOR_EACH_VEC_ELT (vec_oprnds, i, vop)
+ {
+ tree tem = make_ssa_name (char_vectype);
+ new_stmt = gimple_build_assign (tem, build1 (VIEW_CONVERT_EXPR,
+ char_vectype, vop));
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ tree tem2 = make_ssa_name (char_vectype);
+ new_stmt = gimple_build_assign (tem2, VEC_PERM_EXPR,
+ tem, tem, bswap_vconst);
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ tem = make_ssa_name (vectype);
+ new_stmt = gimple_build_assign (tem, build1 (VIEW_CONVERT_EXPR,
+ vectype, tem2));
+ vect_finish_stmt_generation (stmt, new_stmt, gsi);
+ if (slp_node)
+ SLP_TREE_VEC_STMTS (slp_node).quick_push (new_stmt);
+ }
+
+ if (slp_node)
+ continue;
+
+ if (j == 0)
+ STMT_VINFO_VEC_STMT (stmt_info) = *vec_stmt = new_stmt;
+ else
+ STMT_VINFO_RELATED_STMT (prev_stmt_info) = new_stmt;
+
+ prev_stmt_info = vinfo_for_stmt (new_stmt);
+ }
+
+ vec_oprnds.release ();
+ return true;
+}
+
/* Return true if vector types VECTYPE_IN and VECTYPE_OUT have
integer elements and if we can narrow VECTYPE_IN to VECTYPE_OUT
in a single step. On success, store the binary pack code in
@@ -2649,6 +2768,12 @@ vectorizable_call (gimple *gs, gimple_stmt_iterator *gsi, gimple **vec_stmt,
{ 0, 1, 2, ... vf - 1 } vector. */
gcc_assert (nargs == 0);
}
+ else if (modifier == NONE
+ && (gimple_call_builtin_p (stmt, BUILT_IN_BSWAP16)
+ || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP32)
+ || gimple_call_builtin_p (stmt, BUILT_IN_BSWAP64)))
+ return vectorizable_bswap (stmt, gsi, vec_stmt, slp_node,
+ vectype_in, dt);
else
{
if (dump_enabled_p ())
@@ -6548,18 +6673,6 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (slp && SLP_TREE_LOAD_PERMUTATION (slp_node).exists ())
slp_perm = true;
- /* ??? The following is overly pessimistic (as well as the loop
- case above) in the case we can statically determine the excess
- elements loaded are within the bounds of a decl that is accessed.
- Likewise for BB vectorizations using masked loads is a possibility. */
- if (bb_vinfo && slp_perm && group_size % nunits != 0)
- {
- dump_printf_loc (MSG_MISSED_OPTIMIZATION, vect_location,
- "BB vectorization with gaps at the end of a load "
- "is not supported\n");
- return false;
- }
-
/* Invalidate assumptions made by dependence analysis when vectorization
on the unrolled body effectively re-orders stmts. */
if (!PURE_SLP_STMT (stmt_info)
@@ -6978,8 +7091,11 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
}
}
if (slp_perm)
- vect_transform_slp_perm_load (slp_node, dr_chain, gsi, vf,
- slp_node_instance, false);
+ {
+ unsigned n_perms;
+ vect_transform_slp_perm_load (slp_node, dr_chain, gsi, vf,
+ slp_node_instance, false, &n_perms);
+ }
return true;
}
@@ -7497,8 +7613,10 @@ vectorizable_load (gimple *stmt, gimple_stmt_iterator *gsi, gimple **vec_stmt,
if (slp_perm)
{
+ unsigned n_perms;
if (!vect_transform_slp_perm_load (slp_node, dr_chain, gsi, vf,
- slp_node_instance, false))
+ slp_node_instance, false,
+ &n_perms))
{
dr_chain.release ();
return false;
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 386654862b4..2a7cdfe27a5 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1166,7 +1166,7 @@ extern int vect_get_known_peeling_cost (loop_vec_info, int, int *,
extern void vect_free_slp_instance (slp_instance);
extern bool vect_transform_slp_perm_load (slp_tree, vec<tree> ,
gimple_stmt_iterator *, int,
- slp_instance, bool);
+ slp_instance, bool, unsigned *);
extern bool vect_slp_analyze_operations (vec<slp_instance> slp_instances,
void *);
extern bool vect_schedule_slp (vec_info *);
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index fcdb3417bb3..68fe2acb997 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -10650,18 +10650,17 @@ public:
}
virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block);
- void push_value_range (const_tree var, value_range *vr);
- value_range *pop_value_range (const_tree var);
+ void push_value_range (tree var, value_range *vr);
+ value_range *pop_value_range (tree var);
value_range *try_find_new_range (tree op, tree_code code, tree limit);
/* Cond_stack holds the old VR. */
- auto_vec<std::pair <const_tree, value_range*> > stack;
+ auto_vec<std::pair <tree, value_range*> > stack;
bitmap need_eh_cleanup;
auto_vec<gimple *> stmts_to_fixup;
auto_vec<gimple *> stmts_to_remove;
};
-
/* Find new range for OP such that (OP CODE LIMIT) is true. */
value_range *
@@ -10679,6 +10678,10 @@ evrp_dom_walker::try_find_new_range (tree op, tree_code code, tree limit)
PUSH old value in the stack with the old VR. */
if (vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)
{
+ if (old_vr->type == vr.type
+ && vrp_operand_equal_p (old_vr->min, vr.min)
+ && vrp_operand_equal_p (old_vr->max, vr.max))
+ return NULL;
value_range *new_vr = vrp_value_range_pool.allocate ();
*new_vr = vr;
return new_vr;
@@ -10696,7 +10699,10 @@ evrp_dom_walker::before_dom_children (basic_block bb)
edge_iterator ei;
edge e;
- push_value_range (NULL_TREE, NULL);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "Visiting BB%d\n", bb->index);
+
+ stack.safe_push (std::make_pair (NULL_TREE, (value_range *)NULL));
edge pred_e = NULL;
FOR_EACH_EDGE (e, ei, bb->preds)
@@ -10723,6 +10729,11 @@ evrp_dom_walker::before_dom_children (basic_block bb)
&& (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
|| POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Visiting controlling predicate ");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ }
/* Entering a new scope. Try to see if we can find a VR
here. */
tree op1 = gimple_cond_rhs (stmt);
@@ -10778,6 +10789,11 @@ evrp_dom_walker::before_dom_children (basic_block bb)
continue;
value_range vr_result = VR_INITIALIZER;
bool interesting = stmt_interesting_for_vrp (phi);
+ if (interesting && dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Visiting PHI node ");
+ print_gimple_stmt (dump_file, phi, 0, 0);
+ }
if (!has_unvisited_preds
&& interesting)
extract_range_from_phi_node (phi, &vr_result);
@@ -10814,6 +10830,12 @@ evrp_dom_walker::before_dom_children (basic_block bb)
bool was_noreturn = (is_gimple_call (stmt)
&& gimple_call_noreturn_p (stmt));
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "Visiting stmt ");
+ print_gimple_stmt (dump_file, stmt, 0, 0);
+ }
+
if (gcond *cond = dyn_cast <gcond *> (stmt))
{
vrp_visit_cond_stmt (cond, &taken_edge);
@@ -10825,6 +10847,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
gimple_cond_make_false (cond);
else
gcc_unreachable ();
+ update_stmt (stmt);
}
}
else if (stmt_interesting_for_vrp (stmt))
@@ -10873,6 +10896,55 @@ evrp_dom_walker::before_dom_children (basic_block bb)
else
set_defs_to_varying (stmt);
+ /* See if we can derive a range for any of STMT's operands. */
+ tree op;
+ ssa_op_iter i;
+ FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
+ {
+ tree value;
+ enum tree_code comp_code;
+
+ /* If OP is used in such a way that we can infer a value
+ range for it, and we don't find a previous assertion for
+ it, create a new assertion location node for OP. */
+ if (infer_value_range (stmt, op, &comp_code, &value))
+ {
+ /* If we are able to infer a nonzero value range for OP,
+ then walk backwards through the use-def chain to see if OP
+ was set via a typecast.
+ If so, then we can also infer a nonzero value range
+ for the operand of the NOP_EXPR. */
+ if (comp_code == NE_EXPR && integer_zerop (value))
+ {
+ tree t = op;
+ gimple *def_stmt = SSA_NAME_DEF_STMT (t);
+ while (is_gimple_assign (def_stmt)
+ && CONVERT_EXPR_CODE_P
+ (gimple_assign_rhs_code (def_stmt))
+ && TREE_CODE
+ (gimple_assign_rhs1 (def_stmt)) == SSA_NAME
+ && POINTER_TYPE_P
+ (TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
+ {
+ t = gimple_assign_rhs1 (def_stmt);
+ def_stmt = SSA_NAME_DEF_STMT (t);
+
+ /* Add VR when (T COMP_CODE value) condition is
+ true. */
+ value_range *op_range
+ = try_find_new_range (t, comp_code, value);
+ if (op_range)
+ push_value_range (t, op_range);
+ }
+ }
+ /* Add VR when (OP COMP_CODE value) condition is true. */
+ value_range *op_range = try_find_new_range (op,
+ comp_code, value);
+ if (op_range)
+ push_value_range (op, op_range);
+ }
+ }
+
/* Try folding stmts with the VR discovered. */
bool did_replace
= replace_uses_in (stmt, op_with_constant_singleton_value_range);
@@ -10938,42 +11010,44 @@ evrp_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
gcc_checking_assert (!stack.is_empty ());
while (stack.last ().first != NULL_TREE)
pop_value_range (stack.last ().first);
- pop_value_range (stack.last ().first);
+ stack.pop ();
}
/* Push the Value Range of VAR to the stack and update it with new VR. */
void
-evrp_dom_walker::push_value_range (const_tree var, value_range *vr)
+evrp_dom_walker::push_value_range (tree var, value_range *vr)
{
- if (vr != NULL)
+ if (SSA_NAME_VERSION (var) >= num_vr_values)
+ return;
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- unsigned ver = SSA_NAME_VERSION (var);
- gcc_checking_assert (vr_value);
- stack.safe_push (std::make_pair (var, vr_value[ver]));
-
- if (ver < num_vr_values)
- vr_value[ver] = vr;
+ fprintf (dump_file, "pushing new range for ");
+ print_generic_expr (dump_file, var, 0);
+ fprintf (dump_file, ": ");
+ dump_value_range (dump_file, vr);
+ fprintf (dump_file, "\n");
}
- else
- stack.safe_push (std::make_pair (var, vr));
+ stack.safe_push (std::make_pair (var, get_value_range (var)));
+ vr_value[SSA_NAME_VERSION (var)] = vr;
}
/* Pop the Value Range from the vrp_stack and update VAR with it. */
value_range *
-evrp_dom_walker::pop_value_range (const_tree var)
+evrp_dom_walker::pop_value_range (tree var)
{
value_range *vr = stack.last ().second;
- if (vr != NULL)
+ gcc_checking_assert (var == stack.last ().first);
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- unsigned ver = SSA_NAME_VERSION (var);
- gcc_checking_assert (var == stack.last ().first);
- gcc_checking_assert (vr_value);
-
- if (ver < num_vr_values)
- vr_value[ver] = vr;
+ fprintf (dump_file, "popping range for ");
+ print_generic_expr (dump_file, var, 0);
+ fprintf (dump_file, ", restoring ");
+ dump_value_range (dump_file, vr);
+ fprintf (dump_file, "\n");
}
+ vr_value[SSA_NAME_VERSION (var)] = vr;
stack.pop ();
return vr;
}
diff --git a/gcc/tree.c b/gcc/tree.c
index 56cc653c875..c155d56d2c5 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -6497,6 +6497,21 @@ set_type_quals (tree type, int type_quals)
TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
}
+/* Returns true iff CAND and BASE have equivalent language-specific
+ qualifiers. */
+
+bool
+check_lang_type (const_tree cand, const_tree base)
+{
+ if (lang_hooks.types.type_hash_eq == NULL)
+ return true;
+ /* type_hash_eq currently only applies to these types. */
+ if (TREE_CODE (cand) != FUNCTION_TYPE
+ && TREE_CODE (cand) != METHOD_TYPE)
+ return true;
+ return lang_hooks.types.type_hash_eq (cand, base);
+}
+
/* Returns true iff unqualified CAND and BASE are equivalent. */
bool
@@ -6517,7 +6532,8 @@ bool
check_qualified_type (const_tree cand, const_tree base, int type_quals)
{
return (TYPE_QUALS (cand) == type_quals
- && check_base_type (cand, base));
+ && check_base_type (cand, base)
+ && check_lang_type (cand, base));
}
/* Returns true iff CAND is equivalent to BASE with ALIGN. */
@@ -6532,7 +6548,8 @@ check_aligned_type (const_tree cand, const_tree base, unsigned int align)
/* Check alignment. */
&& TYPE_ALIGN (cand) == align
&& attribute_list_equal (TYPE_ATTRIBUTES (cand),
- TYPE_ATTRIBUTES (base)));
+ TYPE_ATTRIBUTES (base))
+ && check_lang_type (cand, base));
}
/* This function checks to see if TYPE matches the size one of the built-in
@@ -13272,12 +13289,10 @@ verify_type_variant (const_tree t, tree tv)
verify_variant_match (TYPE_SIZE);
if (TREE_CODE (TYPE_SIZE_UNIT (t)) != PLACEHOLDER_EXPR
&& TREE_CODE (TYPE_SIZE_UNIT (tv)) != PLACEHOLDER_EXPR
- && TYPE_SIZE_UNIT (t) != TYPE_SIZE_UNIT (tv)
- /* FIXME: ideally we should compare pointer equality, but java FE
- produce variants where size is INTEGER_CST of different type (int
- wrt size_type) during libjava biuld. */
- && !operand_equal_p (TYPE_SIZE_UNIT (t), TYPE_SIZE_UNIT (tv), 0))
+ && TYPE_SIZE_UNIT (t) != TYPE_SIZE_UNIT (tv))
{
+ gcc_assert (!operand_equal_p (TYPE_SIZE_UNIT (t),
+ TYPE_SIZE_UNIT (tv), 0));
error ("type variant has different TYPE_SIZE_UNIT");
debug_tree (tv);
error ("type variant's TYPE_SIZE_UNIT");
diff --git a/gcc/tree.h b/gcc/tree.h
index c494f23c90d..6a98b6ee0b6 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1757,6 +1757,10 @@ extern void protected_set_expr_location (tree, location_t);
/* True if BLOCK has the same ranges as its BLOCK_SUPERCONTEXT. */
#define BLOCK_SAME_RANGE(NODE) (BLOCK_CHECK (NODE)->base.u.bits.nameless_flag)
+/* True if BLOCK appears in cold section. */
+#define BLOCK_IN_COLD_SECTION_P(NODE) \
+ (BLOCK_CHECK (NODE)->base.u.bits.atomic_flag)
+
/* An index number for this block. These values are not guaranteed to
be unique across functions -- whether or not they are depends on
the debugging output format in use. */
@@ -4210,6 +4214,11 @@ extern tree merge_dllimport_decl_attributes (tree, tree);
/* Handle a "dllimport" or "dllexport" attribute. */
extern tree handle_dll_attribute (tree *, tree, tree, int, bool *);
+/* Returns true iff CAND and BASE have equivalent language-specific
+ qualifiers. */
+
+extern bool check_lang_type (const_tree cand, const_tree base);
+
/* Returns true iff unqualified CAND and BASE are equivalent. */
extern bool check_base_type (const_tree cand, const_tree base);
diff --git a/gcc/value-prof.h b/gcc/value-prof.h
index 07e2b3b5840..02220acb206 100644
--- a/gcc/value-prof.h
+++ b/gcc/value-prof.h
@@ -96,15 +96,14 @@ bool check_ic_target (gcall *, struct cgraph_node *);
/* In tree-profile.c. */
-extern void gimple_init_edge_profiler (void);
+extern void gimple_init_gcov_profiler (void);
extern void gimple_gen_edge_profiler (int, edge);
extern void gimple_gen_interval_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_pow2_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_one_value_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_ic_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_ic_func_profiler (void);
-extern void gimple_gen_time_profiler (unsigned, unsigned,
- gimple_stmt_iterator &);
+extern void gimple_gen_time_profiler (unsigned, unsigned);
extern void gimple_gen_average_profiler (histogram_value, unsigned, unsigned);
extern void gimple_gen_ior_profiler (histogram_value, unsigned, unsigned);
extern void stream_out_histogram_value (struct output_block *, histogram_value);