From 1d9fec7937f45dde5e04cac966a2d9a12f2fc15a Mon Sep 17 00:00:00 2001 From: Yiran Wang Date: Tue, 23 Jun 2015 15:33:17 -0700 Subject: Synchronize with google/gcc-4_9 to r224707 (from r214835) Change-Id: I3d6f06fc613c8f8b6a82143dc44b7338483aac5d --- gcc-4.9/ChangeLog | 11 + gcc-4.9/Makefile.def | 4 + gcc-4.9/Makefile.in | 32 + gcc-4.9/boehm-gc/ChangeLog | 4 + gcc-4.9/config/ChangeLog | 4 + gcc-4.9/configure | 49 + gcc-4.9/configure.ac | 3 + gcc-4.9/contrib/ChangeLog | 13 + gcc-4.9/contrib/config-list.mk | 2 +- gcc-4.9/contrib/reghunt/ChangeLog | 4 + gcc-4.9/contrib/regression/ChangeLog | 4 + .../aarch64-grtev4-linux-gnu.xfail | 7 +- .../powerpc64le-grtev4-linux-gnu.xfail | 7 +- .../x86_64-grtev4-linux-gnu.xfail | 20 +- gcc-4.9/fixincludes/ChangeLog | 4 + gcc-4.9/gcc/ChangeLog | 1805 +++++++++++++++++++- gcc-4.9/gcc/DATESTAMP | 2 +- gcc-4.9/gcc/Makefile.in | 6 +- gcc-4.9/gcc/ada/ChangeLog | 48 + gcc-4.9/gcc/ada/back_end.adb | 3 +- gcc-4.9/gcc/ada/gcc-interface/Makefile.in | 9 +- gcc-4.9/gcc/ada/gcc-interface/decl.c | 37 +- gcc-4.9/gcc/ada/gcc-interface/trans.c | 6 +- gcc-4.9/gcc/ada/gcc-interface/utils.c | 3 +- gcc-4.9/gcc/ada/gcc-interface/utils2.c | 10 +- gcc-4.9/gcc/ada/mlib-utl.adb | 4 + gcc-4.9/gcc/ada/uintp.adb | 16 - gcc-4.9/gcc/ada/uintp.ads | 40 +- gcc-4.9/gcc/alias.c | 144 +- gcc-4.9/gcc/asan.c | 830 +++++---- gcc-4.9/gcc/auto-profile.c | 1384 ++++++++------- gcc-4.9/gcc/c-family/ChangeLog | 26 + gcc-4.9/gcc/c-family/c-common.c | 39 +- gcc-4.9/gcc/c-family/c-cppbuiltin.c | 48 + gcc-4.9/gcc/c-family/c-ubsan.c | 11 +- gcc-4.9/gcc/c/ChangeLog | 19 + gcc-4.9/gcc/c/c-parser.c | 10 +- gcc-4.9/gcc/c/c-typeck.c | 134 +- gcc-4.9/gcc/calls.c | 12 + gcc-4.9/gcc/cfg-flags.def | 8 +- gcc-4.9/gcc/cfgcleanup.c | 2 +- gcc-4.9/gcc/cfgloop.c | 3 +- gcc-4.9/gcc/cfgrtl.c | 36 +- gcc-4.9/gcc/cgraph.c | 7 + gcc-4.9/gcc/cgraph.h | 1 + gcc-4.9/gcc/cgraphbuild.c | 48 +- gcc-4.9/gcc/cgraphclones.c | 26 + gcc-4.9/gcc/cgraphunit.c | 15 +- gcc-4.9/gcc/collect2.c | 6 + gcc-4.9/gcc/combine.c | 4 +- gcc-4.9/gcc/common.opt | 47 +- gcc-4.9/gcc/config.gcc | 64 +- gcc-4.9/gcc/config.in | 12 + gcc-4.9/gcc/config/aarch64/aarch64-builtins.c | 154 ++ gcc-4.9/gcc/config/aarch64/aarch64-elf-raw.h | 8 + gcc-4.9/gcc/config/aarch64/aarch64-linux.h | 11 +- gcc-4.9/gcc/config/aarch64/aarch64-protos.h | 1 + gcc-4.9/gcc/config/aarch64/aarch64-simd.md | 39 +- gcc-4.9/gcc/config/aarch64/aarch64.c | 12 +- gcc-4.9/gcc/config/aarch64/aarch64.md | 55 +- gcc-4.9/gcc/config/aarch64/arm_neon.h | 494 +++--- gcc-4.9/gcc/config/alpha/alpha.c | 6 - gcc-4.9/gcc/config/alpha/alpha.md | 63 +- gcc-4.9/gcc/config/arm/arm-protos.h | 3 + gcc-4.9/gcc/config/arm/arm.c | 88 +- gcc-4.9/gcc/config/arm/arm.h | 11 +- gcc-4.9/gcc/config/arm/arm.md | 64 +- gcc-4.9/gcc/config/arm/constraints.md | 11 +- gcc-4.9/gcc/config/arm/linux-grte.h | 27 - gcc-4.9/gcc/config/arm/t-aprofile | 3 + gcc-4.9/gcc/config/avr/avr-dimode.md | 7 + gcc-4.9/gcc/config/avr/avr-fixed.md | 41 +- gcc-4.9/gcc/config/avr/avr-protos.h | 9 + gcc-4.9/gcc/config/avr/avr.c | 109 ++ gcc-4.9/gcc/config/avr/avr.md | 155 +- gcc-4.9/gcc/config/darwin-c.c | 25 +- gcc-4.9/gcc/config/darwin-driver.c | 35 +- gcc-4.9/gcc/config/gnu-user.h | 7 +- gcc-4.9/gcc/config/i386/i386.c | 349 ++-- gcc-4.9/gcc/config/i386/i386.md | 62 +- gcc-4.9/gcc/config/i386/i386.opt | 8 - gcc-4.9/gcc/config/i386/linux.h | 15 - gcc-4.9/gcc/config/i386/linux64.h | 9 - gcc-4.9/gcc/config/i386/mmx.md | 36 +- gcc-4.9/gcc/config/i386/x86-tune.def | 8 +- gcc-4.9/gcc/config/ia64/ia64.c | 5 - gcc-4.9/gcc/config/linux-grte.h | 41 - gcc-4.9/gcc/config/linux.c | 2 - gcc-4.9/gcc/config/msp430/msp430.md | 6 +- gcc-4.9/gcc/config/nios2/nios2.c | 15 + gcc-4.9/gcc/config/pa/pa.c | 26 +- gcc-4.9/gcc/config/pa/pa.md | 25 +- gcc-4.9/gcc/config/pa/predicates.md | 21 +- gcc-4.9/gcc/config/rs6000/altivec.h | 6 + gcc-4.9/gcc/config/rs6000/altivec.md | 56 +- gcc-4.9/gcc/config/rs6000/darwin.h | 6 +- gcc-4.9/gcc/config/rs6000/linux-grte.h | 41 - gcc-4.9/gcc/config/rs6000/predicates.md | 75 +- gcc-4.9/gcc/config/rs6000/rs6000-builtin.def | 10 + gcc-4.9/gcc/config/rs6000/rs6000-c.c | 147 +- gcc-4.9/gcc/config/rs6000/rs6000-protos.h | 5 +- gcc-4.9/gcc/config/rs6000/rs6000.c | 1367 +++++++++++++-- gcc-4.9/gcc/config/rs6000/rs6000.md | 88 +- gcc-4.9/gcc/config/rs6000/rs6000.opt | 4 + gcc-4.9/gcc/config/rs6000/rtems.h | 3 +- gcc-4.9/gcc/config/rs6000/sysv4.h | 6 - gcc-4.9/gcc/config/rs6000/t-rtems | 73 +- gcc-4.9/gcc/config/rs6000/vsx.md | 227 ++- gcc-4.9/gcc/config/rs6000/xcoff.h | 7 +- gcc-4.9/gcc/config/rx/rx.c | 2 +- gcc-4.9/gcc/config/rx/rx.h | 6 +- gcc-4.9/gcc/config/s390/s390.c | 19 +- gcc-4.9/gcc/config/s390/s390.md | 2 +- gcc-4.9/gcc/config/sh/predicates.md | 2 +- gcc-4.9/gcc/config/sh/sh-mem.cc | 24 +- gcc-4.9/gcc/config/sh/sh.c | 2 +- gcc-4.9/gcc/config/sh/sh.md | 47 +- gcc-4.9/gcc/config/sh/sh_optimize_sett_clrt.cc | 24 +- gcc-4.9/gcc/config/sh/sh_treg_combine.cc | 49 +- gcc-4.9/gcc/config/sh/sync.md | 18 +- gcc-4.9/gcc/config/sparc/leon.md | 14 +- gcc-4.9/gcc/config/sparc/linux.h | 6 - gcc-4.9/gcc/config/sparc/linux64.h | 6 - gcc-4.9/gcc/config/sparc/sparc-opts.h | 1 + gcc-4.9/gcc/config/sparc/sparc.c | 40 +- gcc-4.9/gcc/config/sparc/sparc.h | 51 +- gcc-4.9/gcc/config/sparc/sparc.md | 1 + gcc-4.9/gcc/config/sparc/sparc.opt | 3 + gcc-4.9/gcc/config/sparc/t-rtems | 13 +- gcc-4.9/gcc/configure | 91 +- gcc-4.9/gcc/configure.ac | 66 + gcc-4.9/gcc/convert.c | 26 + gcc-4.9/gcc/coverage.c | 162 +- gcc-4.9/gcc/cp/ChangeLog | 131 ++ gcc-4.9/gcc/cp/call.c | 6 +- gcc-4.9/gcc/cp/cp-tree.h | 24 +- gcc-4.9/gcc/cp/decl.c | 63 +- gcc-4.9/gcc/cp/decl2.c | 142 +- gcc-4.9/gcc/cp/mangle.c | 5 +- gcc-4.9/gcc/cp/method.c | 1 + gcc-4.9/gcc/cp/parser.c | 9 +- gcc-4.9/gcc/cp/pt.c | 73 +- gcc-4.9/gcc/cp/semantics.c | 27 +- gcc-4.9/gcc/cp/typeck.c | 20 + gcc-4.9/gcc/cppbuiltin.c | 3 + gcc-4.9/gcc/cprop.c | 7 +- gcc-4.9/gcc/dbgcnt.def | 1 + gcc-4.9/gcc/df.h | 28 +- gcc-4.9/gcc/doc/cpp.texi | 4 +- gcc-4.9/gcc/doc/extend.texi | 145 +- gcc-4.9/gcc/doc/gcov-tool.texi | 46 +- gcc-4.9/gcc/doc/install.texi | 4 + gcc-4.9/gcc/doc/invoke.texi | 105 +- gcc-4.9/gcc/doc/md.texi | 6 +- gcc-4.9/gcc/doc/sourcebuild.texi | 3 + gcc-4.9/gcc/doc/tm.texi | 48 +- gcc-4.9/gcc/doc/tm.texi.in | 27 +- gcc-4.9/gcc/dse.c | 8 + gcc-4.9/gcc/dwarf2out.c | 489 +++++- gcc-4.9/gcc/expmed.c | 32 +- gcc-4.9/gcc/expr.c | 32 +- gcc-4.9/gcc/final.c | 43 +- gcc-4.9/gcc/flag-types.h | 24 +- gcc-4.9/gcc/fold-const.c | 5 +- gcc-4.9/gcc/fortran/ChangeLog | 65 + gcc-4.9/gcc/fortran/interface.c | 95 +- gcc-4.9/gcc/fortran/module.c | 5 +- gcc-4.9/gcc/fortran/resolve.c | 14 +- gcc-4.9/gcc/fortran/trans-array.c | 7 + gcc-4.9/gcc/fortran/trans-decl.c | 5 +- gcc-4.9/gcc/fortran/trans-expr.c | 2 +- gcc-4.9/gcc/fortran/trans-openmp.c | 22 + gcc-4.9/gcc/function.c | 708 +++++++- gcc-4.9/gcc/function.h | 12 + gcc-4.9/gcc/gcc.c | 31 +- gcc-4.9/gcc/gcov-dump.c | 63 +- gcc-4.9/gcc/gcov-io.c | 195 ++- gcc-4.9/gcc/gcov-io.h | 43 +- gcc-4.9/gcc/gcov-tool.c | 123 +- gcc-4.9/gcc/gcov.c | 15 + gcc-4.9/gcc/gimple-fold.c | 3 +- gcc-4.9/gcc/gimple.c | 9 +- gcc-4.9/gcc/go/ChangeLog | 4 + gcc-4.9/gcc/go/gofrontend/expressions.cc | 7 +- gcc-4.9/gcc/go/gofrontend/gogo.cc | 5 +- gcc-4.9/gcc/go/gofrontend/import-archive.cc | 9 + gcc-4.9/gcc/graphite-clast-to-gimple.c | 5 + gcc-4.9/gcc/graphite-interchange.c | 6 + gcc-4.9/gcc/graphite-optimize-isl.c | 8 + gcc-4.9/gcc/graphite-poly.c | 4 + gcc-4.9/gcc/graphite-sese-to-poly.c | 5 + gcc-4.9/gcc/haifa-sched.c | 2 +- gcc-4.9/gcc/ifcvt.c | 10 +- gcc-4.9/gcc/internal-fn.c | 28 +- gcc-4.9/gcc/internal-fn.def | 40 +- gcc-4.9/gcc/internal-fn.h | 16 +- gcc-4.9/gcc/ipa-cp.c | 26 +- gcc-4.9/gcc/ipa-devirt.c | 11 +- gcc-4.9/gcc/ipa-inline-analysis.c | 16 +- gcc-4.9/gcc/ipa-inline-transform.c | 2 +- gcc-4.9/gcc/ipa-inline.c | 26 +- gcc-4.9/gcc/ipa-profile.c | 3 +- gcc-4.9/gcc/ipa-pure-const.c | 2 +- gcc-4.9/gcc/ipa-split.c | 41 +- gcc-4.9/gcc/ipa.c | 21 +- gcc-4.9/gcc/ira-build.c | 480 ++++++ gcc-4.9/gcc/ira-color.c | 223 ++- gcc-4.9/gcc/ira-conflicts.c | 10 +- gcc-4.9/gcc/ira-int.h | 7 + gcc-4.9/gcc/ira-lives.c | 71 + gcc-4.9/gcc/ira.c | 128 +- gcc-4.9/gcc/java/ChangeLog | 4 + gcc-4.9/gcc/l-ipo.c | 35 +- gcc-4.9/gcc/lra-assigns.c | 71 +- gcc-4.9/gcc/lra-constraints.c | 9 - gcc-4.9/gcc/lra-int.h | 12 +- gcc-4.9/gcc/lra.c | 6 +- gcc-4.9/gcc/lto-cgraph.c | 3 +- gcc-4.9/gcc/lto-streamer-out.c | 5 +- gcc-4.9/gcc/lto/ChangeLog | 4 + gcc-4.9/gcc/objc/ChangeLog | 4 + gcc-4.9/gcc/objcp/ChangeLog | 4 + gcc-4.9/gcc/omp-low.c | 140 +- gcc-4.9/gcc/opts-global.c | 70 + gcc-4.9/gcc/opts.c | 91 +- gcc-4.9/gcc/opts.h | 1 + gcc-4.9/gcc/params.def | 48 +- gcc-4.9/gcc/params.h | 4 + gcc-4.9/gcc/po/ChangeLog | 4 + gcc-4.9/gcc/postreload.c | 8 +- gcc-4.9/gcc/recog.c | 2 + gcc-4.9/gcc/ree.c | 131 +- gcc-4.9/gcc/regcprop.c | 12 +- gcc-4.9/gcc/regrename.c | 3 +- gcc-4.9/gcc/reload.c | 1 + gcc-4.9/gcc/rtlanal.c | 13 +- gcc-4.9/gcc/sanitizer.def | 32 +- gcc-4.9/gcc/sched-deps.c | 25 +- gcc-4.9/gcc/simplify-got.c | 2 +- gcc-4.9/gcc/stor-layout.c | 7 +- gcc-4.9/gcc/system.h | 1 + gcc-4.9/gcc/target.def | 37 +- gcc-4.9/gcc/targhooks.c | 6 + gcc-4.9/gcc/targhooks.h | 1 + gcc-4.9/gcc/testsuite/ChangeLog | 871 ++++++++++ .../testsuite/c-c++-common/asan/asan-interface-1.c | 14 + .../gcc/testsuite/c-c++-common/asan/bitfield-1.c | 25 + .../gcc/testsuite/c-c++-common/asan/bitfield-2.c | 25 + .../gcc/testsuite/c-c++-common/asan/bitfield-3.c | 25 + .../gcc/testsuite/c-c++-common/asan/bitfield-4.c | 25 + gcc-4.9/gcc/testsuite/c-c++-common/asan/inc.c | 4 +- .../c-c++-common/asan/instrument-with-calls-1.c | 10 + .../c-c++-common/asan/instrument-with-calls-2.c | 16 + .../gcc/testsuite/c-c++-common/asan/misalign-1.c | 42 + .../gcc/testsuite/c-c++-common/asan/misalign-2.c | 42 + .../asan/no-redundant-instrumentation-1.c | 24 +- .../asan/no-redundant-instrumentation-2.c | 9 +- .../asan/no-redundant-instrumentation-3.c | 10 +- .../asan/no-redundant-instrumentation-4.c | 12 +- .../asan/no-redundant-instrumentation-5.c | 13 +- .../asan/no-redundant-instrumentation-6.c | 14 +- .../asan/no-redundant-instrumentation-7.c | 12 +- .../asan/no-redundant-instrumentation-8.c | 14 +- .../asan/no-redundant-instrumentation-9.c | 13 + gcc-4.9/gcc/testsuite/c-c++-common/asan/pr61530.c | 17 + gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62089.c | 38 + .../gcc/testsuite/c-c++-common/asan/pr62140-1.c | 10 + .../gcc/testsuite/c-c++-common/asan/pr62140-2.c | 11 + gcc-4.9/gcc/testsuite/c-c++-common/asan/pr63638.c | 20 + .../c-c++-common/asan/strlen-overflow-1.c | 30 + .../gcc/testsuite/c-c++-common/gomp/pr60823-4.c | 7 + gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr61200.c | 13 + gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr63249.c | 16 + gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr63328.c | 5 + gcc-4.9/gcc/testsuite/c-c++-common/pr56493.c | 16 + gcc-4.9/gcc/testsuite/c-c++-common/pr61553.c | 8 + .../gcc/testsuite/c-c++-common/tsan/atomic_stack.c | 8 +- .../gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c | 9 +- .../gcc/testsuite/c-c++-common/tsan/mutexset1.c | 9 +- .../testsuite/c-c++-common/tsan/race_on_barrier.c | 10 +- .../testsuite/c-c++-common/tsan/race_on_mutex.c | 12 +- .../testsuite/c-c++-common/tsan/race_on_mutex2.c | 11 +- .../gcc/testsuite/c-c++-common/tsan/simple_race.c | 11 +- .../gcc/testsuite/c-c++-common/tsan/simple_stack.c | 25 +- .../gcc/testsuite/c-c++-common/tsan/sleep_sync.c | 6 + .../gcc/testsuite/c-c++-common/tsan/tiny_race.c | 8 +- gcc-4.9/gcc/testsuite/c-c++-common/tsan/tls_race.c | 8 +- .../gcc/testsuite/c-c++-common/tsan/tsan_barrier.h | 14 + .../c-c++-common/tsan/write_in_reader_lock.c | 8 +- .../testsuite/c-c++-common/ubsan/overflow-sub-3.c | 34 + .../gcc/testsuite/c-c++-common/ubsan/undefined-2.c | 26 + gcc-4.9/gcc/testsuite/g++.dg/abi/aarch64_guard1.C | 3 +- gcc-4.9/gcc/testsuite/g++.dg/abi/no-weak1.C | 13 + gcc-4.9/gcc/testsuite/g++.dg/abi/spec1.C | 4 + gcc-4.9/gcc/testsuite/g++.dg/asan/pr62017.C | 17 + .../g++.dg/compat/struct-layout-1_generate.c | 4 +- gcc-4.9/gcc/testsuite/g++.dg/cpp0x/alias-decl-44.C | 43 + .../gcc/testsuite/g++.dg/cpp0x/constexpr-63241.C | 13 + .../gcc/testsuite/g++.dg/cpp0x/constexpr-63265.C | 19 + .../testsuite/g++.dg/cpp0x/constexpr-initlist8.C | 7 + gcc-4.9/gcc/testsuite/g++.dg/cpp0x/deleted9.C | 31 + gcc-4.9/gcc/testsuite/g++.dg/cpp0x/initlist89.C | 4 + .../g++.dg/cpp0x/lambda/lambda-template14.C | 11 + gcc-4.9/gcc/testsuite/g++.dg/cpp0x/ref-qual16.C | 12 + gcc-4.9/gcc/testsuite/g++.dg/cpp0x/variadic161.C | 51 + gcc-4.9/gcc/testsuite/g++.dg/cpp0x/variadic162.C | 14 + .../gcc/testsuite/g++.dg/cpp1y/feat-cxx11-neg.C | 40 + gcc-4.9/gcc/testsuite/g++.dg/cpp1y/feat-cxx11.C | 81 + gcc-4.9/gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C | 231 +++ .../gcc/testsuite/g++.dg/cpp1y/feat-cxx98-neg.C | 99 ++ gcc-4.9/gcc/testsuite/g++.dg/cpp1y/feat-cxx98.C | 9 + gcc-4.9/gcc/testsuite/g++.dg/cpp1y/paren1.C | 31 + gcc-4.9/gcc/testsuite/g++.dg/cpp1y/phoobhar.h | 16 + gcc-4.9/gcc/testsuite/g++.dg/cpp1y/pr57644.C | 13 + gcc-4.9/gcc/testsuite/g++.dg/ext/altivec-2.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ext/stmtexpr16.C | 10 + gcc-4.9/gcc/testsuite/g++.dg/gomp/pr63249.C | 35 + gcc-4.9/gcc/testsuite/g++.dg/init/const9.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-1.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-10.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-11.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-12.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-13.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-14.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-15.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-16.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-17.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-18.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-19.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-2.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-20.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-21.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-22.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-23.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-24.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-25.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-26.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-27.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-28.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-28a.C | 15 + gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-29.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-3.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-30.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-31.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-39.C | 5 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-4.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-40.C | 21 + gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-5.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-6.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-7.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-9.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-c-1.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-c-2.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-c-3.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-c-4.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-c-5.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-c-6.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-c-7.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-c-8.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-d-1.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-g-1.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/imm-devirt-1.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/imm-devirt-2.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/ivinline-1.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/ivinline-2.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/ivinline-3.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/ivinline-4.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/ivinline-5.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/ivinline-7.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/ivinline-8.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/ivinline-9.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/pr60600.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/pr60640-4.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/ipa/pr61654.C | 40 + gcc-4.9/gcc/testsuite/g++.dg/ipa/pr62015.C | 55 + gcc-4.9/gcc/testsuite/g++.dg/ipa/pr63306.C | 14 + gcc-4.9/gcc/testsuite/g++.dg/ipa/pr63838.C | 56 + gcc-4.9/gcc/testsuite/g++.dg/ipa/pr64068.C | 49 + .../gcc/testsuite/g++.dg/ipa/type-inheritance-1.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/lto/pr62026.C | 22 + gcc-4.9/gcc/testsuite/g++.dg/opt/devirt1.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/opt/devirt2.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/opt/devirt3.C | 2 +- gcc-4.9/gcc/testsuite/g++.dg/opt/devirt4.C | 7 +- gcc-4.9/gcc/testsuite/g++.dg/opt/devirt5.C | 19 + gcc-4.9/gcc/testsuite/g++.dg/opt/flifetime-dse1.C | 23 + gcc-4.9/gcc/testsuite/g++.dg/pr54442.C | 12 + gcc-4.9/gcc/testsuite/g++.dg/pr62079.C | 78 + gcc-4.9/gcc/testsuite/g++.dg/pr64037.C | 27 + gcc-4.9/gcc/testsuite/g++.dg/template/friend56.C | 13 + .../testsuite/g++.dg/template/non-dependent14.C | 7 + gcc-4.9/gcc/testsuite/g++.dg/template/offsetof3.C | 18 + gcc-4.9/gcc/testsuite/g++.dg/template/ptrmem29.C | 10 + gcc-4.9/gcc/testsuite/g++.dg/template/ref9.C | 15 + gcc-4.9/gcc/testsuite/g++.dg/template/spec38.C | 6 + gcc-4.9/gcc/testsuite/g++.dg/torture/pr62121.C | 12 + gcc-4.9/gcc/testsuite/g++.dg/torture/pr62175.C | 36 + gcc-4.9/gcc/testsuite/g++.dg/torture/pr63632.C | 5 + .../g++.dg/tree-prof/func_reorder_gold_plugin_1.C | 2 +- .../testsuite/g++.dg/tree-prof/lipo/buildinfo.txt | 1 + .../testsuite/g++.dg/tree-prof/lipo/comdat_fixup.h | 5 + .../g++.dg/tree-prof/lipo/comdat_fixup_0.C | 9 + .../g++.dg/tree-prof/lipo/comdat_fixup_1.C | 7 + .../g++.dg/tree-prof/lipo/comdat_fixup_2.C | 7 + .../g++.dg/tree-prof/lipo/indir-call-prof_0.C | 2 +- .../testsuite/g++.dg/tree-prof/lipo/static1_0.C | 48 + .../testsuite/g++.dg/tree-prof/lipo/static1_1.C | 14 + .../testsuite/g++.dg/tree-prof/lipo/static1_2.C | 14 + gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/tls.h | 16 + gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/tls2.h | 15 + .../gcc/testsuite/g++.dg/tree-prof/lipo/tls2_0.C | 10 + .../gcc/testsuite/g++.dg/tree-prof/lipo/tls2_1.C | 31 + .../gcc/testsuite/g++.dg/tree-prof/lipo/tls_0.C | 10 + .../gcc/testsuite/g++.dg/tree-prof/lipo/tls_1.C | 38 + .../testsuite/g++.dg/tree-prof/partition_patch.C | 19 + gcc-4.9/gcc/testsuite/g++.dg/tree-prof/pr63581.C | 91 + gcc-4.9/gcc/testsuite/g++.dg/tree-ssa/pr63841.C | 35 + gcc-4.9/gcc/testsuite/g++.dg/tsan/atomic_free.C | 9 +- gcc-4.9/gcc/testsuite/g++.dg/tsan/atomic_free2.C | 9 +- gcc-4.9/gcc/testsuite/g++.dg/tsan/cond_race.C | 9 +- gcc-4.9/gcc/testsuite/g++.dg/tsan/tsan_barrier.h | 14 + gcc-4.9/gcc/testsuite/g++.dg/ubsan/pr61272.C | 24 + gcc-4.9/gcc/testsuite/g++.dg/ubsan/pr63913.C | 12 + gcc-4.9/gcc/testsuite/g++.dg/warn/Wunused-parm-6.C | 8 + gcc-4.9/gcc/testsuite/g++.dg/warn/Wunused-var-22.C | 12 + .../gcc/testsuite/g++.dg/warn/register-parm-1.C | 9 + .../gcc/testsuite/gcc.c-torture/compile/pr62312.c | 23 + .../gcc/testsuite/gcc.c-torture/compile/pr63282.c | 13 + .../gcc/testsuite/gcc.c-torture/compile/pr64067.c | 10 + .../gcc/testsuite/gcc.c-torture/compile/pr64269.c | 9 + .../gcc/testsuite/gcc.c-torture/execute/pr63209.c | 27 + .../gcc/testsuite/gcc.c-torture/execute/pr63302.c | 60 + .../gcc/testsuite/gcc.c-torture/execute/pr63659.c | 29 + gcc-4.9/gcc/testsuite/gcc.dg/20141029-1.c | 28 + gcc-4.9/gcc/testsuite/gcc.dg/darwin-minversion-1.c | 3 +- gcc-4.9/gcc/testsuite/gcc.dg/darwin-minversion-2.c | 3 +- gcc-4.9/gcc/testsuite/gcc.dg/darwin-minversion-3.c | 3 +- gcc-4.9/gcc/testsuite/gcc.dg/darwin-minversion-4.c | 12 + gcc-4.9/gcc/testsuite/gcc.dg/fpomit-1.c | 25 + gcc-4.9/gcc/testsuite/gcc.dg/fpomit-2.c | 41 + gcc-4.9/gcc/testsuite/gcc.dg/fpomit-3.c | 56 + gcc-4.9/gcc/testsuite/gcc.dg/fpomit-4.c | 64 + gcc-4.9/gcc/testsuite/gcc.dg/fpomit-5.c | 59 + gcc-4.9/gcc/testsuite/gcc.dg/fpomit-6.c | 50 + gcc-4.9/gcc/testsuite/gcc.dg/fpomit-7.c | 50 + gcc-4.9/gcc/testsuite/gcc.dg/fpomit-8.c | 84 + gcc-4.9/gcc/testsuite/gcc.dg/fpomit-9.c | 23 + gcc-4.9/gcc/testsuite/gcc.dg/ipa/PR64559.c | 39 + gcc-4.9/gcc/testsuite/gcc.dg/ipa/pr61986.c | 48 + gcc-4.9/gcc/testsuite/gcc.dg/ipa/pr63551.c | 33 + gcc-4.9/gcc/testsuite/gcc.dg/ipa/pr64041.c | 64 + gcc-4.9/gcc/testsuite/gcc.dg/option_no-pie.c | 7 + gcc-4.9/gcc/testsuite/gcc.dg/pr51879-12.c | 4 +- gcc-4.9/gcc/testsuite/gcc.dg/pr52769.c | 24 + gcc-4.9/gcc/testsuite/gcc.dg/pr56724-1.c | 33 + gcc-4.9/gcc/testsuite/gcc.dg/pr56724-2.c | 31 + gcc-4.9/gcc/testsuite/gcc.dg/pr61053.c | 8 +- gcc-4.9/gcc/testsuite/gcc.dg/pr62167-run.c | 47 + gcc-4.9/gcc/testsuite/gcc.dg/pr62167.c | 50 + gcc-4.9/gcc/testsuite/gcc.dg/pr62294.c | 10 + gcc-4.9/gcc/testsuite/gcc.dg/pr62294.h | 3 + gcc-4.9/gcc/testsuite/gcc.dg/pr63186.c | 30 + gcc-4.9/gcc/testsuite/gcc.dg/pr63284.c | 42 + gcc-4.9/gcc/testsuite/gcc.dg/pr63342.c | 26 + gcc-4.9/gcc/testsuite/gcc.dg/pr63538.c | 14 + gcc-4.9/gcc/testsuite/gcc.dg/pr63665.c | 18 + gcc-4.9/gcc/testsuite/gcc.dg/pr64536.c | 67 + gcc-4.9/gcc/testsuite/gcc.dg/pr64563.c | 14 + gcc-4.9/gcc/testsuite/gcc.dg/tm/pr64391.c | 10 + .../gcc.dg/torture/float128-exact-underflow.c | 41 + gcc-4.9/gcc/testsuite/gcc.dg/torture/pr62031.c | 52 + gcc-4.9/gcc/testsuite/gcc.dg/torture/pr62238.c | 30 + gcc-4.9/gcc/testsuite/gcc.dg/torture/pr63380-1.c | 15 + gcc-4.9/gcc/testsuite/gcc.dg/torture/pr63380-2.c | 10 + gcc-4.9/gcc/testsuite/gcc.dg/torture/pr63738.c | 27 + gcc-4.9/gcc/testsuite/gcc.dg/torture/pr64365.c | 37 + gcc-4.9/gcc/testsuite/gcc.dg/torture/vshuf-4.inc | 4 +- .../gcc.dg/tree-prof/cold_partition_label.c | 2 + .../gcc.dg/tree-prof/cold_partition_patch.c | 37 + .../gcc.dg/tree-prof/lipo/ic-misattribution-1_0.c | 2 +- .../tree-prof/lipo/indir-call-prof-single_0.c | 2 +- .../gcc.dg/tree-prof/lipo/indir-call-prof_0.c | 2 +- .../testsuite/gcc.dg/tree-prof/time-profiler-1.c | 2 +- .../testsuite/gcc.dg/tree-prof/time-profiler-2.c | 2 +- gcc-4.9/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c | 2 +- gcc-4.9/gcc/testsuite/gcc.dg/tree-ssa/pr61144.c | 7 + gcc-4.9/gcc/testsuite/gcc.dg/vect/pr25413a.c | 1 + gcc-4.9/gcc/testsuite/gcc.dg/vect/pr59594.c | 2 +- gcc-4.9/gcc/testsuite/gcc.dg/vect/pr60196-1.c | 34 + gcc-4.9/gcc/testsuite/gcc.dg/vect/pr60196-2.c | 33 + gcc-4.9/gcc/testsuite/gcc.dg/vect/pr62021.c | 30 + gcc-4.9/gcc/testsuite/gcc.dg/vect/pr62075.c | 22 + gcc-4.9/gcc/testsuite/gcc.dg/vect/pr63189.c | 26 + gcc-4.9/gcc/testsuite/gcc.dg/vect/pr63379.c | 43 + gcc-4.9/gcc/testsuite/gcc.dg/vect/pr63605.c | 22 + gcc-4.9/gcc/testsuite/gcc.dg/vect/vect-109.c | 1 + gcc-4.9/gcc/testsuite/gcc.dg/vmx/3c-01a.c | 1 + gcc-4.9/gcc/testsuite/gcc.dg/vmx/ops-long-1.c | 1 + gcc-4.9/gcc/testsuite/gcc.dg/vmx/ops.c | 1 + .../gcc.target/aarch64/madd_after_asm_1.c | 14 + gcc-4.9/gcc/testsuite/gcc.target/aarch64/pr62040.c | 21 + gcc-4.9/gcc/testsuite/gcc.target/aarch64/pr62262.c | 20 + gcc-4.9/gcc/testsuite/gcc.target/aarch64/pr63424.c | 39 + .../gcc.target/aarch64/scalar_intrinsics.c | 366 ++-- .../testsuite/gcc.target/aarch64/sisd-shft-neg_1.c | 38 + .../gcc.target/aarch64/vqdmlalh_lane_s16.c | 4 +- .../gcc.target/aarch64/vqdmlals_lane_s32.c | 2 +- .../gcc.target/aarch64/vqdmlslh_lane_s16.c | 4 +- .../gcc.target/aarch64/vqdmlsls_lane_s32.c | 2 +- .../gcc.target/aarch64/vqdmullh_lane_s16.c | 4 +- .../gcc.target/aarch64/vqdmulls_lane_s32.c | 2 +- .../gcc.target/avr/torture/pr63633-ice-mult.c | 37 + gcc-4.9/gcc/testsuite/gcc.target/h8300/h8300.exp | 41 - .../gcc/testsuite/gcc.target/h8300/pragma-isr.c | 20 - .../gcc/testsuite/gcc.target/h8300/pragma-isr2.c | 21 - .../gcc/testsuite/gcc.target/i386/avx2-pr64286.c | 37 + .../gcc.target/i386/avx256-unaligned-load-7.c | 6 +- .../gcc.target/i386/avx256-unaligned-store-7.c | 4 +- .../gcc/testsuite/gcc.target/i386/bmi2-bzhi-2.c | 67 + .../testsuite/gcc.target/i386/memcpy-strategy-4.c | 21 + .../testsuite/gcc.target/i386/memset-strategy-2.c | 10 + gcc-4.9/gcc/testsuite/gcc.target/i386/noplt-1.c | 13 + gcc-4.9/gcc/testsuite/gcc.target/i386/noplt-2.c | 13 + gcc-4.9/gcc/testsuite/gcc.target/i386/noplt-3.c | 12 + gcc-4.9/gcc/testsuite/gcc.target/i386/noplt-4.c | 11 + .../testsuite/gcc.target/i386/pie-copyrelocs-1.c | 11 +- .../testsuite/gcc.target/i386/pie-copyrelocs-2.c | 13 +- .../testsuite/gcc.target/i386/pie-copyrelocs-3.c | 14 + .../testsuite/gcc.target/i386/pie-copyrelocs-4.c | 17 + gcc-4.9/gcc/testsuite/gcc.target/i386/pr57003.c | 2 +- gcc-4.9/gcc/testsuite/gcc.target/i386/pr59927.c | 2 +- gcc-4.9/gcc/testsuite/gcc.target/i386/pr60516.c | 2 +- gcc-4.9/gcc/testsuite/gcc.target/i386/pr63285.c | 28 + gcc-4.9/gcc/testsuite/gcc.target/i386/pr63448.c | 120 ++ gcc-4.9/gcc/testsuite/gcc.target/i386/pr63495.c | 6 + gcc-4.9/gcc/testsuite/gcc.target/i386/pr63538.c | 13 + gcc-4.9/gcc/testsuite/gcc.target/i386/pr63661.c | 80 + gcc-4.9/gcc/testsuite/gcc.target/i386/pr63947.c | 9 + gcc-4.9/gcc/testsuite/gcc.target/i386/pr64409.c | 6 + gcc-4.9/gcc/testsuite/gcc.target/i386/pr64513.c | 17 + .../gcc/testsuite/gcc.target/powerpc/altivec-20.c | 2 +- .../gcc/testsuite/gcc.target/powerpc/altivec-6.c | 2 +- .../gcc.target/powerpc/altivec-vec-merge.c | 2 +- .../gcc/testsuite/gcc.target/powerpc/builtins-1.c | 166 ++ .../gcc/testsuite/gcc.target/powerpc/builtins-2.c | 47 + .../gcc/testsuite/gcc.target/powerpc/lvsl-lvsr.c | 21 + gcc-4.9/gcc/testsuite/gcc.target/powerpc/pr63335.c | 30 + gcc-4.9/gcc/testsuite/gcc.target/powerpc/pr64505.c | 231 +++ .../gcc/testsuite/gcc.target/powerpc/swaps-p8-1.c | 35 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-10.c | 42 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-11.c | 53 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-12.c | 56 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-13.c | 54 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-14.c | 43 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-15.c | 51 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-16.c | 57 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-17.c | 15 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-2.c | 41 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-3.c | 43 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-4.c | 45 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-5.c | 45 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-6.c | 32 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-7.c | 38 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-8.c | 40 + .../gcc/testsuite/gcc.target/powerpc/swaps-p8-9.c | 42 + .../testsuite/gcc.target/powerpc/vsx-builtin-8.c | 2 +- .../testsuite/gcc.target/powerpc/vsx-extract-1.c | 8 +- .../testsuite/gcc.target/powerpc/warn-lvsl-lvsr.c | 14 + .../gcc/testsuite/gcc.target/sh/pr51244-20-sh2a.c | 6 +- gcc-4.9/gcc/testsuite/gcc.target/sh/pr51244-20.c | 10 +- gcc-4.9/gcc/testsuite/gcc.target/sh/pr64507.c | 25 + .../testsuite/gcc.target/sh/torture/pr63783-1.c | 29 + .../testsuite/gcc.target/sh/torture/pr63783-2.c | 29 + .../gcc/testsuite/gfortran.dg/dependency_45.f90 | 12 + .../gcc/testsuite/gfortran.dg/gomp/pr59488-1.f90 | 13 + .../gcc/testsuite/gfortran.dg/gomp/pr59488-2.f90 | 16 + .../gcc/testsuite/gfortran.dg/pointer_intent_7.f90 | 2 +- gcc-4.9/gcc/testsuite/gfortran.dg/pr64528.f90 | 20 + .../testsuite/gfortran.dg/typebound_call_26.f90 | 30 + .../gfortran.dg/typebound_operator_20.f90 | 53 + gcc-4.9/gcc/testsuite/gnat.dg/entry_queues2.adb | 45 + gcc-4.9/gcc/testsuite/gnat.dg/opt41.adb | 15 + gcc-4.9/gcc/testsuite/gnat.dg/opt41_pkg.adb | 53 + gcc-4.9/gcc/testsuite/gnat.dg/opt41_pkg.ads | 28 + gcc-4.9/gcc/testsuite/gnat.dg/opt45.adb | 38 + gcc-4.9/gcc/testsuite/gnat.dg/opt47.adb | 31 + gcc-4.9/gcc/testsuite/go.test/go-test.exp | 6 +- gcc-4.9/gcc/testsuite/lib/asan-dg.exp | 23 +- gcc-4.9/gcc/testsuite/lib/profopt.exp | 2 + gcc-4.9/gcc/testsuite/lib/target-supports.exp | 64 + gcc-4.9/gcc/toplev.c | 13 +- gcc-4.9/gcc/trans-mem.c | 9 +- gcc-4.9/gcc/tree-cfgcleanup.c | 15 +- gcc-4.9/gcc/tree-data-ref.c | 58 +- gcc-4.9/gcc/tree-data-ref.h | 5 - gcc-4.9/gcc/tree-inline.c | 3 +- gcc-4.9/gcc/tree-nrv.c | 3 +- gcc-4.9/gcc/tree-predcom.c | 4 +- gcc-4.9/gcc/tree-profile.c | 35 +- gcc-4.9/gcc/tree-sra.c | 5 + gcc-4.9/gcc/tree-ssa-forwprop.c | 10 +- gcc-4.9/gcc/tree-ssa-loop-niter.c | 3 + gcc-4.9/gcc/tree-ssa-reassoc.c | 9 +- gcc-4.9/gcc/tree-ssa-strlen.c | 2 +- gcc-4.9/gcc/tree-ssa-tail-merge.c | 10 +- gcc-4.9/gcc/tree-vect-data-refs.c | 6 + gcc-4.9/gcc/tree-vect-loop.c | 14 +- gcc-4.9/gcc/tree-vect-slp.c | 27 +- gcc-4.9/gcc/tree-vect-stmts.c | 5 +- gcc-4.9/gcc/tree-vrp.c | 8 +- gcc-4.9/gcc/tree.c | 16 +- gcc-4.9/gcc/tsan.c | 15 +- gcc-4.9/gcc/ubsan.c | 37 +- gcc-4.9/gcc/value-prof.c | 28 +- gcc-4.9/gcc/value-prof.h | 2 +- gcc-4.9/gcc/varasm.c | 19 +- gcc-4.9/gcc/varasm.h | 7 + gcc-4.9/gcc/varpool.c | 12 +- gcc-4.9/gcc/web.c | 65 +- gcc-4.9/gnattools/ChangeLog | 4 + gcc-4.9/include/ChangeLog | 4 + gcc-4.9/include/demangle.h | 4 + gcc-4.9/intl/ChangeLog | 4 + gcc-4.9/libada/ChangeLog | 4 + gcc-4.9/libatomic/ChangeLog | 9 + gcc-4.9/libatomic/fop_n.c | 12 +- gcc-4.9/libbacktrace/ChangeLog | 4 + gcc-4.9/libcilkrts/ChangeLog | 4 + gcc-4.9/libcpp/ChangeLog | 40 + gcc-4.9/libcpp/directives.c | 14 + gcc-4.9/libcpp/expr.c | 75 + gcc-4.9/libcpp/files.c | 18 + gcc-4.9/libcpp/identifiers.c | 2 + gcc-4.9/libcpp/internal.h | 8 + gcc-4.9/libcpp/lex.c | 115 +- gcc-4.9/libcpp/line-map.c | 10 +- gcc-4.9/libcpp/pch.c | 2 + gcc-4.9/libcpp/po/ChangeLog | 8 + gcc-4.9/libcpp/po/ja.po | 27 +- gcc-4.9/libcpp/traditional.c | 19 +- gcc-4.9/libdecnumber/ChangeLog | 4 + gcc-4.9/libffi/ChangeLog | 10 + gcc-4.9/libffi/src/powerpc/linux64.S | 5 +- gcc-4.9/libffi/src/powerpc/linux64_closure.S | 5 +- gcc-4.9/libgcc/ChangeLog | 79 +- gcc-4.9/libgcc/Makefile.in | 12 +- gcc-4.9/libgcc/config/avr/lib1funcs.S | 229 ++- gcc-4.9/libgcc/config/avr/t-avr | 3 +- gcc-4.9/libgcc/config/i386/sfp-machine.h | 2 +- gcc-4.9/libgcc/config/libbid/ChangeLog | 4 + gcc-4.9/libgcc/config/nios2/linux-unwind.h | 3 +- gcc-4.9/libgcc/config/pa/linux-atomic.c | 304 ++-- gcc-4.9/libgcc/config/pa/linux-unwind.h | 34 +- gcc-4.9/libgcc/config/sh/lib1funcs.S | 18 +- gcc-4.9/libgcc/dyn-ipa.c | 111 +- gcc-4.9/libgcc/libgcov-driver-kernel.c | 203 +++ gcc-4.9/libgcc/libgcov-driver-system.c | 23 - gcc-4.9/libgcc/libgcov-driver.c | 469 ++++- gcc-4.9/libgcc/libgcov-kernel.h | 121 ++ gcc-4.9/libgcc/libgcov-merge.c | 2 + gcc-4.9/libgcc/libgcov-profiler.c | 136 +- gcc-4.9/libgcc/libgcov-util.c | 684 +++++++- gcc-4.9/libgcc/libgcov.h | 40 +- gcc-4.9/libgfortran/ChangeLog | 28 + gcc-4.9/libgfortran/config.h.in | 3 + gcc-4.9/libgfortran/configure | 10 +- gcc-4.9/libgfortran/configure.ac | 3 +- gcc-4.9/libgfortran/io/unit.c | 1 + gcc-4.9/libgfortran/runtime/main.c | 44 +- gcc-4.9/libgfortran/runtime/memory.c | 4 +- gcc-4.9/libgo/configure | 35 +- gcc-4.9/libgo/configure.ac | 13 +- gcc-4.9/libgo/go/debug/elf/elf.go | 574 ++++++- gcc-4.9/libgo/go/debug/elf/file.go | 94 +- gcc-4.9/libgo/go/debug/elf/file_test.go | 6 + gcc-4.9/libgo/go/go/build/syslist.go | 2 +- gcc-4.9/libgo/go/syscall/exec_linux.go | 4 +- gcc-4.9/libgo/mksysinfo.sh | 26 +- gcc-4.9/libgo/runtime/getncpu-linux.c | 2 +- gcc-4.9/libgomp/ChangeLog | 32 + gcc-4.9/libgomp/configure.tgt | 2 +- gcc-4.9/libgomp/testsuite/libgomp.c++/pr63248.C | 62 + gcc-4.9/libgomp/testsuite/libgomp.c/pr61200.c | 87 + gcc-4.9/libgomp/testsuite/libgomp.c/pr64734.c | 55 + .../testsuite/libgomp.fortran/pr63938-1.f90 | 14 + .../testsuite/libgomp.fortran/pr63938-2.f90 | 18 + gcc-4.9/libiberty/ChangeLog | 4 + gcc-4.9/libiberty/cp-demangle.c | 37 +- gcc-4.9/libiberty/cp-demint.c | 1 + gcc-4.9/libiberty/testsuite/demangle-expected | 23 + gcc-4.9/libitm/ChangeLog | 8 + gcc-4.9/libitm/configure.tgt | 2 +- gcc-4.9/libjava/ChangeLog | 4 + gcc-4.9/libjava/classpath/ChangeLog | 4 + gcc-4.9/libjava/libltdl/ChangeLog | 4 + gcc-4.9/libobjc/ChangeLog | 4 + gcc-4.9/libquadmath/ChangeLog | 4 + gcc-4.9/libsanitizer/ChangeLog | 28 + gcc-4.9/libsanitizer/Makefile.am | 9 + gcc-4.9/libsanitizer/Makefile.in | 64 +- .../sanitizer_platform_limits_linux.cc | 3 +- .../sanitizer_platform_limits_posix.h | 56 +- gcc-4.9/libssp/ChangeLog | 4 + gcc-4.9/libstdc++-v3/ChangeLog | 273 +++ .../config/os/mingw32-w64/os_defines.h | 3 + .../libstdc++-v3/config/os/mingw32/os_defines.h | 3 + gcc-4.9/libstdc++-v3/configure.host | 1 - gcc-4.9/libstdc++-v3/doc/html/index.html | 2 +- .../libstdc++-v3/doc/html/manual/containers.html | 19 +- gcc-4.9/libstdc++-v3/doc/html/manual/index.html | 2 +- gcc-4.9/libstdc++-v3/doc/html/manual/status.html | 12 +- .../libstdc++-v3/doc/html/manual/std_contents.html | 2 +- gcc-4.9/libstdc++-v3/doc/xml/manual/containers.xml | 25 +- .../libstdc++-v3/doc/xml/manual/status_cxx2011.xml | 24 +- gcc-4.9/libstdc++-v3/include/bits/algorithmfwd.h | 12 +- gcc-4.9/libstdc++-v3/include/bits/atomic_base.h | 5 +- gcc-4.9/libstdc++-v3/include/bits/basic_string.h | 2 + gcc-4.9/libstdc++-v3/include/bits/hashtable.h | 2 +- gcc-4.9/libstdc++-v3/include/bits/move.h | 5 +- gcc-4.9/libstdc++-v3/include/bits/regex.h | 137 +- gcc-4.9/libstdc++-v3/include/bits/regex.tcc | 106 +- .../libstdc++-v3/include/bits/regex_compiler.tcc | 2 +- .../libstdc++-v3/include/bits/regex_executor.tcc | 35 +- gcc-4.9/libstdc++-v3/include/bits/stl_algo.h | 16 +- gcc-4.9/libstdc++-v3/include/bits/stl_algobase.h | 3 + gcc-4.9/libstdc++-v3/include/bits/stl_function.h | 4 + gcc-4.9/libstdc++-v3/include/bits/stl_queue.h | 3 + gcc-4.9/libstdc++-v3/include/bits/stl_stack.h | 3 + .../libstdc++-v3/include/bits/stl_uninitialized.h | 5 +- gcc-4.9/libstdc++-v3/include/bits/unique_ptr.h | 3 + gcc-4.9/libstdc++-v3/include/bits/vector.tcc | 2 +- .../libstdc++-v3/include/c_compatibility/complex.h | 28 +- gcc-4.9/libstdc++-v3/include/debug/array | 32 +- gcc-4.9/libstdc++-v3/include/debug/functions.h | 14 +- gcc-4.9/libstdc++-v3/include/parallel/algo.h | 35 +- gcc-4.9/libstdc++-v3/include/parallel/numeric | 9 +- gcc-4.9/libstdc++-v3/include/std/array | 40 +- gcc-4.9/libstdc++-v3/include/std/atomic | 10 +- gcc-4.9/libstdc++-v3/include/std/chrono | 2 + gcc-4.9/libstdc++-v3/include/std/complex | 12 +- gcc-4.9/libstdc++-v3/include/std/functional | 2 +- gcc-4.9/libstdc++-v3/include/std/future | 3 +- gcc-4.9/libstdc++-v3/include/std/iomanip | 2 + gcc-4.9/libstdc++-v3/include/std/mutex | 7 +- gcc-4.9/libstdc++-v3/include/std/shared_mutex | 16 +- gcc-4.9/libstdc++-v3/include/std/tuple | 31 +- gcc-4.9/libstdc++-v3/include/std/type_traits | 19 + gcc-4.9/libstdc++-v3/include/std/utility | 9 + gcc-4.9/libstdc++-v3/include/tr1/functional | 4 +- gcc-4.9/libstdc++-v3/libsupc++/eh_personality.cc | 6 + .../20_util/declval/requirements/1_neg.cc | 2 +- .../testsuite/20_util/forward/c_neg.cc | 2 +- .../testsuite/20_util/forward/f_neg.cc | 2 +- .../testsuite/20_util/function/63840.cc | 55 + .../requirements/explicit_instantiation.cc | 29 + .../20_util/is_final/requirements/typedefs.cc | 34 + .../testsuite/20_util/is_final/value.cc | 35 + .../make_signed/requirements/typedefs_neg.cc | 4 +- .../make_unsigned/requirements/typedefs_neg.cc | 4 +- .../uninitialized_copy/64476.cc | 65 + .../libstdc++-v3/testsuite/20_util/tuple/61947.cc | 29 + .../testsuite/20_util/uses_allocator/cons_neg.cc | 2 +- .../priority_queue/requirements/uses_allocator.cc | 29 + .../queue/requirements/uses_allocator.cc | 29 + .../stack/requirements/uses_allocator.cc | 29 + .../testsuite/23_containers/unordered_set/63456.cc | 34 + .../testsuite/23_containers/vector/63500.cc | 39 + .../25_algorithms/is_permutation/64646.cc | 35 + .../25_algorithms/random_shuffle/59603.cc | 34 + .../testsuite/25_algorithms/unique/11480.cc | 2 +- .../algorithms/regex_match/ecma/wchar_t/63199.cc | 69 + .../28_regex/basic_regex/assign/char/string.cc | 20 +- .../testsuite/28_regex/basic_regex/imbue/string.cc | 44 + .../iterators/regex_iterator/char/64140.cc | 53 + .../regex_iterator/char/string_position_01.cc | 45 + .../iterators/regex_token_iterator/64303.cc | 49 + .../testsuite/28_regex/match_results/swap.cc | 43 + .../28_regex/traits/char/lookup_classname.cc | 22 + .../28_regex/traits/char/lookup_collatename.cc | 12 + .../testsuite/29_atomics/atomic/62259.cc | 59 + .../testsuite/29_atomics/atomic/65147.cc | 29 + .../testsuite/29_atomics/atomic_integral/65147.cc | 33 + .../testsuite/30_threads/try_lock/4.cc | 11 +- .../testsuite/experimental/feat-cxx14.cc | 121 ++ .../testsuite/experimental/feat-lib-fund.cc | 25 + .../tr1/3_function_objects/function/63840.cc | 55 + .../libstdc++-v3/testsuite/util/testsuite_tr1.h | 4 + gcc-4.9/libvtv/ChangeLog | 4 + gcc-4.9/lto-plugin/ChangeLog | 4 + gcc-4.9/maintainer-scripts/ChangeLog | 4 + gcc-4.9/zlib/ChangeLog | 4 + 791 files changed, 25645 insertions(+), 4550 deletions(-) create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/asan-interface-1.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-1.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-2.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-3.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-4.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/instrument-with-calls-1.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/misalign-1.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/misalign-2.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/pr61530.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62089.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62140-1.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62140-2.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/pr63638.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/asan/strlen-overflow-1.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr60823-4.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr61200.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr63249.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr63328.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/pr56493.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/pr61553.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/tsan/tsan_barrier.h create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/ubsan/overflow-sub-3.c create mode 100644 gcc-4.9/gcc/testsuite/c-c++-common/ubsan/undefined-2.c create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/abi/no-weak1.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/abi/spec1.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/asan/pr62017.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp0x/alias-decl-44.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp0x/constexpr-63241.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp0x/constexpr-63265.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist8.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp0x/deleted9.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp0x/initlist89.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp0x/lambda/lambda-template14.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp0x/ref-qual16.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp0x/variadic161.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp0x/variadic162.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp1y/feat-cxx11-neg.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp1y/feat-cxx11.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp1y/feat-cxx14.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp1y/feat-cxx98-neg.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp1y/feat-cxx98.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp1y/paren1.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp1y/phoobhar.h create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/cpp1y/pr57644.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/ext/stmtexpr16.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/gomp/pr63249.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-28a.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/ipa/devirt-40.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/ipa/pr61654.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/ipa/pr62015.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/ipa/pr63306.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/ipa/pr63838.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/ipa/pr64068.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/lto/pr62026.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/opt/devirt5.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/opt/flifetime-dse1.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/pr54442.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/pr62079.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/pr64037.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/template/friend56.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/template/non-dependent14.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/template/offsetof3.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/template/ptrmem29.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/template/ref9.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/template/spec38.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/torture/pr62121.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/torture/pr62175.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/torture/pr63632.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/buildinfo.txt create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/comdat_fixup.h create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/comdat_fixup_0.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/comdat_fixup_1.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/comdat_fixup_2.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/static1_0.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/static1_1.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/static1_2.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/tls.h create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/tls2.h create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/tls2_0.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/tls2_1.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/tls_0.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/lipo/tls_1.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/partition_patch.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-prof/pr63581.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tree-ssa/pr63841.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/tsan/tsan_barrier.h create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/ubsan/pr61272.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/ubsan/pr63913.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/warn/Wunused-parm-6.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/warn/Wunused-var-22.C create mode 100644 gcc-4.9/gcc/testsuite/g++.dg/warn/register-parm-1.C create mode 100644 gcc-4.9/gcc/testsuite/gcc.c-torture/compile/pr62312.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.c-torture/compile/pr63282.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.c-torture/compile/pr64067.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.c-torture/compile/pr64269.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.c-torture/execute/pr63209.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.c-torture/execute/pr63302.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.c-torture/execute/pr63659.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/20141029-1.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/darwin-minversion-4.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/fpomit-1.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/fpomit-2.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/fpomit-3.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/fpomit-4.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/fpomit-5.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/fpomit-6.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/fpomit-7.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/fpomit-8.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/fpomit-9.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/ipa/PR64559.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/ipa/pr61986.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/ipa/pr63551.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/ipa/pr64041.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/option_no-pie.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr52769.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr56724-1.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr56724-2.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr62167-run.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr62167.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr62294.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr62294.h create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr63186.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr63284.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr63342.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr63538.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr63665.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr64536.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/pr64563.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/tm/pr64391.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/torture/float128-exact-underflow.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/torture/pr62031.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/torture/pr62238.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/torture/pr63380-1.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/torture/pr63380-2.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/torture/pr63738.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/torture/pr64365.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/tree-prof/cold_partition_patch.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/tree-ssa/pr61144.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/vect/pr60196-1.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/vect/pr60196-2.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/vect/pr62021.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/vect/pr62075.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/vect/pr63189.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/vect/pr63379.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.dg/vect/pr63605.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/aarch64/pr63424.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/aarch64/sisd-shft-neg_1.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/avr/torture/pr63633-ice-mult.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/avx2-pr64286.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/bmi2-bzhi-2.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/memcpy-strategy-4.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/memset-strategy-2.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/noplt-1.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/noplt-2.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/noplt-3.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/noplt-4.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/pie-copyrelocs-3.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/pie-copyrelocs-4.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/pr63285.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/pr63448.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/pr63495.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/pr63538.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/pr63661.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/pr63947.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/pr64409.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/i386/pr64513.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/builtins-1.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/builtins-2.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/lvsl-lvsr.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/pr63335.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/pr64505.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-1.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-10.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-11.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-12.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-13.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-14.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-15.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-16.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-17.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-2.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-3.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-4.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-5.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-6.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-7.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-8.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/swaps-p8-9.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/powerpc/warn-lvsl-lvsr.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/sh/pr64507.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/sh/torture/pr63783-1.c create mode 100644 gcc-4.9/gcc/testsuite/gcc.target/sh/torture/pr63783-2.c create mode 100644 gcc-4.9/gcc/testsuite/gfortran.dg/dependency_45.f90 create mode 100644 gcc-4.9/gcc/testsuite/gfortran.dg/gomp/pr59488-1.f90 create mode 100644 gcc-4.9/gcc/testsuite/gfortran.dg/gomp/pr59488-2.f90 create mode 100644 gcc-4.9/gcc/testsuite/gfortran.dg/pr64528.f90 create mode 100644 gcc-4.9/gcc/testsuite/gfortran.dg/typebound_call_26.f90 create mode 100644 gcc-4.9/gcc/testsuite/gfortran.dg/typebound_operator_20.f90 create mode 100644 gcc-4.9/gcc/testsuite/gnat.dg/entry_queues2.adb create mode 100644 gcc-4.9/gcc/testsuite/gnat.dg/opt41.adb create mode 100644 gcc-4.9/gcc/testsuite/gnat.dg/opt41_pkg.adb create mode 100644 gcc-4.9/gcc/testsuite/gnat.dg/opt41_pkg.ads create mode 100644 gcc-4.9/gcc/testsuite/gnat.dg/opt45.adb create mode 100644 gcc-4.9/gcc/testsuite/gnat.dg/opt47.adb create mode 100644 gcc-4.9/libgcc/libgcov-driver-kernel.c create mode 100644 gcc-4.9/libgcc/libgcov-kernel.h create mode 100644 gcc-4.9/libgomp/testsuite/libgomp.c++/pr63248.C create mode 100644 gcc-4.9/libgomp/testsuite/libgomp.c/pr61200.c create mode 100644 gcc-4.9/libgomp/testsuite/libgomp.c/pr64734.c create mode 100644 gcc-4.9/libgomp/testsuite/libgomp.fortran/pr63938-1.f90 create mode 100644 gcc-4.9/libgomp/testsuite/libgomp.fortran/pr63938-2.f90 create mode 100644 gcc-4.9/libstdc++-v3/testsuite/20_util/function/63840.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/20_util/is_final/requirements/explicit_instantiation.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/20_util/is_final/requirements/typedefs.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/20_util/is_final/value.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/20_util/specialized_algorithms/uninitialized_copy/64476.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/20_util/tuple/61947.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/23_containers/priority_queue/requirements/uses_allocator.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/23_containers/queue/requirements/uses_allocator.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/23_containers/stack/requirements/uses_allocator.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/23_containers/unordered_set/63456.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/23_containers/vector/63500.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/25_algorithms/is_permutation/64646.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/25_algorithms/random_shuffle/59603.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/28_regex/algorithms/regex_match/ecma/wchar_t/63199.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/28_regex/basic_regex/imbue/string.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/28_regex/iterators/regex_iterator/char/64140.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/28_regex/iterators/regex_token_iterator/64303.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/28_regex/match_results/swap.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/29_atomics/atomic/62259.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/29_atomics/atomic/65147.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/29_atomics/atomic_integral/65147.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/experimental/feat-cxx14.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/experimental/feat-lib-fund.cc create mode 100644 gcc-4.9/libstdc++-v3/testsuite/tr1/3_function_objects/function/63840.cc diff --git a/gcc-4.9/ChangeLog b/gcc-4.9/ChangeLog index 1a00eae06..a8ea3479c 100644 --- a/gcc-4.9/ChangeLog +++ b/gcc-4.9/ChangeLog @@ -1,8 +1,19 @@ +2014-12-04 Tobias Burnus + + * configure.ac: Permit also ISL 0.14 with CLooG. + * Makefile.def: Make more dependent on mpfr, mpc, isl, and cloog. + * Makefile.in: Regenerate. + * configure: Regenerate. + 2014-11-19 Renlin Li PR middle-end/63762 * ira.c (ira): Update preferred class. +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-26 Uros Bizjak PR target/47230 diff --git a/gcc-4.9/Makefile.def b/gcc-4.9/Makefile.def index fd040a520..29ad919a8 100644 --- a/gcc-4.9/Makefile.def +++ b/gcc-4.9/Makefile.def @@ -298,6 +298,10 @@ dependencies = { module=all-build-fixincludes; on=all-build-libiberty; }; // Host modules specific to gcc. dependencies = { module=configure-gcc; on=configure-intl; }; dependencies = { module=configure-gcc; on=all-gmp; }; +dependencies = { module=configure-gcc; on=all-mpfr; }; +dependencies = { module=configure-gcc; on=all-mpc; }; +dependencies = { module=configure-gcc; on=all-isl; }; +dependencies = { module=configure-gcc; on=all-cloog; }; dependencies = { module=configure-gcc; on=all-lto-plugin; }; dependencies = { module=configure-gcc; on=all-function_reordering_plugin; }; dependencies = { module=configure-gcc; on=all-binutils; }; diff --git a/gcc-4.9/Makefile.in b/gcc-4.9/Makefile.in index cd76a643d..9e0b0f530 100644 --- a/gcc-4.9/Makefile.in +++ b/gcc-4.9/Makefile.in @@ -47951,6 +47951,38 @@ configure-stage3-gcc: maybe-all-stage3-gmp configure-stage4-gcc: maybe-all-stage4-gmp configure-stageprofile-gcc: maybe-all-stageprofile-gmp configure-stagefeedback-gcc: maybe-all-stagefeedback-gmp +configure-gcc: maybe-all-mpfr + +configure-stage1-gcc: maybe-all-stage1-mpfr +configure-stage2-gcc: maybe-all-stage2-mpfr +configure-stage3-gcc: maybe-all-stage3-mpfr +configure-stage4-gcc: maybe-all-stage4-mpfr +configure-stageprofile-gcc: maybe-all-stageprofile-mpfr +configure-stagefeedback-gcc: maybe-all-stagefeedback-mpfr +configure-gcc: maybe-all-mpc + +configure-stage1-gcc: maybe-all-stage1-mpc +configure-stage2-gcc: maybe-all-stage2-mpc +configure-stage3-gcc: maybe-all-stage3-mpc +configure-stage4-gcc: maybe-all-stage4-mpc +configure-stageprofile-gcc: maybe-all-stageprofile-mpc +configure-stagefeedback-gcc: maybe-all-stagefeedback-mpc +configure-gcc: maybe-all-isl + +configure-stage1-gcc: maybe-all-stage1-isl +configure-stage2-gcc: maybe-all-stage2-isl +configure-stage3-gcc: maybe-all-stage3-isl +configure-stage4-gcc: maybe-all-stage4-isl +configure-stageprofile-gcc: maybe-all-stageprofile-isl +configure-stagefeedback-gcc: maybe-all-stagefeedback-isl +configure-gcc: maybe-all-cloog + +configure-stage1-gcc: maybe-all-stage1-cloog +configure-stage2-gcc: maybe-all-stage2-cloog +configure-stage3-gcc: maybe-all-stage3-cloog +configure-stage4-gcc: maybe-all-stage4-cloog +configure-stageprofile-gcc: maybe-all-stageprofile-cloog +configure-stagefeedback-gcc: maybe-all-stagefeedback-cloog configure-gcc: maybe-all-lto-plugin configure-stage1-gcc: maybe-all-stage1-lto-plugin diff --git a/gcc-4.9/boehm-gc/ChangeLog b/gcc-4.9/boehm-gc/ChangeLog index 2dbc61fa9..abf401c1e 100644 --- a/gcc-4.9/boehm-gc/ChangeLog +++ b/gcc-4.9/boehm-gc/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-16 Release Manager * GCC 4.9.1 released. diff --git a/gcc-4.9/config/ChangeLog b/gcc-4.9/config/ChangeLog index cb6dcaafc..e569d7aed 100644 --- a/gcc-4.9/config/ChangeLog +++ b/gcc-4.9/config/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-26 Uros Bizjak PR target/47230 diff --git a/gcc-4.9/configure b/gcc-4.9/configure index a91394234..a7b80ffa0 100755 --- a/gcc-4.9/configure +++ b/gcc-4.9/configure @@ -6027,6 +6027,55 @@ $as_echo "$gcc_cv_isl" >&6; } fi + if test "${gcc_cv_isl}" = no ; then + + if test "${ENABLE_ISL_CHECK}" = yes ; then + _isl_saved_CFLAGS=$CFLAGS + _isl_saved_LDFLAGS=$LDFLAGS + _isl_saved_LIBS=$LIBS + + CFLAGS="${_isl_saved_CFLAGS} ${islinc} ${gmpinc}" + LDFLAGS="${_isl_saved_LDFLAGS} ${isllibs}" + LIBS="${_isl_saved_LIBS} -lisl" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for version 0.14 of ISL" >&5 +$as_echo_n "checking for version 0.14 of ISL... " >&6; } + if test "$cross_compiling" = yes; then : + gcc_cv_isl=yes +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include +int +main () +{ +if (strncmp (isl_version (), "isl-0.14", strlen ("isl-0.14")) != 0) + return 1; + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + gcc_cv_isl=yes +else + gcc_cv_isl=no +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_isl" >&5 +$as_echo "$gcc_cv_isl" >&6; } + + CFLAGS=$_isl_saved_CFLAGS + LDFLAGS=$_isl_saved_LDFLAGS + LIBS=$_isl_saved_LIBS + fi + + + fi fi fi diff --git a/gcc-4.9/configure.ac b/gcc-4.9/configure.ac index aa41d3c70..5dac5dae0 100644 --- a/gcc-4.9/configure.ac +++ b/gcc-4.9/configure.ac @@ -1661,6 +1661,9 @@ if test "x$with_isl" != "xno" && ISL_CHECK_VERSION(0,11) if test "${gcc_cv_isl}" = no ; then ISL_CHECK_VERSION(0,12) + if test "${gcc_cv_isl}" = no ; then + ISL_CHECK_VERSION(0,14) + fi fi fi dnl Only execute fail-action, if ISL has been requested. diff --git a/gcc-4.9/contrib/ChangeLog b/gcc-4.9/contrib/ChangeLog index 985389828..6254a17c3 100644 --- a/gcc-4.9/contrib/ChangeLog +++ b/gcc-4.9/contrib/ChangeLog @@ -1,3 +1,16 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + +2014-09-18 Joel Sherrill + + * config-list.mk (LIST): Add v850-rtems. + +2014-09-18 Sebastian Huber + + * config-list.mk (LIST): Add arm-rtems. + Add nios2-rtems. Remove extra option from powerpc-rtems. + 2014-07-16 Release Manager * GCC 4.9.1 released. diff --git a/gcc-4.9/contrib/config-list.mk b/gcc-4.9/contrib/config-list.mk index 43454871d..68e2e3ed0 100644 --- a/gcc-4.9/contrib/config-list.mk +++ b/gcc-4.9/contrib/config-list.mk @@ -68,7 +68,7 @@ LIST = aarch64-elf aarch64-linux-gnu \ sparc-wrs-vxworks sparc64-elf sparc64-rtems sparc64-linux sparc64-freebsd6 \ sparc64-netbsd sparc64-openbsd spu-elf \ tilegx-linux-gnu tilegxbe-linux-gnu tilepro-linux-gnu \ - v850e-elf v850-elf vax-linux-gnu \ + v850e-elf v850-elf v850-rtems vax-linux-gnu \ vax-netbsdelf vax-openbsd x86_64-apple-darwin \ x86_64-pc-linux-gnuOPT-with-fpmath=avx \ x86_64-elfOPT-with-fpmath=sse x86_64-freebsd6 x86_64-netbsd \ diff --git a/gcc-4.9/contrib/reghunt/ChangeLog b/gcc-4.9/contrib/reghunt/ChangeLog index ccb88eb1d..64956647e 100644 --- a/gcc-4.9/contrib/reghunt/ChangeLog +++ b/gcc-4.9/contrib/reghunt/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-16 Release Manager * GCC 4.9.1 released. diff --git a/gcc-4.9/contrib/regression/ChangeLog b/gcc-4.9/contrib/regression/ChangeLog index de91385ff..602272d70 100644 --- a/gcc-4.9/contrib/regression/ChangeLog +++ b/gcc-4.9/contrib/regression/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-16 Release Manager * GCC 4.9.1 released. diff --git a/gcc-4.9/contrib/testsuite-management/aarch64-grtev4-linux-gnu.xfail b/gcc-4.9/contrib/testsuite-management/aarch64-grtev4-linux-gnu.xfail index d77ebeedf..a459149ee 100644 --- a/gcc-4.9/contrib/testsuite-management/aarch64-grtev4-linux-gnu.xfail +++ b/gcc-4.9/contrib/testsuite-management/aarch64-grtev4-linux-gnu.xfail @@ -18,10 +18,9 @@ FAIL: gcc.dg/wself-assign-1.c (test for warnings, line 20) FAIL: gcc.dg/wself-assign-1.c (test for warnings, line 21) FAIL: gcc.dg/wself-assign-1.c (test for warnings, line 22) -# Also xfailed in x86; Google b/13171749 -FAIL: g++.dg/ipa/devirt-24.C -std=gnu++98 scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 -FAIL: g++.dg/ipa/devirt-24.C -std=gnu++11 scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 -FAIL: g++.dg/ipa/devirt-24.C -std=gnu++1y scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 +# Also xfailed in x86; Google b/20184248 +FAIL: 17_intro/headers/c++1998/complex.cc (test for excess errors) +FAIL: 26_numerics/complex/c99.cc (test for excess errors) # AArch64-specific; appear to be missing "loop turned into non-loop; it never loops" output. FAIL: gcc.dg/unroll_1.c (test for warnings, line 14) diff --git a/gcc-4.9/contrib/testsuite-management/powerpc64le-grtev4-linux-gnu.xfail b/gcc-4.9/contrib/testsuite-management/powerpc64le-grtev4-linux-gnu.xfail index d3717ac74..d8995e0cd 100644 --- a/gcc-4.9/contrib/testsuite-management/powerpc64le-grtev4-linux-gnu.xfail +++ b/gcc-4.9/contrib/testsuite-management/powerpc64le-grtev4-linux-gnu.xfail @@ -18,10 +18,9 @@ FAIL: gcc.dg/wself-assign-1.c (test for warnings, line 20) FAIL: gcc.dg/wself-assign-1.c (test for warnings, line 21) FAIL: gcc.dg/wself-assign-1.c (test for warnings, line 22) -# Also xfailed in x86; Google b/13171749 -FAIL: g++.dg/ipa/devirt-24.C -std=gnu++98 scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 -FAIL: g++.dg/ipa/devirt-24.C -std=gnu++11 scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 -FAIL: g++.dg/ipa/devirt-24.C -std=gnu++1y scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 +# Also xfailed in x86; Google b/20184248 +FAIL: 17_intro/headers/c++1998/complex.cc (test for excess errors) +FAIL: 26_numerics/complex/c99.cc (test for excess errors) # PPCle-specific. From PR33512, still failing in truck despite resolved PR. FAIL: gcc.dg/and-1.c scan-assembler-not nand diff --git a/gcc-4.9/contrib/testsuite-management/x86_64-grtev4-linux-gnu.xfail b/gcc-4.9/contrib/testsuite-management/x86_64-grtev4-linux-gnu.xfail index 7d2b65382..b4fa69337 100644 --- a/gcc-4.9/contrib/testsuite-management/x86_64-grtev4-linux-gnu.xfail +++ b/gcc-4.9/contrib/testsuite-management/x86_64-grtev4-linux-gnu.xfail @@ -1,14 +1,6 @@ # 2014/03/29 merge from trunk FAIL: 23_containers/map/pthread6.cc execution test -# Google b/13171749 -FAIL: g++.dg/ipa/devirt-24.C -std=gnu++98 scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 -FAIL: g++.dg/ipa/devirt-24.C -std=gnu++11 scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 -FAIL: g++.dg/ipa/devirt-24.C -std=gnu++1y scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 -FAIL: g++.dg/ipa/devirt-11.C -std=gnu++98 scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 -FAIL: g++.dg/ipa/devirt-11.C -std=gnu++11 scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 -FAIL: g++.dg/ipa/devirt-11.C -std=gnu++1y scan-ipa-dump-times inline "Discovered a virtual call to a known target" 1 - # Google b/13175515 -- r208255 disabled self-assign in templates. FAIL: g++.dg/warn/Wself-assign-non-pod-3.C -std=gnu++98 (test for warnings, line 30) FAIL: g++.dg/warn/Wself-assign-non-pod-3.C -std=gnu++11 (test for warnings, line 30) @@ -29,6 +21,10 @@ FAIL: gcc.dg/wself-assign-1.c (test for warnings, line 22) # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60037 FAIL: ext/random/hypergeometric_distribution/operators/values.cc execution test +# Google b/20184248 +FAIL: 17_intro/headers/c++1998/complex.cc (test for excess errors) +FAIL: 26_numerics/complex/c99.cc (test for excess errors) + # Google b/14137212 FAIL: 29_atomics/atomic/cons/user_pod.cc (test for excess errors) @@ -45,3 +41,11 @@ FAIL: gfortran.dg/erf_3.F90 -O3 -fomit-frame-pointer -funroll-loops execution t FAIL: gfortran.dg/erf_3.F90 -O3 -fomit-frame-pointer -funroll-all-loops -finline-functions execution test FAIL: gfortran.dg/erf_3.F90 -O3 -g execution test FAIL: gfortran.dg/erf_3.F90 -Os execution test + +# Sporadic timeouts in nightly testing. +flaky | FAIL: 23_containers/list/pthread5.cc execution test +flaky | FAIL: 27_io/basic_ofstream/pthread2.cc execution test +flaky | FAIL: g++.dg/tls/thread_local4g.C -std=gnu++11 execution test +flaky | FAIL: g++.dg/tls/thread_local4g.C -std=gnu++1y execution test +flaky | FAIL: g++.dg/tls/thread_local4.C -std=gnu++11 execution test +flaky | FAIL: g++.dg/tls/thread_local4.C -std=gnu++1y execution test diff --git a/gcc-4.9/fixincludes/ChangeLog b/gcc-4.9/fixincludes/ChangeLog index cef5385de..f1bb068a7 100644 --- a/gcc-4.9/fixincludes/ChangeLog +++ b/gcc-4.9/fixincludes/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-16 Release Manager * GCC 4.9.1 released. diff --git a/gcc-4.9/gcc/ChangeLog b/gcc-4.9/gcc/ChangeLog index b97054b2c..a6c51d36b 100644 --- a/gcc-4.9/gcc/ChangeLog +++ b/gcc-4.9/gcc/ChangeLog @@ -1,32 +1,1424 @@ +2015-03-26 Bill Schmidt + + Backport of r214242, r214254, and bug fix patches from mainline + * config/rs6000/rs6000.c (context.h): New #include. + (tree-pass.h): Likewise. + (make_pass_analyze_swaps): New declaration. + (rs6000_option_override): Register swap-optimization pass. + (swap_web_entry): New class. + (special_handling_values): New enum. + (union_defs): New function. + (union_uses): Likewise. + (insn_is_load_p): Likewise. + (insn_is_store_p): Likewise. + (insn_is_swap_p): Likewise. + (rtx_is_swappable_p): Likewise. + (insn_is_swappable_p): Likewise. + (chain_purpose): New enum. + (chain_contains_only_swaps): New function. + (mark_swaps_for_removal): Likewise. + (swap_const_vector_halves): Likewise. + (adjust_subreg_index): Likewise. + (permute_load): Likewise. + (permute_store): Likewise. + (adjust_extract): Likewise. + (adjust_splat): Likewise. + (handle_special_swappables): Likewise. + (replace_swap_with_copy): Likewise. + (dump_swap_insn_table): Likewise. + (rs6000_analyze_swaps): Likewise. + (pass_data_analyze_swaps): New pass_data. + (pass_analyze_swaps): New class. + (pass_analyze_swaps::gate): New method. + (pass_analyze_swaps::execute): New method. + (make_pass_analyze_swaps): New function. + * config/rs6000/rs6000.opt (moptimize-swaps): New option. + * df.h (web_entry_base): New class, replacing struct web_entry. + (web_entry_base::pred): New method. + (web_entry_base::set_pred): Likewise. + (web_entry_base::unionfind_root): Likewise. + (web_entry_base::unionfind_union): Likewise. + (unionfind_root): Delete external reference. + (unionfind_union): Likewise. + (union_defs): Likewise. + * web.c (web_entry_base::unionfind_root): Convert to method. + (web_entry_base::unionfind_union): Likewise. + (web_entry): New class. + (union_match_dups): Convert to use class structure. + (union_defs): Likewise. + (entry_register): Likewise. + (web_main): Likewise. + +2015-01-23 Jakub Jelinek + + PR middle-end/64734 + * omp-low.c (scan_sharing_clauses): Don't ignore + OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION GOMP_MAP_POINTER clauses + on target data/update constructs. + +2015-01-23 Wei Mi + + Backported from trunk. + 2015-01-22 Wei Mi + + PR rtl-optimization/64557 + * dse.c (record_store): Call get_addr for mem_addr. + (check_mem_read_rtx): Likewise. + +2015-01-22 Andreas Krebbel + + * config/s390/s390.md (atomic code attribute): Fix typo "ior" -> + "or". + +2015-01-21 Wei Mi + + Backported from trunk. + 2014-11-22 Jan Hubicka + + PR ipa/63970 + * ipa.c (symbol_table::remove_unreachable_nodes): Mark all inline clones + as having abstract origin used. + * ipa-inline-transform.c (can_remove_node_now_p_1): Drop abstract origin check. + (clone_inlined_nodes): Copy abstract originflag. + * lto-cgraph.c (compute_ltrans_boundary): Use get_create to get abstract origin node. + +2015-01-20 Chung-Lin Tang + + Backport from mainline + * config/nios2/nios2.c (nios2_asm_file_end): Implement + TARGET_ASM_FILE_END hook for adding .note.GNU-stack section when + needed. + (TARGET_ASM_FILE_END): Define. + +2015-01-15 Martin Liska + + Backport from mainline + 2014-11-27 Richard Biener + + PR middle-end/63704 + * alias.c (mems_in_disjoint_alias_sets_p): Remove assert + and instead return false when !fstrict-aliasing. + +2015-01-15 Eric Botcazou + + * expr.c (expand_expr_real_1) : Use the expression to + set the memory attributes in all cases but clear MEM_EXPR if need be. + +2015-01-14 Jakub Jelinek + + Backported from mainline + 2015-01-12 Jakub Jelinek + + PR target/64513 + * config/i386/i386.c (ix86_expand_prologue): Add + REG_FRAME_RELATED_EXPR to %rax and %r10 pushes. + + 2015-01-13 Jakub Jelinek + + PR rtl-optimization/64286 + * ree.c (combine_reaching_defs): Move part of comment earlier, + remove !SCALAR_INT_MODE_P check. + (add_removable_extension): Don't add vector mode + extensions if all uses of the source register aren't the same + vector extensions. + + 2015-01-12 Jakub Jelinek + + PR tree-optimization/64563 + * tree-vrp.c (vrp_evaluate_conditional): Check for VR_RANGE + instead of != VR_VARYING. + +2015-01-14 Marek Polacek + + Backport from mainline + 2015-01-13 Marek Polacek + + PR middle-end/64391 + * trans-mem.c (get_attrs_for): Return NULL_TREE if X is NULL_TREE. + +2015-01-13 Marc Glisse + + PR c++/54442 + * tree.c (build_qualified_type): Use a canonical type for + TYPE_CANONICAL. + +2015-01-13 Pat Haugen + + Backport from mainline + 2014-12-20 Segher Boessenkool + + PR target/64358 + * config/rs6000/rs6000.c (rs6000_split_logical_inner): Swap the + input operands if only the second is inverted. + * config/rs6000/rs6000.md (*boolc3_internal1 for BOOL_128): + Swap BOOL_REGS_OP1 and BOOL_REGS_OP2. Correct arguments to + rs6000_split_logical. + (*boolc3_internal2 for TI2): Swap operands[1] and operands[2]. + +2015-01-13 Renlin Li + + Backport from mainline: + 2014-11-19 Renlin Li + + PR target/63424 + * config/aarch64/aarch64-simd.md (v2di3): New. + +2015-01-13 Oleg Endo + + Backport form mainline + 2015-01-13 Oleg Endo + + PR target/64479 + * rtlanal.c (set_reg_p): Handle SEQUENCE constructs. + +2015-01-09 Jakub Jelinek + + PR rtl-optimization/64536 + * cfgrtl.c (rtl_tidy_fallthru_edge): Handle removal of degenerate + tablejumps. + +2015-01-09 Michael Meissner + + Backport from mainline: + 2015-01-06 Michael Meissner + + PR target/64505 + * config/rs6000/rs6000.c (rs6000_secondary_reload): Return the + correct reload handler if -m32 -mpowerpc64 is used. + +2015-01-09 Sebastian Huber + + Backport from mainline: + 2015-01-09 Sebastian Huber + + * config/rs6000/rtems.h (CPP_OS_RTEMS_SPEC): Define __PPC_CPU_E6500__ + for -mcpu=e6500. + * config/rs6000/t-rtems: Add e6500 multilibs. + +2015-01-09 Sebastian Huber + + Backport from mainline: + 2015-01-09 Sebastian Huber + + * config/rs6000/t-rtems: Add -mno-spe to soft-float multilib for + MPC8540. + +2015-01-09 Sebastian Huber + + Backport from mainline: + 2015-01-09 Sebastian Huber + + * config/rs6000/t-rtems: Use MULTILIB_REQUIRED instead of + MULTILIB_EXCEPTIONS. + +2015-01-09 Renlin Li + + Backport from mainline: + 2014-08-12 Ramana Radhakrishnan + + PR target/61413 + * config/arm/arm.h (TARGET_CPU_CPP_BUILTINS): Fix definition + of __ARM_SIZEOF_WCHAR_T. + +2015-01-08 Christian Bruel + + PR target/64507 + * config/sh/sh-mem.cc (sh_expand_cmpnstr): Check 0 length. + +2015-01-03 John David Anglin + + * config/pa/pa.md (decrement_and_branch_until_zero): Use `Q' constraint + instead of `m' constraint. Likewise for unnamed movb comparison + patterns using reg_before_reload_operand predicate. + * config/pa/predicates.md (reg_before_reload_operand): Tighten + predicate to reject register index and LO_SUM DLT memory forms + after reload. + +2014-12-27 H.J. Lu + + Backport from mainline: + 2014-12-27 H.J. Lu + + PR target/64409 + * config/i386/i386.c (ix86_function_type_abi): Issue an error + when ms_abi attribute is used with x32. + +2014-12-27 Uros Bizjak + + * config/i386/mmx.md (*vec_extractv2sf_1): Do not emit unpckhps. + Emit movshdup for SSE3 and shufps otherwise. + (*vec_extractv2si_1): Do not emit punpckhdq and unpckhps. + Emit pshufd for SSE2 and shufps otherwise. + +2014-12-24 Nick Clifton + + Backport from mainline: + 2014-06-13 Nick Clifton + + * config/rx/rx.h (JUMP_ALIGN): Return the log value if user + requested alignment is active. + (LABEL_ALIGN): Likewise. + (LOOP_ALIGN): Likewise. + + 2014-03-25 Nick Clifton + + * config/rx/rx.c (rx_print_operand): Allow R operator to accept + SImode values. + +2014-12-17 Ulrich Weigand + + Backport from mainline + 2014-12-03 Ulrich Weigand + + PR rtl-optimization/64010 + * reload.c (push_reload): Before reusing a register contained + in an operand as input reload register, ensure that it is not + used in CALL_INSN_FUNCTION_USAGE. + +2014-12-15 Jakub Jelinek + + PR sanitizer/64265 + * tsan.c (instrument_func_entry): Insert __tsan_func_entry + call on edge from entry block to single succ instead + of after labels of single succ of entry block. + +2014-12-14 H.J. Lu + + Backported from mainline + 2014-12-14 H.J. Lu + + PR rtl-optimization/64037 + * combine.c (setup_incoming_promotions): Pass the argument + before any promotions happen to promote_function_mode. + +2014-12-14 H.J. Lu + + Backported from mainline + 2014-12-06 H.J. Lu + + PR target/64200 + * config/i386/i386.c (decide_alg): Don't assert "alg != libcall" + for TARGET_INLINE_STRINGOPS_DYNAMICALLY. + +2014-12-13 Jakub Jelinek + + Backported from mainline + 2014-12-12 Jakub Jelinek + + PR tree-optimization/64269 + * tree-ssa-forwprop.c (simplify_builtin_call): Bail out if + len2 or diff are too large. + +2014-12-11 Eric Botcazou + + * doc/md.texi (Insn Lengths): Fix description of (pc). + +2014-12-11 Renlin Li + + Backport from mainline + 2014-12-11 Renlin Li + + * config/aarch64/aarch64.c (aarch64_parse_cpu): Don't define + selected_tune. + (aarch64_override_options): Use selected_cpu's tuning. + +2014-12-10 Bill Schmidt + + Backport from mainline + 2014-09-02 Bill Schmidt + + * config/rs6000/rs6000-builtin.def (XVCVSXDDP_SCALE): New + built-in definition. + (XVCVUXDDP_SCALE): Likewise. + (XVCVDPSXDS_SCALE): Likewise. + (XVCVDPUXDS_SCALE): Likewise. + * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Add + entries for VSX_BUILTIN_XVCVSXDDP_SCALE, + VSX_BUILTIN_XVCVUXDDP_SCALE, VSX_BUILTIN_XVCVDPSXDS_SCALE, and + VSX_BUILTIN_XVCVDPUXDS_SCALE. + * config/rs6000/rs6000-protos.h (rs6000_scale_v2df): New + prototype. + * config/rs6000/rs6000.c (real.h): New include. + (rs6000_scale_v2df): New function. + * config/rs6000/vsx.md (UNSPEC_VSX_XVCVSXDDP): New unspec. + (UNSPEC_VSX_XVCVUXDDP): Likewise. + (UNSPEC_VSX_XVCVDPSXDS): Likewise. + (UNSPEC_VSX_XVCVDPUXDS): Likewise. + (vsx_xvcvsxddp_scale): New define_expand. + (vsx_xvcvsxddp): New define_insn. + (vsx_xvcvuxddp_scale): New define_expand. + (vsx_xvcvuxddp): New define_insn. + (vsx_xvcvdpsxds_scale): New define_expand. + (vsx_xvcvdpsxds): New define_insn. + (vsx_xvcvdpuxds_scale): New define_expand. + (vsx_xvcvdpuxds): New define_insn. + * doc/extend.texi (vec_ctf): Add new prototypes. + (vec_cts): Likewise. + (vec_ctu): Likewise. + (vec_splat): Likewise. + (vec_div): Likewise. + (vec_mul): Likewise. + + Backport from mainline + 2014-08-28 Bill Schmidt + + * config/rs6000/altivec.h (vec_xl): New #define. + (vec_xst): Likewise. + * config/rs6000/rs6000-builtin.def (XXSPLTD_V2DF): New built-in. + (XXSPLTD_V2DI): Likewise. + (DIV_V2DI): Likewise. + (UDIV_V2DI): Likewise. + (MUL_V2DI): Likewise. + * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Add + entries for VSX_BUILTIN_XVRDPI, VSX_BUILTIN_DIV_V2DI, + VSX_BUILTIN_UDIV_V2DI, VSX_BUILTIN_MUL_V2DI, + VSX_BUILTIN_XXSPLTD_V2DF, and VSX_BUILTIN_XXSPLTD_V2DI). + * config/rs6000/vsx.md (UNSPEC_VSX_XXSPLTD): New unspec. + (UNSPEC_VSX_DIVSD): Likewise. + (UNSPEC_VSX_DIVUD): Likewise. + (UNSPEC_VSX_MULSD): Likewise. + (vsx_mul_v2di): New insn-and-split. + (vsx_div_v2di): Likewise. + (vsx_udiv_v2di): Likewise. + (vsx_xxspltd_): New insn. + + Backport from mainline + 2014-08-20 Bill Schmidt + + * config/rs6000/altivec.h (vec_cpsgn): New #define. + (vec_mergee): Likewise. + (vec_mergeo): Likewise. + (vec_cntlz): Likewise. + * config/rs600/rs6000-c.c (altivec_overloaded_builtins): Add new + entries for VEC_AND, VEC_ANDC, VEC_MERGEH, VEC_MERGEL, VEC_NOR, + VEC_OR, VEC_PACKSU, VEC_XOR, VEC_PERM, VEC_SEL, VEC_VCMPGT_P, + VMRGEW, and VMRGOW. + * doc/extend.texi: Document various forms of vec_cpsgn, + vec_splats, vec_and, vec_andc, vec_mergeh, vec_mergel, vec_nor, + vec_or, vec_perm, vec_sel, vec_sub, vec_xor, vec_all_eq, + vec_all_ge, vec_all_gt, vec_all_le, vec_all_lt, vec_all_ne, + vec_any_eq, vec_any_ge, vec_any_gt, vec_any_le, vec_any_lt, + vec_any_ne, vec_mergee, vec_mergeo, vec_packsu, and vec_cntlz. + + Backport from mainline + 2014-07-20 Bill Schmidt + + * config/rs6000/altivec.md (unspec enum): Fix typo in UNSPEC_VSLDOI. + (altivec_vsldoi_): Likewise. + + +2014-12-10 Jakub Jelinek + + PR tree-optimization/62021 + * omp-low.c (simd_clone_adjust_return_type): Use + vector of pointer_sized_int_node types instead vector of pointer + types. + (simd_clone_adjust_argument_types): Likewise. + +2014-12-10 Bill Schmidt + + Backport from mainline: + 2014-12-09 Bill Schmidt + + PR middle-end/64225 + * tree-ssa-reassoc.c (acceptable_pow_call): Disable transformation + for BUILT_IN_POW when flag_errno_math is present. + +2014-12-10 Marek Polacek + + Backport from mainline + 2014-12-10 Marek Polacek + + PR tree-optimization/61686 + * tree-ssa-reassoc.c (range_entry_cmp): Use q->high instead of + p->high. + +2014-12-09 David Edelsohn + + Backport from mainline + 2014-12-05 David Edelsohn + + * config/rs6000/xcoff.h (ASM_OUTPUT_ALIGNED_LOCAL): Append + alignment to section name. Increase default alignment to + word. + +2014-12-09 Uros Bizjak + + PR bootstrap/64213 + Revert: + 2014-11-28 H.J. Lu + + PR rtl-optimization/64037 + * combine.c (setup_incoming_promotions): Pass the argument + before any promotions happen to promote_function_mode. + +2014-12-09 Richard Biener + + PR tree-optimization/64191 + * tree-vect-stmts.c (vect_stmt_relevant_p): Clobbers are + not relevant (nor are their uses). + +2014-12-07 Oleg Endo + + Backport from mainline + 2014-12-07 Oleg Endo + + PR target/50751 + * config/sh/sh.md (extendqihi2): Allow only for TARGET_SH1. + +2014-12-05 H.J. Lu + + Backport from mainline + 2014-12-02 H.J. Lu + + PR target/64108 + * config/i386/i386.c (decide_alg): Stop only if there aren't + any usable algorithms. + +2014-12-05 H.J. Lu + + Backport from mainline + 2014-11-28 H.J. Lu + + PR rtl-optimization/64037 + * combine.c (setup_incoming_promotions): Pass the argument + before any promotions happen to promote_function_mode. + +2014-12-04 Tobias Burnus + + * configure.ac + (ac_has_isl_schedule_constraints_compute_schedule): + New check. + * graphite-clast-to-gimple.c: For ISL 0.14, include deprecate headers. + * graphite-interchange.c: Ditto. + * graphite-poly.c: Ditto. + * graphite-sese-to-poly.c: Ditto. + * graphite-optimize-isl.c (getScheduleForBandList): Ditto. + Conditionally use ISL 0.13+ functions. + * config.in: Regenerate. + * configure: Regenerate. + +2014-12-04 Jakub Jelinek + + PR c++/56493 + * convert.c (convert_to_real, convert_to_expr, convert_to_complex): + Handle COMPOUND_EXPR. + +2014-12-03 Jakub Jelinek + + PR c/59708 + * expmed.c (expand_widening_mult): Return const0_rtx if + coeff is 0. + +2014-12-03 Martin Jambor + + PR ipa/64153 + * ipa-inline-analysis.c (evaluate_conditions_for_known_args): Check + type sizes before view_converting. + +2014-12-03 Shanyao Chen + + Backport from mainline + 2014-11-20 Ramana Radhakrishnan + + PR target/59593 + * config/arm/arm.md (*movhi_insn): Use right formatting + for immediate. + + 2014-11-19 Felix Yang + Shanyao Chen + + PR target/59593 + * config/arm/arm.md (define_attr "arch"): Add v6t2. + (define_attr "arch_enabled"): Add test for the above. + (*movhi_insn_arch4): Add new alternative. + +2014-12-03 Renlin Li + + Backported from mainline + 2014-12-03 Renlin Li + + PR middle-end/63762 + PR target/63661 + * ira.c (ira): Update preferred class. + +2014-12-02 Uros Bizjak + + PR target/64113 + * config/alpha/alpha.md (call_value_osf_tlsgd): Do not split insn + using post-reload splitter. Use peephole2 pass instead. + (call_value_osf_tlsldm): Ditto. + (TLS_CALL): New int iterator. + (tls): New int attribute. + (call_value_osf_): Merge insn pattern from call_value_osf_tlsgd + and call_value_tlsldm using TLS_CALL int iterator. + +2014-12-02 Ulrich Weigand + + PR target/64115 + * config/rs6000/rs6000.c (rs6000_delegitimize_address): Remove + invalid UNSPEC_TOCREL sanity check under ENABLE_CHECKING. + +2014-12-01 Richard Biener + + PR middle-end/64111 + * tree.c (int_cst_hash_hash): Use TYPE_UID instead of + htab_hash_pointer to not break PCH. + +2014-12-01 Martin Jambor + + PR ipa/63551 + * ipa-inline-analysis.c (evaluate_conditions_for_known_args): Convert + value of the argument to the type of the value in the condition. + +2014-11-28 Jakub Jelinek + + Backported from mainline + 2014-11-27 Jakub Jelinek + + PR middle-end/64067 + * expr.c (expand_expr_addr_expr_1) : + Handle it by returning address of COMPOUND_LITERAL_EXPR_DECL + not only if modifier is EXPAND_INITIALIZER, but whenever + COMPOUND_LITERAL_EXPR_DECL is non-NULL and TREE_STATIC. + + 2014-11-19 Jakub Jelinek + + PR tree-optimization/63915 + * tree-vect-stmts.c (vectorizable_simd_clone_call): Pass + true instead of false as last argument to gsi_replace. + + PR sanitizer/63913 + * ubsan.c: Include tree-eh.h. + (instrument_bool_enum_load): Handle loads that can throw. + + 2014-10-31 Jakub Jelinek + + PR rtl-optimization/63659 + * ree.c (update_reg_equal_equiv_notes): New function. + (combine_set_extension, transform_ifelse): Use it. + +2014-11-28 Ramana Radhakrishnan + + Backport from mainline. + 2014-11-28 Ramana Radhakrishnan + * config/arm/t-aprofile (MULTILIB_MATCHES): New entry for + -march=armv8-a+crc. + +2014-11-26 Richard Biener + + PR middle-end/63738 + * tree-data-ref.c (split_constant_offset_1): Do not follow + SSA edges for SSA names with SSA_NAME_OCCURS_IN_ABNORMAL_PHI. + +2014-11-26 Richard Biener + + Backport from mainline + 2014-11-26 Richard Biener + + PR tree-optimization/62238 + * tree-predcom.c (ref_at_iteration): Unshare the expression + before gimplifying it. + + 2014-11-25 Richard Biener + + PR tree-optimization/61927 + * tree-vect-loop.c (vect_analyze_loop_2): Revert ordering + of group and pattern analysis to the one in GCC 4.8. + + 2014-11-07 Richard Biener + + PR tree-optimization/63605 + * fold-const.c (fold_binary_loc): Properly use element_precision + for types that may not be scalar. + + 2014-10-28 Richard Biener + + PR middle-end/63665 + * fold-const.c (fold_comparison): Properly guard simplifying + against INT_MAX/INT_MIN with !TYPE_OVERFLOW_WRAPS. + +2014-11-25 Rohit + + PR bootstrap/63703 + * config/rs6000/darwin.h (REGISTER_NAMES): Update based on 32 newly + added GCC hard register numbers for SPE high registers. + +2014-11-23 Oleg Endo + + Backport from mainline + 2014-11-23 Oleg Endo + + PR target/53976 + * config/sh/sh_optimize_sett_clrt.cc + (sh_optimize_sett_clrt::find_last_ccreg_values): Return bool instead + of void. Abort at complex edges. + (sh_optimize_sett_clrt::execute): Do nothing if find_last_ccreg_values + returned false. + 2014-11-22 Uros Bizjak - * params.def (PARAM_MAX_COMPLETELY_PEELED_INSNS): Increase to 200. - * config/i386/i386.c (ix86_option_override_internal): Do not increase - PARAM_MAX_COMPLETELY_PEELED_INSNS. + * params.def (PARAM_MAX_COMPLETELY_PEELED_INSNS): Increase to 200. + * config/i386/i386.c (ix86_option_override_internal): Do not increase + PARAM_MAX_COMPLETELY_PEELED_INSNS. + +2014-11-22 Oleg Endo + + Backport from mainline + 2014-11-22 Oleg Endo + + PR target/63783 + PR target/51244 + * config/sh/sh_treg_combine.cc (sh_treg_combine::make_not_reg_insn): + Do not emit bitwise not insn. Emit logical not insn sequence instead. + Adjust related comments throughout the file. + +2014-11-22 Oleg Endo + + Backport from mainline + 2014-11-20 Segher Boessenkool + + PR target/60111 + * config/sh/sh.c: Use signed char for signed field. + +2014-11-21 Bill Schmidt + + PR target/63673 + * config/rs6000/rs6000-c.c (altivec_overloaded_builtins): Allow + the base pointer of vec_vsx_ld and vec_vsx_st to take a pointer to + double. + +2014-11-21 Richard Biener + + PR tree-optimization/61750 + * tree-ssa-forwprop.c (simplify_vce): Verify type sizes + match for the resulting VIEW_CONVERT_EXPR. + +2014-11-19 Uros Bizjak + + PR target/63947 + * config/i386/i386.c (put_condition_code) : + Output "b" and "nb" suffix for FP mode. + +2014-11-19 Tom de Vries + + Backport from mainline + PR tree-optimization/62167 + * tree-ssa-tail-merge.c (stmt_local_def): Handle statements with vuse + conservatively. + (gimple_equal_p): Don't use vn_valueize to compare for lhs equality of + assigns. + +2014-11-16 Eric Botcazou + + * doc/tm.texi.in (TARGET_FLAGS_REGNUM): Move around. + * doc/tm.texi: Regenerate. + +2014-11-14 Felix Yang + + Backport from mainline + 2014-11-14 Felix Yang + Jiji Jiang + + * config/aarch64/aarch64-simd.md (*aarch64_simd_ld1r): Use + VALL mode iterator instead of VALLDI. + +2014-11-13 Teresa Johnson + + PR tree-optimization/63841 + * tree-ssa-strlen.c (strlen_optimize_stmt): Ignore clobbers. + +2014-11-13 Christophe Lyon + + Backport from mainline + 2014-11-02 Michael Collison + + * config/arm/arm.h (CLZ_DEFINED_VALUE_AT_ZERO) : Update + to support vector modes. + (CTZ_DEFINED_VALUE_AT_ZERO): Ditto. + +2014-11-13 Eric Botcazou + + * doc/tm.texi.in (SELECT_CC_MODE): Update example. + (REVERSIBLE_CC_MODE): Fix example. + (REVERSE_CONDITION): Fix typo. + * doc/tm.texi: Regenerate. + +2014-11-12 Jakub Jelinek + + PR ipa/63838 + * ipa-pure-const.c (propagate_nothrow): Walk w->indirect_calls + chain instead of node->indirect_calls. + +2014-11-11 Eric Botcazou + + PR target/61535 + * config/sparc/sparc.c (function_arg_vector_value): Deal with vectors + smaller than 8 bytes. + (sparc_function_arg_1): Tweak. + (sparc_function_value_1): Tweak. + +2014-11-08 Eric Botcazou + + * config/arm/arm.c (arm_set_return_address): Mark the store as frame + related, if any. + (thumb_set_return_address): Likewise. + +2014-11-07 Daniel Hellstrom + + * config.gcc (sparc-*-rtems*): Clean away unused t-elf. + * config/sparc/t-rtems: Add leon3v7 and muser-mode multilibs. + +2014-11-07 Marek Polacek + + Backported from mainline + 2014-10-23 Marek Polacek + + * c-ubsan.c (ubsan_instrument_shift): Perform the MINUS_EXPR + in unsigned type. + +2014-11-06 John David Anglin + + * config/pa/pa.md (trap): New insn. Add "trap" to attribute type. + Don't allow trap insn in in_branch_delay, in_nullified_branch_delay + or in_call_delay. + +2014-11-06 Daniel Hellstrom + + * config.gcc (sparc*-*-*): Accept mcpu=leon3v7 processor. + * doc/invoke.texi (SPARC options): Add mcpu=leon3v7 comment. + * config/sparc/leon.md (leon3_load, leon_store, leon_fp_*): Handle + leon3v7 as leon3. + * config/sparc/sparc-opts.h (enum processor_type): Add LEON3V7. + * config/sparc/sparc.c (sparc_option_override): Add leon3v7 support. + * config/sparc/sparc.h (TARGET_CPU_leon3v7): New define. + * config/sparc/sparc.md (cpu): Add leon3v7. + * config/sparc/sparc.opt (enum processor_type): Add leon3v7. + +2014-11-05 Uros Bizjak + + PR target/63538 + * config/i386/i386.c (in_large_data_p): Reject automatic variables. + (ix86_encode_section_info): Do not check for non-automatic varibles + when setting SYMBOL_FLAG_FAR_ADDR flag. + (x86_64_elf_select_section): Do not check ix86_cmodel here. + (x86_64_elf_unique_section): Ditto. + (x86_elf_aligned_common): Emit tab before .largecomm. + +2014-11-05 Uros Bizjak + + Backport from mainline: + 2014-10-20 Uros Bizjak + + * varasm.c (const_alias_set): Remove. + (init_varasm_once): Remove initialization of const_alias_set. + (build_constant_desc): Do not set alias set to const_alias_set. + + Backport from mainline: + 2014-10-14 Uros Bizjak + + PR rtl-optimization/63475 + * alias.c (true_dependence_1): Always use get_addr to extract + true address operands from x_addr and mem_addr. Use extracted + address operands to check for references with alignment ANDs. + Use extracted address operands with find_base_term and + base_alias_check. For noncanonicalized operands call canon_rtx with + extracted address operand. + (write_dependence_1): Ditto. + (may_alias_p): Ditto. Remove unused calls to canon_rtx. + + Backport from mainline: + 2014-10-10 Uros Bizjak + + PR rtl-optimization/63483 + * alias.c (true_dependence_1): Do not exit early for MEM_READONLY_P + references when alignment ANDs are involved. + (write_dependence_p): Ditto. + (may_alias_p): Ditto. + +2014-10-31 DJ Delorie + + * expmed.c (strict_volatile_bitfield_p): Fix off-by-one error. + +2014-10-31 Kyrylo Tkachov + + * config/aarch64/aarch64-elf-raw.h (CA53_ERR_835769_SPEC): Define. + (LINK_SPEC): Include CA53_ERR_835769_SPEC. + * config/aarch64/aarch64-linux.h (CA53_ERR_835769_SPEC): Define. + (LINK_SPEC): Include CA53_ERR_835769_SPEC. + +2014-10-31 Jakub Jelinek + + PR sanitizer/63697 + * tree-vrp.c (simplify_internal_call_using_ranges): For subcode == + MINUS_EXPR, check overflow on vr0.min - vr1.max and vr0.max - vr1.min + instead of vr0.min - vr1.min and vr0.max - vr1.max. + +2014-10-30 Georg-Johann Lay + + PR63633 + * config/avr/avr-protos.h (regmask): New inline function. + (avr_fix_inputs, avr_emit3_fix_outputs): New protos. + * config/avr/avr.c (avr_fix_operands, avr_move_fixed_operands) + (avr_fix_inputs, avr_emit3_fix_outputs): New functions. + * config/avr/avr-fixed.md (mulqq3_nomul, muluqq3_nomul) + (mul3, mul3, 3, 3) + (3, round3): Fix input operands. + * config/avr/avr-dimode.md (add3, sub3) + (3, 3, cbranch4) + (3, mulsidi3): Fix input operands. + * config/avr/avr.md (mulqi3_call, mulhi3_call, mulsi3, mulpsi3) + (mulusi3, mulssi3, mulohisi3, mulhisi3) + (usmulhisi3, mulhi3_highpart, mulsqipsi3) + (fmul, fmuls, fmulsu): Fix operands. Turn insn into expander as + needed. + +2014-10-30 Jakub Jelinek + + * BASE-VER: Set to 4.9.3. + * DEV-PHASE: Set to prerelease. + +2014-10-30 Release Manager + + * GCC 4.9.2 released. + +2014-10-29 Kyrylo Tkachov + + * config/aarch64/aarch64.c (aarch64_madd_needs_nop): Restore + recog state after aarch64_prev_real_insn call. + +2014-10-27 Guozhi Wei + + PR tree-optimization/63530 + tree-vect-data-refs.c (vect_create_addr_base_for_vector_ref): Set + pointer alignment according to DR_MISALIGNMENT. + +2014-10-25 Yury Gribov + + PR sanitizer/63638 + * asan.c (enum asan_check_flags): Fixed ASAN_CHECK_LAST. + +2014-10-24 Kyrylo Tkachov + + * config/aarch64/aarch64-elf-raw.h (CA53_ERR_835769_SPEC): Define. + (LINK_SPEC): Include CA53_ERR_835769_SPEC. + * config/aarch64/aarch64-linux.h (CA53_ERR_835769_SPEC): Define. + (LINK_SPEC): Include CA53_ERR_835769_SPEC. + +2014-10-24 Markus Trippelsdorf + + PR bootstrap/63632 + * collect2.c (main): Filter out -fno-lto. + +2014-10-22 Richard Biener + Tobias Burnus + + PR lto/63603 + * gcc.c (LINK_COMMAND_SPEC): Add %{fno-lto}. + +2014-10-21 Jakub Jelinek + + PR tree-optimization/63563 + * tree-vect-data-refs.c (vect_analyze_data_ref_accesses): Bail out + if either dra or drb stmts are not normal loads/stores. + +2014-10-17 Jakub Jelinek + + * asan.c (instrument_derefs): Allow instrumentation of odd-sized + accesses even for -fsanitize=address. + (execute_sanopt): Only allow use_calls for -fsanitize=kernel-address. + + PR tree-optimization/63302 + * tree-ssa-reassoc.c (optimize_range_tests_xor, + optimize_range_tests_diff): Use !integer_pow2p () instead of + tree_log2 () < 0. + +2014-10-16 Yury Gribov + + * asan.c (instrument_derefs): Enable unaligned path for KASan. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-10-03 Yury Gribov + + * asan.c (asan_finish_file): Disable __asan_init calls for KASan; + don't emit empty ctors. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-09-01 Yury Gribov + + PR sanitizer/61897 + PR sanitizer/62140 + + * asan.c (asan_mem_ref_get_end): Handle non-ptroff_t lengths. + (build_check_stmt): Likewise. + (instrument_strlen_call): Likewise. + (asan_expand_check_ifn): Likewise and fix types. + (maybe_cast_to_ptrmode): New function. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-08-18 Yury Gribov + + PR sanitizer/62089 + + * asan.c (instrument_derefs): Fix bitfield check. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-08-11 Yury Gribov + + * asan.c (asan_check_flags): New enum. + (build_check_stmt_with_calls): Removed function. + (build_check_stmt): Split inlining logic to + asan_expand_check_ifn. + (instrument_derefs): Rename parameter. + (instrument_mem_region_access): Rename parameter. + (instrument_strlen_call): Likewise. + (asan_expand_check_ifn): New function. + (asan_instrument): Remove old code. + (pass_sanopt::execute): Change handling of + asan-instrumentation-with-call-threshold. + (asan_clear_shadow): Fix formatting. + (asan_function_start): Likewise. + (asan_emit_stack_protection): Likewise. + * doc/invoke.texi (asan-instrumentation-with-call-threshold): + Update description. + * internal-fn.c (expand_ASAN_CHECK): New function. + * internal-fn.def (ASAN_CHECK): New internal function. + * params.def (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD): + Update description. + (PARAM_ASAN_USE_AFTER_RETURN): Likewise. + * tree.c: Small comment fix. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-08-11 Yury Gribov + + * gimple.c (gimple_call_fnspec): Support internal functions. + (gimple_call_return_flags): Use const. + * Makefile.in (GTFILES): Add internal-fn.h to list of GC files. + * internal-fn.def: Add fnspec information. + * internal-fn.h (internal_fn_fnspec): New function. + (init_internal_fns): Declare new function. + * internal-fn.c (internal_fn_fnspec_array): New global variable. + (init_internal_fns): New function. + * tree-core.h: Update macro call. + * tree.c (build_common_builtin_nodes): Initialize internal fns. + + Backport from mainline + 2014-08-12 Yury Gribov + + * internal-fn.c (init_internal_fns): Fix off-by-one. -2014-10-29 Kyrylo Tkachov +2014-10-16 Yury Gribov - * config/aarch64/aarch64.c (aarch64_madd_needs_nop): Restore - recog state after aarch64_prev_real_insn call. + Backport from mainline + 2014-07-31 Yury Gribov -2014-10-27 Guozhi Wei + * doc/cpp.texi (__SANITIZE_ADDRESS__): Updated description. + * doc/invoke.texi (-fsanitize=kernel-address): Describe new option. + * flag-types.h (SANITIZE_USER_ADDRESS, SANITIZE_KERNEL_ADDRESS): + New enums. + * gcc.c (sanitize_spec_function): Support new option. + (SANITIZER_SPEC): Remove now redundant check. + * opts.c (common_handle_option): Support new option. + (finish_options): Check for incompatibilities. + * toplev.c (process_options): Split userspace-specific checks. - PR tree-optimization/63530 - tree-vect-data-refs.c (vect_create_addr_base_for_vector_ref): Set - pointer alignment according to DR_MISALIGNMENT. +2014-10-16 Yury Gribov -2014-10-24 Kyrylo Tkachov + Backport from mainline + 2014-06-24 Max Ostapenko - * config/aarch64/aarch64-elf-raw.h (CA53_ERR_835769_SPEC): Define. - (LINK_SPEC): Include CA53_ERR_835769_SPEC. - * config/aarch64/aarch64-linux.h (CA53_ERR_835769_SPEC): Define. - (LINK_SPEC): Include CA53_ERR_835769_SPEC. + * asan.c (instrument_strlen_call): Do not instrument first byte in + strlen if already instrumented. -2014-10-21 Jakub Jelinek +2014-10-16 Yury Gribov - PR tree-optimization/63563 - * tree-vect-data-refs.c (vect_analyze_data_ref_accesses): Bail out - if either dra or drb stmts are not normal loads/stores. + Backport from mainline + 2014-06-16 Yury Gribov + + * asan.c (check_func): New function. + (maybe_create_ssa_name): Likewise. + (build_check_stmt_with_calls): Likewise. + (use_calls_p): Likewise. + (report_error_func): Change interface. + (build_check_stmt): Allow non-integer lengths; add support + for new parameter. + (asan_instrument): Likewise. + (instrument_mem_region_access): Moved code to + build_check_stmt. + (instrument_derefs): Likewise. + (instrument_strlen_call): Likewise. + * cfgcleanup.c (old_insns_match_p): Add support for new + functions. + * doc/invoke.texi: Describe new parameter. + * params.def: Define new parameter. + * params.h: Likewise. + * sanitizer.def: Describe new builtins. + + Backport from mainline + 2014-06-16 Yury Gribov + + * asan.c (build_check_stmt): Fix maybe-uninitialized warning. + + Backport from mainline + 2014-06-18 Yury Gribov + + PR sanitizer/61530 + + * asan.c (build_check_stmt): Add condition. + + Backport from mainline + 2014-06-18 Yury Gribov + + PR sanitizer/61547 + + * asan.c (instrument_strlen_call): Fixed instrumentation of + trailing byte. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-05-30 Jakub Jelinek + + * asan.c (report_error_func): Add SLOW_P argument, use + BUILT_IN_ASAN_*_N if set. + (build_check_stmt): Likewise. + (instrument_derefs): If T has insufficient alignment, + force same handling as for odd sizes. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-05-30 Jakub Jelinek + + * sanitizer.def (BUILT_IN_ASAN_REPORT_LOAD_N, + BUILT_IN_ASAN_REPORT_STORE_N): New. + * asan.c (struct asan_mem_ref): Change access_size type to + HOST_WIDE_INT. + (asan_mem_ref_init, asan_mem_ref_new, get_mem_refs_of_builtin_call, + update_mem_ref_hash_table): Likewise. + (asan_mem_ref_hasher::hash): Hash in a HWI. + (report_error_func): Change size_in_bytes argument to HWI. + Use *_N builtins if size_in_bytes is larger than 16 or not power of + two. + (build_shadow_mem_access): New function. + (build_check_stmt): Use it. Change size_in_bytes argument to HWI. + Handle size_in_bytes not power of two or larger than 16. + (instrument_derefs): Don't give up if size_in_bytes is not + power of two or is larger than 16. + +2014-10-15 Vladimir Makarov + + PR rtl-optimization/63448 + * lra-int.h (LRA_MAX_CONSTRAINT_ITERATION_NUMBER): Remove. + (LRA_MAX_ASSIGNMENT_ITERATION_NUMBER): New. + (LRA_MAX_INHERITANCE_PASSES): Use it. + (lra_constraint_iter_after_spill): Remove. + (lra_assignment_iter): New. + (lra_assignment_iter_after_spill): New. + * lra-assigns.c (lra_assignment_iter): New. + (lra_assignment_iter_after_spill): New. + (former_reload_pseudo_spill_p): New. + (spill_for): Set up former_reload_pseudo_spill_p. + (setup_live_pseudos_and_spill_after_risky): Ditto. + (assign_by_spills): Ditto. + (lra_assign): Increment lra_assignment_iter. Print the iteration + number. Reset former_reload_pseudo_spill_p. Check + lra_assignment_iter_after_spill. + * lra.c (lra): Remove lra_constraint_iter_after_spill. Initialize + lra_assignment_iter and lra_assignment_iter_after_spill. + * lra-constraints.c (lra_constraint_iter_after_spill): Remove. + (lra_constraints): Remove code with + lra_assignment_iter_after_spill. + +2014-10-15 Eric Botcazou + + * stor-layout.c (self_referential_size): Do not promote arguments. + +2014-10-15 Richard Biener + + Backport from mainline + 2014-08-15 Richard Biener + + PR tree-optimization/62031 + * tree-data-ref.c (dr_analyze_indices): Do not set + DR_UNCONSTRAINED_BASE. + (dr_may_alias_p): All indirect accesses have to go the + formerly DR_UNCONSTRAINED_BASE path. + * tree-data-ref.h (struct indices): Remove + unconstrained_base member. + (DR_UNCONSTRAINED_BASE): Remove. + +2014-10-12 Bill Schmidt + + Backport from mainline r215880 + 2014-10-03 Bill Schmidt + + * config/rs6000/rs6000-c.c (altivec_resolve_overloaded_builtin): + Issue a warning message when vec_lvsl or vec_lvsr is used with a + little endian target. + + Backport from mainline r215882 + 2014-10-03 Bill Schmidt + + * altivec.md (altivec_lvsl): New define_expand. + (altivec_lvsl_direct): Rename define_insn from altivec_lvsl. + (altivec_lvsr): New define_expand. + (altivec_lvsr_direct): Rename define_insn from altivec_lvsr. + * rs6000.c (rs6000_expand_builtin): Change to use + altivec_lvs[lr]_direct; remove commented-out code. + +2014-10-10 Richard Biener + + PR tree-optimization/63379 + * tree-vect-slp.c (vect_get_constant_vectors): Do not compute + a neutral operand for min/max when it is not a reduction chain. + +2014-10-10 Kyrylo Tkachov + + Backport from mainline + 2014-10-10 Kyrylo Tkachov + + * configure.ac: Add --enable-fix-cortex-a53-835769 option. + * configure: Regenerate. + * config/aarch64/aarch64.c (aarch64_override_options): Handle + TARGET_FIX_ERR_A53_835769_DEFAULT. + * config/aarch64/aarch64.opt (mfix-cortex-a53-835769): Set Init + value to 2. + * doc/install.texi (aarch64*-*-*): Document new + --enable-fix-cortex-a53-835769 option. + +2014-10-10 Kyrylo Tkachov + + Backport from mainline + 2014-10-10 Kyrylo Tkachov + Ramana Radhakrishnan + + * config/aarch64/aarch64.h (FINAL_PRESCAN_INSN): Define. + (ADJUST_INSN_LENGTH): Define. + * config/aarch64/aarch64.opt (mfix-cortex-a53-835769): New option. + * config/aarch64/aarch64.c (is_mem_p): New function. + (is_memory_op): Likewise. + (aarch64_prev_real_insn): Likewise. + (is_madd_op): Likewise. + (dep_between_memop_and_curr): Likewise. + (aarch64_madd_needs_nop): Likewise. + (aarch64_final_prescan_insn): Likewise. + * doc/invoke.texi (AArch64 Options): Document -mfix-cortex-a53-835769 + and -mno-fix-cortex-a53-835769 options. + +2014-10-10 Richard Biener + + PR tree-optimization/63380 + * tree-ssa-tail-merge.c (stmt_local_def): Exclude stmts that + may trap. + +2014-10-09 Richard Biener + + PR tree-optimization/61969 + * tree-nrv.c (pass_nrv::execute): Properly test for automatic + variables. + +2014-10-09 Uros Bizjak + + Backport from mainline + 2014-10-09 Uros Bizjak + + PR rtl-optimization/57003 + * regcprop.c (copyprop_hardreg_forward_1): If ksvd.ignore_set_reg, + also check CALL_INSN_FUNCTION_USAGE for clobbers again after + killing regs_invalidated_by_call. + +2014-10-08 Rong Xu + + * gcov-tool.c (profile_overlap): New driver function + to compute profile overlap. + (print_overlap_usage_message): New. + (overlap_usage): New. + (do_overlap): New. + (print_usage): Add calls to overlap function. + (main): Ditto. + * doc/gcov-tool.texi: Add documentation. + +2014-10-08 Oleg Endo + + Backport from mainline + 2014-10-08 Oleg Endo + + PR target/52941 + * config/sh/sync.md (atomic_exchangesi_hard, atomic_exchange_hard, + atomic_fetch_si_hard, + atomic_fetch__hard, atomic_fetch_nandsi_hard, + atomic_fetch_nand_hard, atomic__fetchsi_hard, + atomic__fetch_hard, atomic_nand_fetchsi_hard, + atomic_nand_fetch_hard): Add missing set of T_REG. + +2014-10-03 Jan Hubicka + + PR ipa/61144 + * varpool.c (ctor_for_folding): Do not fold WEAK symbols. + +2014-10-03 Jan Hubicka + + PR ipa/62121 + * ipa-devirt.c (restrict_to_inner_class): Do not ICE when type is + unknown. + +2014-10-03 Jan Hubicka + + PR lto/62026 + * lto-streamer-out.c (lto_output): Handle thunks correctly. + * cgraphclones.c (duplicate_thunk_for_node): Get thunk's arguments. + +2014-10-03 Jakub Jelinek + + PR libgomp/61200 + * omp-low.c (taskreg_contexts): New variable. + (scan_omp_parallel): Push newly created context into taskreg_contexts + vector and move record layout code to finish_taskreg_scan. + (scan_omp_task): Likewise. + (finish_taskreg_scan): New function. + (execute_lower_omp): Call finish_taskreg_scan on all taskreg_contexts + vector elements and release it. + +2014-10-02 Martin Jambor + + PR tree-optimization/63375 + * tree-sra.c (build_access_from_expr_1): Disqualify volatile + references. + +2014-10-01 Jakub Jelinek + + PR debug/63342 + * dwarf2out.c (loc_list_from_tree): Handle TARGET_MEM_REF and + SSA_NAME. + + PR target/63428 + * config/i386/i386.c (expand_vec_perm_pshufb): Fix up rperm[0] + argument to avx2_permv2ti. + + PR c++/63306 + Backported from mainline + 2014-08-01 James Greenhalgh + + PR regression/61510 + * cgraphunit.c (analyze_functions): Use get_create rather than get + for decls which are clones of abstract functions. + +2014-10-01 Jakub Jelinek + + Backported from mainline + 2014-09-18 Vladimir Makarov + + PR debug/63285 + * haifa-sched.c (schedule_block): Advance cycle at the end of BB + if advance != 0. + + 2014-09-10 Jan Hubicka + + PR tree-optimization/63186 + * ipa-split.c (test_nonssa_use): Skip nonforced labels. + (mark_nonssa_use): Likewise. + (verify_non_ssa_vars): Verify all header blocks for label + definitions. + +2014-10-01 Kyrylo Tkachov + + Backport from mainline + 2014-10-01 Kyrylo Tkachov + + * config/arm/arm.md (*store_minmaxsi): Disable for arm_restrict_it. + +2014-10-01 Uros Bizjak + + Backport from mainline + 2014-09-30 Uros Bizjak + + * config/i386/i386.md (fmodxf3): Enable for flag_finite_math_only only. + (fmod3): Ditto. + (fpremxf4_i387): Ditto. + (reminderxf3): Ditto. + (reminder3): Ditto. + (fprem1xf4_i387): Ditto. + +2014-09-30 David Malcolm + + PR plugins/63410 + * Makefile.in (PLUGIN_HEADERS): Add pass-instances.def. + +2014-09-30 Jakub Jelinek + + PR inline-asm/63282 + * ifcvt.c (dead_or_predicable): Don't call redirect_jump_1 + or invert_jump_1 if jump isn't any_condjump_p. + +2014-09-29 James Clarke + Francois-Xavier Coudert + + PR target/61407 + * config/darwin-c.c (version_as_macro): Added extra 0 for OS X 10.10 + and above. + * config/darwin-driver.c (darwin_find_version_from_kernel): Removed + kernel version check to avoid incrementing it after every major OS X + release. + (darwin_default_min_version): Avoid static memory buffer. + +2014-09-29 Charles Baylis + + Backport from mainline r212303 + PR target/49423 + * config/arm/arm-protos.h (arm_legitimate_address_p, + arm_is_constant_pool_ref): Add prototypes. + * config/arm/arm.c (arm_legitimate_address_p): Remove static. + (arm_is_constant_pool_ref) New function. + * config/arm/arm.md (unaligned_loadhis, arm_zero_extendhisi2_v6, + arm_zero_extendqisi2_v6): Use Uh constraint for memory operand. + (arm_extendhisi2, arm_extendhisi2_v6): Use Uh constraint for memory + operand and remove pool_range and neg_pool_range attributes. + (arm_extendqihi_insn, arm_extendqisi, arm_extendqisi_v6): Remove + pool_range and neg_pool_range attributes. + * config/arm/constraints.md (Uh): New constraint. (Uq): Don't allow + constant pool references. + +2014-09-29 Jakub Jelinek + + PR middle-end/63247 + * omp-low.c (lower_omp_target): For OMP_CLAUSE_MAP_POINTER + of ARRAY_TYPE, if not OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION + use the alignment of avar rather than ovar. + +2014-09-28 John David Anglin + + * config/pa/pa.c (pa_output_function_epilogue): Only update + last_address when a nonnote insn is found. + +2014-09-25 Oleg Endo + + Backport from mainline + 2014-09-25 Nick Clifton + 2014-09-25 Oleg Endo + + PR target/62218 + * config/sh/sync.md (atomic_fetch_nand_soft_imask, + atomic_test_and_set_soft_imask): Fix typo in instruction sequence. + +2014-09-25 Bill Schmidt + + Backport from mainline r215559 + 2014-09-25 Bill Schmidt + + PR target/63335 + * config/rs6000/rs6000-c.c (altivec_build_resolved_builtin): + Exclude VSX_BUILTIN_XVCMPGEDP_P from special handling. 2014-09-25 Jakub Jelinek @@ -43,6 +1435,374 @@ - 1 instead of setting offset, pass byte_offset down to vect_create_data_ref_ptr. +2014-09-23 Michael Meissner + + Backport from mainline + 2014-09-23 Michael Meissner + + * config/rs6000/rs6000.md (f32_vsx): New mode attributes to + refine the constraints used on 32/64-bit floating point moves. + (f32_av): Likewise. + (f64_vsx): Likewise. + (f64_dm): Likewise. + (f64_av): Likewise. + (BOOL_REGS_OUTPUT): Use wt constraint for TImode instead of wa. + (BOOL_REGS_OP1): Likewise. + (BOOL_REGS_OP2): Likewise. + (BOOL_REGS_UNARY): Likewise. + (mov_hardfloat, SFmode/SDmode): Tighten down constraints for + 32/64-bit floating point moves. Do not use wa, instead use ww/ws + for moves involving VSX registers. Do not use constraints that + target VSX registers for decimal types. + (mov_hardfloat32, DFmode/DDmode): Likewise. + (mov_hardfloat64, DFmode/DDmode): Likewise. + +2014-09-22 Marek Polacek + + Backport from mainline + 2014-05-21 Marek Polacek + + PR sanitizer/61272 + * ubsan.c (is_ubsan_builtin_p): Turn assert into a condition. + +2014-09-22 Jakub Jelinek + + PR debug/63328 + * omp-low.c (ipa_simd_modify_stmt_ops): For debug stmts + insert a debug source bind stmt setting DEBUG_EXPR_DECL + instead of a normal gimple assignment stmt. + +2014-09-19 Michael Meissner + + Back port from trunk: + 2014-09-19 Michael Meissner + + * config/rs6000/predicates.md (fusion_gpr_mem_load): Move testing + for base_reg_operand to be common between LO_SUM and PLUS. + (fusion_gpr_mem_combo): New predicate to match a fused address + that combines the addis and memory offset address. + + * config/rs6000/rs6000-protos.h (fusion_gpr_load_p): Change + calling signature. + (emit_fusion_gpr_load): Likewise. + + * config/rs6000/rs6000.c (fusion_gpr_load_p): Change calling + signature to pass each argument separately, rather than + using an operands array. Rewrite the insns found by peephole2 to + be a single insn, rather than hoping the insns will still be + together when the peephole pass is done. Drop being called via a + normal peephole. + (emit_fusion_gpr_load): Change calling signature to be called from + the fusion_gpr_load_ insns with a combined memory address + instead of the peephole pass passing the addis and offset + separately. + + * config/rs6000/rs6000.md (UNSPEC_FUSION_GPR): New unspec for GPR + fusion. + (power8 fusion peephole): Drop support for doing power8 via a + normal peephole that was created by the peephole2 pass. + (power8 fusion peephole2): Create a new insn with the fused + address, so that the fused operation is kept together after + register allocation is done. + (fusion_gpr_load_): Likewise. + +2014-09-18 Jakub Jelinek + + PR c++/62017 + * asan.c (transform_statements): Don't instrument clobber statements. + +2014-09-17 Jakub Jelinek + + PR debug/63284 + * tree-cfgcleanup.c (fixup_noreturn_call): Don't split block + if there are only debug stmts after the noreturn call, instead + remove the debug stmts. + +2014-09-17 Sebastian Huber + + * config.gcc (*-*-rtems*): Default to 'rtems' thread model. + Enable selection of 'posix' or no thread model. + +2014-09-16 John David Anglin + + PR target/61853 + * config/pa/pa.c (pa_function_value): Directly handle aggregates + that fit exactly in a word or double word. + +2014-09-15 Sharad Singhai + + Google Ref b/17114943 + + * l-ipo.c (promote_static_var_func): Update RTL with the unique name. + +2014-09-15 Markus Trippelsdorf + + * doc/install.texi (Options specification): add + --disable-libsanitizer item. + +2014-09-12 DJ Delorie + + * config/msp430/msp430.md (extendhipsi2): Use 20-bit form of RLAM/RRAM. + (extend_and_shift1_hipsi2): Likewise. + (extend_and_shift2_hipsi2): Likewise. + +2014-09-12 Martin Jambor + + PR ipa/61654 + * cgraph.h (cgraph_analyze_function): Declare. + * cgraphunit.c: (analyze_function): Remove forward declaration, + rename to cgraph_analyze_function, made external. + * cgraphclones.c (duplicate_thunk_for_node): Copy arguments of the + new decl properly. Analyze the new thunk if it is expanded. + +2014-09-11 H.J. Lu + + Backport from mainline + 2014-09-11 H.J. Lu + + PR target/63228 + * config/i386/i386.c (ix86_option_override_internal): Also turn + off OPTION_MASK_ABI_X32 for -m16. + +2014-09-11 James Greenhalgh + + Backport from mainline. + 2014-09-11 James Greenhalgh + + * config/aarch64/arm_neon.h (vmull_high_lane_s16): Fix argument + types. + (vmull_high_lane_s32): Likewise. + (vmull_high_lane_u16): Likewise. + (vmull_high_lane_u32): Likewise. + +2014-09-11 Alan Lawrence + + Backport r214946 from mainline + 2014-09-05 Alan Lawrence + + * config/aarch64/aarch64.md (adddi3_aarch64): Set type to neon_add. + +2014-09-11 Alan Lawrence + + Backport r214953 from mainline + 2014-09-05 Alan Lawrence + + * config/aarch64/arm_neon.h (int32x1_t, int16x1_t, int8x1_t, + uint32x1_t, uint16x1_t, uint8x1_t): Remove typedefs. + + (vqabsb_s8, vqabsh_s16, vqabss_s32, vqaddb_s8, vqaddh_s16, vqadds_s32, + vqaddb_u8, vqaddh_u16, vqadds_u32, vqdmlalh_s16, vqdmlalh_lane_s16, + vqdmlals_s32, vqdmlslh_s16, vqdmlslh_lane_s16, vqdmlsls_s32, + vqdmulhh_s16, vqdmulhh_lane_s16, vqdmulhs_s32, vqdmulhs_lane_s32, + vqdmullh_s16, vqdmullh_lane_s16, vqdmulls_s32, vqdmulls_lane_s32, + vqmovnh_s16, vqmovns_s32, vqmovnd_s64, vqmovnh_u16, vqmovns_u32, + vqmovnd_u64, vqmovunh_s16, vqmovuns_s32, vqmovund_s64, vqnegb_s8, + vqnegh_s16, vqnegs_s32, vqrdmulhh_s16, vqrdmulhh_lane_s16, + vqrdmulhs_s32, vqrdmulhs_lane_s32, vqrshlb_s8, vqrshlh_s16, + vqrshls_s32, vqrshlb_u8, vqrshlh_u16, vqrshls_u32, vqrshrnh_n_s16, + vqrshrns_n_s32, vqrshrnd_n_s64, vqrshrnh_n_u16, vqrshrns_n_u32, + vqrshrnd_n_u64, vqrshrunh_n_s16, vqrshruns_n_s32, vqrshrund_n_s64, + vqshlb_s8, vqshlh_s16, vqshls_s32, vqshlb_u8, vqshlh_u16, vqshls_u32, + vqshlb_n_s8, vqshlh_n_s16, vqshls_n_s32, vqshlb_n_u8, vqshlh_n_u16, + vqshls_n_u32, vqshlub_n_s8, vqshluh_n_s16, vqshlus_n_s32, + vqshrnh_n_s16, vqshrns_n_s32, vqshrnd_n_s64, vqshrnh_n_u16, + vqshrns_n_u32, vqshrnd_n_u64, vqshrunh_n_s16, vqshruns_n_s32, + vqshrund_n_s64, vqsubb_s8, vqsubh_s16, vqsubs_s32, vqsubb_u8, + vqsubh_u16, vqsubs_u32, vsqaddb_u8, vsqaddh_u16, vsqadds_u32, + vuqaddb_s8, vuqaddh_s16, vuqadds_s32): Replace all int{32,16,8}x1_t + with int{32,16,8}_t. + +2014-09-11 Jason Merrill + + PR c++/58678 + * ipa-devirt.c (ipa_devirt): Don't check DECL_COMDAT. + +2014-09-11 Georg-Johann Lay + + Backport from 2014-09-11 trunk r215152. + + PR target/63223 + * config/avr/avr.md (*tablejump.3byte-pc): New insn. + (*tablejump): Restrict to !AVR_HAVE_EIJMP_EICALL. Add void clobber. + (casesi): Expand to *tablejump.3byte-pc if AVR_HAVE_EIJMP_EICALL. + +2014-09-10 Michael Meissner + + Backport from mainline + 2014-09-10 Michael Meissner + + * config/rs6000/vsx.md (vsx_fmav4sf4): Use correct constraints for + V2DF, V4SF, DF, and DI modes. + (vsx_fmav2df2): Likewise. + (vsx_float_fix_2): Likewise. + (vsx_reduc__v2df_scalar): Likewise. + +2014-09-10 Xinliang David Li + + Backport from mainline + PR target/63209 + * config/arm/arm.md (movcond_addsi): Handle case where source + and target operands are the same. + +2014-09-10 Alan Modra + + PR debug/60655 + * dwarf2out.c (mem_loc_descriptor ): Return NULL if addend + can't be output. + +2014-09-09 Bill Schmidt + + Backported from mainline + 2014-09-04 Bill Schmidt + + * config/rs6000/vsx.md (*vsx_extract__load): Always match + selection of 0th memory doubleword, regardless of endianness. + +2014-09-09 James Greenhalgh + + Backport from mainline + 2014-09-09 James Greenhalgh + + * doc/invoke.texi (-march): Use GNU/Linux rather than Linux. + (-mtune): Likewise. + (-mcpu): Likewise. + +2014-09-09 Jason Merrill + + PR c++/61214 + PR c++/62224 + * gimple-fold.c (can_refer_decl_in_current_unit_p): Don't allow + reference to a DECL_EXTERNAL COMDAT. + +2014-09-09 Richard Biener + + Backport from mainline + 2014-08-05 Richard Biener + + PR rtl-optimization/61672 + * emit-rtl.h (mem_attrs_eq_p): Declare. + * emit-rtl.c (mem_attrs_eq_p): Export. Handle NULL mem-attrs. + * cse.c (exp_equiv_p): Use mem_attrs_eq_p. + * cfgcleanup.c (merge_memattrs): Likewise. + Include emit-rtl.h. + + 2014-08-11 Richard Biener + + PR tree-optimization/62075 + * tree-vect-slp.c (vect_detect_hybrid_slp_stmts): Properly + handle uses in patterns. + + 2014-08-14 Richard Biener + + PR rtl-optimization/62079 + * recog.c (peephole2_optimize): If peep2_do_cleanup_cfg + run cleanup_cfg. + + 2014-08-26 Richard Biener + + PR tree-optimization/62175 + * tree-ssa-loop-niter.c (expand_simple_operations): Do not + expand possibly trapping operations. + +2014-09-08 DJ Delorie + + * doc/invoke.texi (MSP430 Options): Add -minrt. + +2014-09-05 Easwaran Raman + + Backport from mainline + PR rtl-optimization/62146 + * ifcvt.c (dead_or_predicable): Make removal of REG_EQUAL note of + hoisted instruction unconditional. + +2014-09-04 Guozhi Wei + + PR target/62040 + * config/aarch64/iterators.md (VQ_NO2E, VQ_2E): New iterators. + * config/aarch64/aarch64-simd.md (move_lo_quad_internal_): Split + it into two patterns. + (move_lo_quad_internal_be_): Likewise. + +2014-09-03 Martin Jambor + + PR ipa/62015 + * ipa-cp.c (intersect_aggregates_with_edge): Handle impermissible + pass-trough jump functions correctly. + +2014-09-03 Martin Jambor + + PR ipa/61986 + * ipa-cp.c (find_aggregate_values_for_callers_subset): Chain + created replacements in ascending order of offsets. + (known_aggs_to_agg_replacement_list): Likewise. + +2014-09-02 Kaz Kojima + + Backport from mainline + 2014-08-27 Kaz Kojima + + PR target/62261 + * config/sh/sh.md (ashlsi3): Handle negative shift count for + TARGET_SHMEDIA. + (ashldi3, ashrsi3, ashrdi3, lshrsi3, lshrdi3): Likewise. + +2014-09-02 Kaz Kojima + + Backport from mainline + 2014-08-25 Kaz Kojima + + PR target/62111 + * config/sh/predicates.md (general_extend_operand): Disable + TRUNCATE before reload completes. + +2014-09-01 Oleg Endo + + Backport from mainline + 2014-09-01 Oleg Endo + + PR target/62312 + * config/sh/sh.md (*cmp_div0s_0): Add missing constraints. + +2014-09-01 Jakub Jelinek + + PR target/62025 + * sched-deps.c (add_or_update_dep_1): If ask_dependency_caches + returned DEP_PRESENT, make sure to set DEP_MULTIPLE on present_dep. + (find_inc): Revert 2014-08-12 change. + + * config/gnu-user.h (LIBLSAN_EARLY_SPEC): Define. + * gcc.c (LIBLSAN_SPEC, LIBLSAN_EARLY_SPEC): Follow LIBTSAN*_SPEC. + (SANITIZER_EARLY_SPEC): Include LIBLSAN_EARLY_SPEC for -fsanitize=leak. + +2014-09-01 Marek Polacek + + Backport from mainline + 2014-08-21 Marek Polacek + + PR c/61271 + * expr.c (is_aligning_offset): Remove logical not. + +2014-09-01 Marek Polacek + + Backport from mainline + 2014-08-19 Marek Polacek + + PR c/61271 + * cgraphunit.c (handle_alias_pairs): Fix condition. + +2014-08-30 John David Anglin + + * config/pa/pa.c (pa_assemble_integer): Don't add PLABEL relocation + prefix to function labels when generating fast indirect calls. + +2014-08-29 Yvan Roux + + Backport from mainline + 2014-08-27 Yvan Roux + + PR other/62248 + * config.gcc (arm*-*-*): Check --with-fpu against arm-fpus.def. + 2014-08-27 Guozhi Wei PR target/62262 @@ -208,7 +1968,6 @@ OMP_CLAUSE_SHARED for global vars if the global var is mentioned in OMP_CLAUSE_MAP in some outer target region. ->>>>>>> .r214216 2014-08-14 Kyrylo Tkachov Backport from mainline @@ -376,7 +2135,7 @@ 2014-08-12 Ganesh Gopalasubramanian Backport from mainline - 2014-08-04 Ganesh Gopalasubramanian + 2014-08-04 Ganesh Gopalasubramanian * config/i386/driver-i386.c (host_detect_local_cpu): Handle AMD's extended @@ -385,7 +2144,7 @@ 2014-08-12 Ganesh Gopalasubramanian Backport from mainline - 2014-06-16 Ganesh Gopalasubramanian + 2014-06-16 Ganesh Gopalasubramanian * config/i386/i386.c (ix86_expand_sse2_mulvxdi3): Issue @@ -649,7 +2408,7 @@ * omp-low.c (create_omp_child_function): Don't set DECL_NAMELESS on the FUNCTION_DECL. - * BASE-VER: Set to 4.9.1. + * BASE-VER: Set to 4.9.2. * DEV-PHASE: Set to prerelease. 2014-07-16 Release Manager diff --git a/gcc-4.9/gcc/DATESTAMP b/gcc-4.9/gcc/DATESTAMP index 2cd35d408..b5129ed0d 100644 --- a/gcc-4.9/gcc/DATESTAMP +++ b/gcc-4.9/gcc/DATESTAMP @@ -1 +1 @@ -20140827 +20150123 diff --git a/gcc-4.9/gcc/Makefile.in b/gcc-4.9/gcc/Makefile.in index 868054981..0309b3701 100644 --- a/gcc-4.9/gcc/Makefile.in +++ b/gcc-4.9/gcc/Makefile.in @@ -2294,7 +2294,9 @@ GTFILES = $(CPP_ID_DATA_H) $(srcdir)/input.h $(srcdir)/coretypes.h \ $(srcdir)/vtable-verify.c \ $(srcdir)/asan.c \ $(srcdir)/ubsan.c \ - $(srcdir)/tsan.c $(srcdir)/ipa-devirt.c \ + $(srcdir)/tsan.c \ + $(srcdir)/ipa-devirt.c \ + $(srcdir)/internal-fn.h \ @all_gtfiles@ # Compute the list of GT header files from the corresponding C sources, @@ -3169,7 +3171,7 @@ PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ tree-parloops.h tree-ssa-address.h tree-ssa-coalesce.h tree-ssa-dom.h \ tree-ssa-loop.h tree-ssa-loop-ivopts.h tree-ssa-loop-manip.h \ tree-ssa-loop-niter.h tree-ssa-ter.h tree-ssa-threadedge.h \ - tree-ssa-threadupdate.h + tree-ssa-threadupdate.h pass-instances.def # generate the 'build fragment' b-header-vars s-header-vars: Makefile diff --git a/gcc-4.9/gcc/ada/ChangeLog b/gcc-4.9/gcc/ada/ChangeLog index c8c4d807b..ba21f435e 100644 --- a/gcc-4.9/gcc/ada/ChangeLog +++ b/gcc-4.9/gcc/ada/ChangeLog @@ -1,3 +1,51 @@ +2015-01-05 Eric Botcazou + + PR ada/64492 + * gcc-interface/Makefile.in (../stamp-tools): Reinstate dropped code. + +2014-11-24 Eric Botcazou + + * gcc-interface/trans.c (push_range_check_info): Replace early test + with assertion. + (Raise_Error_to_gnu): Do not call push_range_check_info if the loop + stack is empty. + * gcc-interface/utils.c (convert_to_fat_pointer): Fix formatting. + * gcc-interface/utils2.c (gnat_invariant_expr): Deal with padded types + and revert latest change. + +2014-11-22 Eric Botcazou + + Backport from mainline + 2014-11-20 Vincent Celier + + PR ada/47500 + * back_end.adb (Scan_Back_End_Switches): Skip switch -G and + its argument. + +2014-11-11 Simon Wright + + PR ada/42978 + * mlib-utl.adb (ar): Output the options passed to ranlib. + +2014-10-30 Release Manager + + * GCC 4.9.2 released. + +2014-10-27 Eric Botcazou + + * gcc-interface/decl.c (gnat_to_gnu_entity) : Remove + superfluous computation for the max size. + : Likewise. Make sure that the max size calculation + does not overflow at compile time. + +2014-10-13 Eric Botcazou + Alan Modra + + PR ada/63225 + * uintp.adb (Vector_To_Uint): Move from here to... + * uintp.ads (UI_Vector): Make public. + (Vector_To_Uint): ...here. + 2014-08-12 Joel Sherrill * socket.c: For RTEMS, use correct prototype of gethostbyname_r(). diff --git a/gcc-4.9/gcc/ada/back_end.adb b/gcc-4.9/gcc/ada/back_end.adb index bb442ad5e..53146c891 100644 --- a/gcc-4.9/gcc/ada/back_end.adb +++ b/gcc-4.9/gcc/ada/back_end.adb @@ -210,9 +210,10 @@ package body Back_End is Last : constant Natural := Switch_Last (Switch_Chars); begin - -- Skip -o or internal GCC switches together with their argument + -- Skip -o, -G or internal GCC switches together with their argument. if Switch_Chars (First .. Last) = "o" + or else Switch_Chars (First .. Last) = "G" or else Is_Internal_GCC_Switch (Switch_Chars) then Next_Arg := Next_Arg + 1; diff --git a/gcc-4.9/gcc/ada/gcc-interface/Makefile.in b/gcc-4.9/gcc/ada/gcc-interface/Makefile.in index 5c36962ef..e2cc4a9e0 100644 --- a/gcc-4.9/gcc/ada/gcc-interface/Makefile.in +++ b/gcc-4.9/gcc/ada/gcc-interface/Makefile.in @@ -2510,9 +2510,16 @@ GCC_LINK=$(CXX) $(GCC_LINK_FLAGS) $(ADA_INCLUDES) $(LDFLAGS) # Build directory for the tools. Let's copy the target-dependent # sources using the same mechanism as for gnatlib. The other sources are # accessed using the vpath directive below -# Note: dummy target, stamp-tools is mainly handled by gnattools. ../stamp-tools: + -$(RM) tools/* + -$(RMDIR) tools + -$(MKDIR) tools + -(cd tools; $(LN_S) ../sdefault.adb ../snames.ads ../snames.adb .) + -$(foreach PAIR,$(TOOLS_TARGET_PAIRS), \ + $(RM) tools/$(word 1,$(subst <, ,$(PAIR)));\ + $(LN_S) $(fsrcpfx)ada/$(word 2,$(subst <, ,$(PAIR))) \ + tools/$(word 1,$(subst <, ,$(PAIR)));) touch ../stamp-tools # when compiling the tools, the runtime has to be first on the path so that diff --git a/gcc-4.9/gcc/ada/gcc-interface/decl.c b/gcc-4.9/gcc/ada/gcc-interface/decl.c index 52452ce79..95bc778b4 100644 --- a/gcc-4.9/gcc/ada/gcc-interface/decl.c +++ b/gcc-4.9/gcc/ada/gcc-interface/decl.c @@ -2200,11 +2200,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) tree gnu_max = convert (sizetype, TYPE_MAX_VALUE (gnu_index_type)); tree gnu_this_max - = size_binop (MAX_EXPR, - size_binop (PLUS_EXPR, size_one_node, - size_binop (MINUS_EXPR, - gnu_max, gnu_min)), - size_zero_node); + = size_binop (PLUS_EXPR, size_one_node, + size_binop (MINUS_EXPR, gnu_max, gnu_min)); if (TREE_CODE (gnu_this_max) == INTEGER_CST && TREE_OVERFLOW (gnu_this_max)) @@ -2525,20 +2522,26 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition) gnu_max_size = NULL_TREE; else { - tree gnu_this_max - = size_binop (MAX_EXPR, - size_binop (PLUS_EXPR, size_one_node, - size_binop (MINUS_EXPR, + tree gnu_this_max; + + /* Use int_const_binop if the bounds are constant to + avoid any unwanted overflow. */ + if (TREE_CODE (gnu_base_min) == INTEGER_CST + && TREE_CODE (gnu_base_max) == INTEGER_CST) + gnu_this_max + = int_const_binop (PLUS_EXPR, size_one_node, + int_const_binop (MINUS_EXPR, gnu_base_max, - gnu_base_min)), - size_zero_node); - - if (TREE_CODE (gnu_this_max) == INTEGER_CST - && TREE_OVERFLOW (gnu_this_max)) - gnu_max_size = NULL_TREE; + gnu_base_min)); else - gnu_max_size - = size_binop (MULT_EXPR, gnu_max_size, gnu_this_max); + gnu_this_max + = size_binop (PLUS_EXPR, size_one_node, + size_binop (MINUS_EXPR, + gnu_base_max, + gnu_base_min)); + + gnu_max_size + = size_binop (MULT_EXPR, gnu_max_size, gnu_this_max); } } diff --git a/gcc-4.9/gcc/ada/gcc-interface/trans.c b/gcc-4.9/gcc/ada/gcc-interface/trans.c index 03bf098b0..30a166611 100644 --- a/gcc-4.9/gcc/ada/gcc-interface/trans.c +++ b/gcc-4.9/gcc/ada/gcc-interface/trans.c @@ -2424,9 +2424,6 @@ push_range_check_info (tree var) struct loop_info_d *iter = NULL; unsigned int i; - if (vec_safe_is_empty (gnu_loop_stack)) - return NULL; - var = remove_conversions (var, false); if (TREE_CODE (var) != VAR_DECL) @@ -2435,6 +2432,8 @@ push_range_check_info (tree var) if (decl_function_context (var) != current_function_decl) return NULL; + gcc_assert (vec_safe_length (gnu_loop_stack) > 0); + for (i = vec_safe_length (gnu_loop_stack) - 1; vec_safe_iterate (gnu_loop_stack, i, &iter); i--) @@ -5165,6 +5164,7 @@ Raise_Error_to_gnu (Node_Id gnat_node, tree *gnu_result_type_p) the original checks reinstated, and a run time selection. The former loop will be suitable for vectorization. */ if (flag_unswitch_loops + && !vec_safe_is_empty (gnu_loop_stack) && (!gnu_low_bound || (gnu_low_bound = gnat_invariant_expr (gnu_low_bound))) && (!gnu_high_bound diff --git a/gcc-4.9/gcc/ada/gcc-interface/utils.c b/gcc-4.9/gcc/ada/gcc-interface/utils.c index 15b72366b..820d2cec9 100644 --- a/gcc-4.9/gcc/ada/gcc-interface/utils.c +++ b/gcc-4.9/gcc/ada/gcc-interface/utils.c @@ -4371,8 +4371,7 @@ convert_to_fat_pointer (tree type, tree expr) { /* The template type can still be dummy at this point so we build an empty constructor. The middle-end will fill it in with zeros. */ - t = build_constructor (template_type, - NULL); + t = build_constructor (template_type, NULL); TREE_CONSTANT (t) = TREE_STATIC (t) = 1; null_bounds = build_unary_op (ADDR_EXPR, NULL_TREE, t); SET_TYPE_NULL_BOUNDS (ptr_template_type, null_bounds); diff --git a/gcc-4.9/gcc/ada/gcc-interface/utils2.c b/gcc-4.9/gcc/ada/gcc-interface/utils2.c index dd4151b5b..da52f4185 100644 --- a/gcc-4.9/gcc/ada/gcc-interface/utils2.c +++ b/gcc-4.9/gcc/ada/gcc-interface/utils2.c @@ -2784,7 +2784,13 @@ gnat_invariant_expr (tree expr) || (TREE_CODE (expr) == VAR_DECL && TREE_READONLY (expr))) && decl_function_context (expr) == current_function_decl && DECL_INITIAL (expr)) - expr = remove_conversions (DECL_INITIAL (expr), false); + { + expr = DECL_INITIAL (expr); + /* Look into CONSTRUCTORs built to initialize padded types. */ + if (TYPE_IS_PADDING_P (TREE_TYPE (expr))) + expr = convert (TREE_TYPE (TYPE_FIELDS (TREE_TYPE (expr))), expr); + expr = remove_conversions (expr, false); + } if (TREE_CONSTANT (expr)) return fold_convert (type, expr); @@ -2840,7 +2846,7 @@ object: if (!TREE_READONLY (t)) return NULL_TREE; - if (TREE_CODE (t) == CONSTRUCTOR || TREE_CODE (t) == PARM_DECL) + if (TREE_CODE (t) == PARM_DECL) return fold_convert (type, expr); if (TREE_CODE (t) == VAR_DECL diff --git a/gcc-4.9/gcc/ada/mlib-utl.adb b/gcc-4.9/gcc/ada/mlib-utl.adb index 756add1d4..7e2d56b75 100644 --- a/gcc-4.9/gcc/ada/mlib-utl.adb +++ b/gcc-4.9/gcc/ada/mlib-utl.adb @@ -282,6 +282,10 @@ package body MLib.Utl is if not Opt.Quiet_Output then Write_Str (Ranlib_Name.all); Write_Char (' '); + for J in Ranlib_Options'Range loop + Write_Str (Ranlib_Options (J).all); + Write_Char (' '); + end loop; Write_Line (Arguments (Ar_Options'Length + 1).all); end if; diff --git a/gcc-4.9/gcc/ada/uintp.adb b/gcc-4.9/gcc/ada/uintp.adb index f418b56ce..226c1877f 100644 --- a/gcc-4.9/gcc/ada/uintp.adb +++ b/gcc-4.9/gcc/ada/uintp.adb @@ -171,22 +171,6 @@ package body Uintp is -- If Discard_Quotient is True, Quotient is set to No_Uint -- If Discard_Remainder is True, Remainder is set to No_Uint - function Vector_To_Uint - (In_Vec : UI_Vector; - Negative : Boolean) return Uint; - -- Functions that calculate values in UI_Vectors, call this function to - -- create and return the Uint value. In_Vec contains the multiple precision - -- (Base) representation of a non-negative value. Leading zeroes are - -- permitted. Negative is set if the desired result is the negative of the - -- given value. The result will be either the appropriate directly - -- represented value, or a table entry in the proper canonical format is - -- created and returned. - -- - -- Note that Init_Operand puts a signed value in the result vector, but - -- Vector_To_Uint is always presented with a non-negative value. The - -- processing of signs is something that is done by the caller before - -- calling Vector_To_Uint. - ------------ -- Direct -- ------------ diff --git a/gcc-4.9/gcc/ada/uintp.ads b/gcc-4.9/gcc/ada/uintp.ads index dcf85a07f..d76d28527 100644 --- a/gcc-4.9/gcc/ada/uintp.ads +++ b/gcc-4.9/gcc/ada/uintp.ads @@ -90,6 +90,18 @@ package Uintp is Uint_Minus_80 : constant Uint; Uint_Minus_128 : constant Uint; + type UI_Vector is array (Pos range <>) of Int; + -- Vector containing the integer values of a Uint value + + -- Note: An earlier version of this package used pointers of arrays of Ints + -- (dynamically allocated) for the Uint type. The change leads to a few + -- less natural idioms used throughout this code, but eliminates all uses + -- of the heap except for the table package itself. For example, Uint + -- parameters are often converted to UI_Vectors for internal manipulation. + -- This is done by creating the local UI_Vector using the function N_Digits + -- on the Uint to find the size needed for the vector, and then calling + -- Init_Operand to copy the values out of the table into the vector. + ----------------- -- Subprograms -- ----------------- @@ -252,6 +264,22 @@ package Uintp is -- function is used for capacity checks, and it can be one bit off -- without affecting its usage. + function Vector_To_Uint + (In_Vec : UI_Vector; + Negative : Boolean) return Uint; + -- Functions that calculate values in UI_Vectors, call this function to + -- create and return the Uint value. In_Vec contains the multiple precision + -- (Base) representation of a non-negative value. Leading zeroes are + -- permitted. Negative is set if the desired result is the negative of the + -- given value. The result will be either the appropriate directly + -- represented value, or a table entry in the proper canonical format is + -- created and returned. + -- + -- Note that Init_Operand puts a signed value in the result vector, but + -- Vector_To_Uint is always presented with a non-negative value. The + -- processing of signs is something that is done by the caller before + -- calling Vector_To_Uint. + --------------------- -- Output Routines -- --------------------- @@ -494,18 +522,6 @@ private -- UI_Vector is defined for this purpose and some internal subprograms -- used for converting from one to the other are defined. - type UI_Vector is array (Pos range <>) of Int; - -- Vector containing the integer values of a Uint value - - -- Note: An earlier version of this package used pointers of arrays of Ints - -- (dynamically allocated) for the Uint type. The change leads to a few - -- less natural idioms used throughout this code, but eliminates all uses - -- of the heap except for the table package itself. For example, Uint - -- parameters are often converted to UI_Vectors for internal manipulation. - -- This is done by creating the local UI_Vector using the function N_Digits - -- on the Uint to find the size needed for the vector, and then calling - -- Init_Operand to copy the values out of the table into the vector. - type Uint_Entry is record Length : Pos; -- Length of entry in Udigits table in digits (i.e. in words) diff --git a/gcc-4.9/gcc/alias.c b/gcc-4.9/gcc/alias.c index e5406123c..b81ea28c6 100644 --- a/gcc-4.9/gcc/alias.c +++ b/gcc-4.9/gcc/alias.c @@ -382,17 +382,9 @@ get_alias_set_entry (alias_set_type alias_set) static inline int mems_in_disjoint_alias_sets_p (const_rtx mem1, const_rtx mem2) { -/* Perform a basic sanity check. Namely, that there are no alias sets - if we're not using strict aliasing. This helps to catch bugs - whereby someone uses PUT_CODE, but doesn't clear MEM_ALIAS_SET, or - where a MEM is allocated in some way other than by the use of - gen_rtx_MEM, and the MEM_ALIAS_SET is not cleared. If we begin to - use alias sets to indicate that spilled registers cannot alias each - other, we might need to remove this check. */ - gcc_assert (flag_strict_aliasing - || (!MEM_ALIAS_SET (mem1) && !MEM_ALIAS_SET (mem2))); - - return ! alias_sets_conflict_p (MEM_ALIAS_SET (mem1), MEM_ALIAS_SET (mem2)); + return (flag_strict_aliasing + && ! alias_sets_conflict_p (MEM_ALIAS_SET (mem1), + MEM_ALIAS_SET (mem2))); } /* Insert the NODE into the splay tree given by DATA. Used by @@ -2454,6 +2446,7 @@ static int true_dependence_1 (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr, const_rtx x, rtx x_addr, bool mem_canonicalized) { + rtx true_mem_addr; rtx base; int ret; @@ -2473,17 +2466,9 @@ true_dependence_1 (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr, || MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER) return 1; - /* Read-only memory is by definition never modified, and therefore can't - conflict with anything. We don't expect to find read-only set on MEM, - but stupid user tricks can produce them, so don't die. */ - if (MEM_READONLY_P (x)) - return 0; - - /* If we have MEMs referring to different address spaces (which can - potentially overlap), we cannot easily tell from the addresses - whether the references overlap. */ - if (MEM_ADDR_SPACE (mem) != MEM_ADDR_SPACE (x)) - return 1; + if (! x_addr) + x_addr = XEXP (x, 0); + x_addr = get_addr (x_addr); if (! mem_addr) { @@ -2491,22 +2476,23 @@ true_dependence_1 (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr, if (mem_mode == VOIDmode) mem_mode = GET_MODE (mem); } + true_mem_addr = get_addr (mem_addr); - if (! x_addr) - { - x_addr = XEXP (x, 0); - if (!((GET_CODE (x_addr) == VALUE - && GET_CODE (mem_addr) != VALUE - && reg_mentioned_p (x_addr, mem_addr)) - || (GET_CODE (x_addr) != VALUE - && GET_CODE (mem_addr) == VALUE - && reg_mentioned_p (mem_addr, x_addr)))) - { - x_addr = get_addr (x_addr); - if (! mem_canonicalized) - mem_addr = get_addr (mem_addr); - } - } + /* Read-only memory is by definition never modified, and therefore can't + conflict with anything. However, don't assume anything when AND + addresses are involved and leave to the code below to determine + dependence. We don't expect to find read-only set on MEM, but + stupid user tricks can produce them, so don't die. */ + if (MEM_READONLY_P (x) + && GET_CODE (x_addr) != AND + && GET_CODE (true_mem_addr) != AND) + return 0; + + /* If we have MEMs referring to different address spaces (which can + potentially overlap), we cannot easily tell from the addresses + whether the references overlap. */ + if (MEM_ADDR_SPACE (mem) != MEM_ADDR_SPACE (x)) + return 1; base = find_base_term (x_addr); if (base && (GET_CODE (base) == LABEL_REF @@ -2514,14 +2500,14 @@ true_dependence_1 (const_rtx mem, enum machine_mode mem_mode, rtx mem_addr, && CONSTANT_POOL_ADDRESS_P (base)))) return 0; - rtx mem_base = find_base_term (mem_addr); - if (! base_alias_check (x_addr, base, mem_addr, mem_base, + rtx mem_base = find_base_term (true_mem_addr); + if (! base_alias_check (x_addr, base, true_mem_addr, mem_base, GET_MODE (x), mem_mode)) return 0; x_addr = canon_rtx (x_addr); if (!mem_canonicalized) - mem_addr = canon_rtx (mem_addr); + mem_addr = canon_rtx (true_mem_addr); if ((ret = memrefs_conflict_p (GET_MODE_SIZE (mem_mode), mem_addr, SIZE_FOR_MODE (x), x_addr, 0)) != -1) @@ -2571,6 +2557,7 @@ write_dependence_p (const_rtx mem, bool mem_canonicalized, bool x_canonicalized, bool writep) { rtx mem_addr; + rtx true_mem_addr, true_x_addr; rtx base; int ret; @@ -2591,8 +2578,20 @@ write_dependence_p (const_rtx mem, || MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER) return 1; - /* A read from read-only memory can't conflict with read-write memory. */ - if (!writep && MEM_READONLY_P (mem)) + if (!x_addr) + x_addr = XEXP (x, 0); + true_x_addr = get_addr (x_addr); + + mem_addr = XEXP (mem, 0); + true_mem_addr = get_addr (mem_addr); + + /* A read from read-only memory can't conflict with read-write memory. + Don't assume anything when AND addresses are involved and leave to + the code below to determine dependence. */ + if (!writep + && MEM_READONLY_P (mem) + && GET_CODE (true_x_addr) != AND + && GET_CODE (true_mem_addr) != AND) return 0; /* If we have MEMs referring to different address spaces (which can @@ -2601,24 +2600,7 @@ write_dependence_p (const_rtx mem, if (MEM_ADDR_SPACE (mem) != MEM_ADDR_SPACE (x)) return 1; - mem_addr = XEXP (mem, 0); - if (!x_addr) - { - x_addr = XEXP (x, 0); - if (!((GET_CODE (x_addr) == VALUE - && GET_CODE (mem_addr) != VALUE - && reg_mentioned_p (x_addr, mem_addr)) - || (GET_CODE (x_addr) != VALUE - && GET_CODE (mem_addr) == VALUE - && reg_mentioned_p (mem_addr, x_addr)))) - { - x_addr = get_addr (x_addr); - if (!mem_canonicalized) - mem_addr = get_addr (mem_addr); - } - } - - base = find_base_term (mem_addr); + base = find_base_term (true_mem_addr); if (! writep && base && (GET_CODE (base) == LABEL_REF @@ -2626,18 +2608,18 @@ write_dependence_p (const_rtx mem, && CONSTANT_POOL_ADDRESS_P (base)))) return 0; - rtx x_base = find_base_term (x_addr); - if (! base_alias_check (x_addr, x_base, mem_addr, base, GET_MODE (x), - GET_MODE (mem))) + rtx x_base = find_base_term (true_x_addr); + if (! base_alias_check (true_x_addr, x_base, true_mem_addr, base, + GET_MODE (x), GET_MODE (mem))) return 0; if (!x_canonicalized) { - x_addr = canon_rtx (x_addr); + x_addr = canon_rtx (true_x_addr); x_mode = GET_MODE (x); } if (!mem_canonicalized) - mem_addr = canon_rtx (mem_addr); + mem_addr = canon_rtx (true_mem_addr); if ((ret = memrefs_conflict_p (SIZE_FOR_MODE (mem), mem_addr, GET_MODE_SIZE (x_mode), x_addr, 0)) != -1) @@ -2705,10 +2687,20 @@ may_alias_p (const_rtx mem, const_rtx x) || MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER) return 1; + x_addr = XEXP (x, 0); + x_addr = get_addr (x_addr); + + mem_addr = XEXP (mem, 0); + mem_addr = get_addr (mem_addr); + /* Read-only memory is by definition never modified, and therefore can't - conflict with anything. We don't expect to find read-only set on MEM, - but stupid user tricks can produce them, so don't die. */ - if (MEM_READONLY_P (x)) + conflict with anything. However, don't assume anything when AND + addresses are involved and leave to the code below to determine + dependence. We don't expect to find read-only set on MEM, but + stupid user tricks can produce them, so don't die. */ + if (MEM_READONLY_P (x) + && GET_CODE (x_addr) != AND + && GET_CODE (mem_addr) != AND) return 0; /* If we have MEMs referring to different address spaces (which can @@ -2717,28 +2709,12 @@ may_alias_p (const_rtx mem, const_rtx x) if (MEM_ADDR_SPACE (mem) != MEM_ADDR_SPACE (x)) return 1; - x_addr = XEXP (x, 0); - mem_addr = XEXP (mem, 0); - if (!((GET_CODE (x_addr) == VALUE - && GET_CODE (mem_addr) != VALUE - && reg_mentioned_p (x_addr, mem_addr)) - || (GET_CODE (x_addr) != VALUE - && GET_CODE (mem_addr) == VALUE - && reg_mentioned_p (mem_addr, x_addr)))) - { - x_addr = get_addr (x_addr); - mem_addr = get_addr (mem_addr); - } - rtx x_base = find_base_term (x_addr); rtx mem_base = find_base_term (mem_addr); if (! base_alias_check (x_addr, x_base, mem_addr, mem_base, GET_MODE (x), GET_MODE (mem_addr))) return 0; - x_addr = canon_rtx (x_addr); - mem_addr = canon_rtx (mem_addr); - if (nonoverlapping_memrefs_p (mem, x, true)) return 0; diff --git a/gcc-4.9/gcc/asan.c b/gcc-4.9/gcc/asan.c index 28a476fe4..f6c42a1d0 100644 --- a/gcc-4.9/gcc/asan.c +++ b/gcc-4.9/gcc/asan.c @@ -242,6 +242,17 @@ static GTY(()) tree shadow_ptr_types[2]; /* 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_START_INSTRUMENTED = 1 << 3, + ASAN_CHECK_END_INSTRUMENTED = 1 << 4, + ASAN_CHECK_LAST = 1 << 5 +}; + /* Hashtable support for memory references used by gimple statements. */ @@ -251,8 +262,8 @@ struct asan_mem_ref /* The expression of the beginning of the memory region. */ tree start; - /* The size of the access (can be 1, 2, 4, 8, 16 for now). */ - char access_size; + /* The size of the access. */ + HOST_WIDE_INT access_size; }; static alloc_pool asan_mem_ref_alloc_pool; @@ -274,7 +285,7 @@ asan_mem_ref_get_alloc_pool () /* Initializes an instance of asan_mem_ref. */ static void -asan_mem_ref_init (asan_mem_ref *ref, tree start, char access_size) +asan_mem_ref_init (asan_mem_ref *ref, tree start, HOST_WIDE_INT access_size) { ref->start = start; ref->access_size = access_size; @@ -287,7 +298,7 @@ asan_mem_ref_init (asan_mem_ref *ref, tree start, char access_size) access to the referenced memory. */ static asan_mem_ref* -asan_mem_ref_new (tree start, char access_size) +asan_mem_ref_new (tree start, HOST_WIDE_INT access_size) { asan_mem_ref *ref = (asan_mem_ref *) pool_alloc (asan_mem_ref_get_alloc_pool ()); @@ -305,6 +316,9 @@ asan_mem_ref_get_end (tree start, tree len) if (len == NULL_TREE || integer_zerop (len)) return start; + if (!ptrofftype_p (len)) + len = convert_to_ptrofftype (len); + return fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (start), start, len); } @@ -334,7 +348,7 @@ inline hashval_t asan_mem_ref_hasher::hash (const asan_mem_ref *mem_ref) { hashval_t h = iterative_hash_expr (mem_ref->start, 0); - h = iterative_hash_hashval_t (h, mem_ref->access_size); + h = iterative_hash_host_wide_int (mem_ref->access_size, h); return h; } @@ -392,7 +406,7 @@ free_mem_ref_resources () /* Return true iff the memory reference REF has been instrumented. */ static bool -has_mem_ref_been_instrumented (tree ref, char access_size) +has_mem_ref_been_instrumented (tree ref, HOST_WIDE_INT access_size) { asan_mem_ref r; asan_mem_ref_init (&r, ref, access_size); @@ -480,7 +494,7 @@ get_mem_refs_of_builtin_call (const gimple call, tree source0 = NULL_TREE, source1 = NULL_TREE, dest = NULL_TREE, len = NULL_TREE; bool is_store = true, got_reference_p = false; - char access_size = 1; + HOST_WIDE_INT access_size = 1; switch (DECL_FUNCTION_CODE (callee)) { @@ -842,7 +856,7 @@ has_stmt_been_instrumented_p (gimple stmt) /* Insert a memory reference into the hash table. */ static void -update_mem_ref_hash_table (tree ref, char access_size) +update_mem_ref_hash_table (tree ref, HOST_WIDE_INT access_size) { hash_table ht = get_mem_ref_hash_table (); @@ -929,7 +943,7 @@ asan_clear_shadow (rtx shadow_mem, HOST_WIDE_INT len) emit_move_insn (shadow_mem, const0_rtx); tmp = expand_simple_binop (Pmode, PLUS, addr, gen_int_mode (4, Pmode), addr, - true, OPTAB_LIB_WIDEN); + true, OPTAB_LIB_WIDEN); if (tmp != addr) emit_move_insn (addr, tmp); emit_cmp_and_jump_insns (addr, end, LT, NULL_RTX, Pmode, true, top_label); @@ -944,7 +958,7 @@ asan_function_start (void) section *fnsec = function_section (current_function_decl); switch_to_section (fnsec); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, "LASANPC", - current_function_funcdef_no); + current_function_funcdef_no); } /* Insert code to protect stack vars. The prologue sequence should be emitted @@ -1009,7 +1023,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, { use_after_return_class = floor_log2 (asan_frame_size - 1) - 5; /* __asan_stack_malloc_N guarantees alignment - N < 6 ? (64 << N) : 4096 bytes. */ + N < 6 ? (64 << N) : 4096 bytes. */ if (alignb > (use_after_return_class < 6 ? (64U << use_after_return_class) : 4096U)) use_after_return_class = -1; @@ -1082,7 +1096,7 @@ asan_emit_stack_protection (rtx base, rtx pbase, unsigned int alignb, ASM_GENERATE_INTERNAL_LABEL (buf, "LASANPC", current_function_funcdef_no); id = get_identifier (buf); decl = build_decl (DECL_SOURCE_LOCATION (current_function_decl), - VAR_DECL, id, char_type_node); + VAR_DECL, id, char_type_node); SET_DECL_ASSEMBLER_NAME (decl, id); TREE_ADDRESSABLE (decl) = 1; TREE_READONLY (decl) = 1; @@ -1315,23 +1329,50 @@ asan_protect_global (tree decl) return true; } -/* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16}. - IS_STORE is either 1 (for a store) or 0 (for a load). - SIZE_IN_BYTES is one of 1, 2, 4, 8, 16. */ +/* Construct a function tree for __asan_report_{load,store}{1,2,4,8,16,_n}. + IS_STORE is either 1 (for a store) or 0 (for a load). */ static tree -report_error_func (bool is_store, int size_in_bytes) +report_error_func (bool is_store, HOST_WIDE_INT size_in_bytes, int *nargs) { - static enum built_in_function report[2][5] + static enum built_in_function report[2][6] = { { BUILT_IN_ASAN_REPORT_LOAD1, BUILT_IN_ASAN_REPORT_LOAD2, BUILT_IN_ASAN_REPORT_LOAD4, BUILT_IN_ASAN_REPORT_LOAD8, - BUILT_IN_ASAN_REPORT_LOAD16 }, + BUILT_IN_ASAN_REPORT_LOAD16, BUILT_IN_ASAN_REPORT_LOAD_N }, { BUILT_IN_ASAN_REPORT_STORE1, BUILT_IN_ASAN_REPORT_STORE2, BUILT_IN_ASAN_REPORT_STORE4, BUILT_IN_ASAN_REPORT_STORE8, - BUILT_IN_ASAN_REPORT_STORE16 } }; + BUILT_IN_ASAN_REPORT_STORE16, BUILT_IN_ASAN_REPORT_STORE_N } }; + if (size_in_bytes == -1) + { + *nargs = 2; + return builtin_decl_implicit (report[is_store][5]); + } + *nargs = 1; return builtin_decl_implicit (report[is_store][exact_log2 (size_in_bytes)]); } +/* Construct a function tree for __asan_{load,store}{1,2,4,8,16,_n}. + IS_STORE is either 1 (for a store) or 0 (for a load). */ + +static tree +check_func (bool is_store, int size_in_bytes, int *nargs) +{ + static enum built_in_function check[2][6] + = { { BUILT_IN_ASAN_LOAD1, BUILT_IN_ASAN_LOAD2, + BUILT_IN_ASAN_LOAD4, BUILT_IN_ASAN_LOAD8, + BUILT_IN_ASAN_LOAD16, BUILT_IN_ASAN_LOADN }, + { BUILT_IN_ASAN_STORE1, BUILT_IN_ASAN_STORE2, + BUILT_IN_ASAN_STORE4, BUILT_IN_ASAN_STORE8, + BUILT_IN_ASAN_STORE16, BUILT_IN_ASAN_STOREN } }; + if (size_in_bytes == -1) + { + *nargs = 2; + return builtin_decl_implicit (check[is_store][5]); + } + *nargs = 1; + return builtin_decl_implicit (check[is_store][exact_log2 (size_in_bytes)]); +} + /* Split the current basic block and create a condition statement insertion point right before or after the statement pointed to by ITER. Return an iterator to the point at which the caller might @@ -1450,85 +1491,36 @@ insert_if_then_before_iter (gimple cond, gsi_insert_after (&cond_insert_point, cond, GSI_NEW_STMT); } -/* Instrument the memory access instruction BASE. Insert new - statements before or after ITER. - - Note that the memory access represented by BASE can be either an - SSA_NAME, or a non-SSA expression. LOCATION is the source code - location. IS_STORE is TRUE for a store, FALSE for a load. - BEFORE_P is TRUE for inserting the instrumentation code before - ITER, FALSE for inserting it after ITER. SIZE_IN_BYTES is one of - 1, 2, 4, 8, 16. - - If BEFORE_P is TRUE, *ITER is arranged to still point to the - statement it was pointing to prior to calling this function, - otherwise, it points to the statement logically following it. */ +/* Build + (base_addr >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset (). */ -static void -build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter, - bool before_p, bool is_store, int size_in_bytes) +static tree +build_shadow_mem_access (gimple_stmt_iterator *gsi, location_t location, + tree base_addr, tree shadow_ptr_type) { - gimple_stmt_iterator gsi; - basic_block then_bb, else_bb; - tree t, base_addr, shadow; - gimple g; - tree shadow_ptr_type = shadow_ptr_types[size_in_bytes == 16 ? 1 : 0]; + tree t, uintptr_type = TREE_TYPE (base_addr); tree shadow_type = TREE_TYPE (shadow_ptr_type); - tree uintptr_type - = build_nonstandard_integer_type (TYPE_PRECISION (TREE_TYPE (base)), 1); - tree base_ssa = base; - - /* Get an iterator on the point where we can add the condition - statement for the instrumentation. */ - gsi = create_cond_insert_point (iter, before_p, - /*then_more_likely_p=*/false, - /*create_then_fallthru_edge=*/false, - &then_bb, - &else_bb); - - base = unshare_expr (base); - - /* BASE can already be an SSA_NAME; in that case, do not create a - new SSA_NAME for it. */ - if (TREE_CODE (base) != SSA_NAME) - { - g = gimple_build_assign_with_ops (TREE_CODE (base), - make_ssa_name (TREE_TYPE (base), NULL), - base, NULL_TREE); - gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); - base_ssa = gimple_assign_lhs (g); - } - - g = gimple_build_assign_with_ops (NOP_EXPR, - make_ssa_name (uintptr_type, NULL), - base_ssa, NULL_TREE); - gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); - base_addr = gimple_assign_lhs (g); - - /* Build - (base_addr >> ASAN_SHADOW_SHIFT) + targetm.asan_shadow_offset (). */ + gimple g; t = build_int_cst (uintptr_type, ASAN_SHADOW_SHIFT); g = gimple_build_assign_with_ops (RSHIFT_EXPR, make_ssa_name (uintptr_type, NULL), base_addr, t); gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); + gsi_insert_after (gsi, g, GSI_NEW_STMT); t = build_int_cst (uintptr_type, targetm.asan_shadow_offset ()); g = gimple_build_assign_with_ops (PLUS_EXPR, make_ssa_name (uintptr_type, NULL), gimple_assign_lhs (g), t); gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); + gsi_insert_after (gsi, g, GSI_NEW_STMT); g = gimple_build_assign_with_ops (NOP_EXPR, make_ssa_name (shadow_ptr_type, NULL), gimple_assign_lhs (g), NULL_TREE); gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); + 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)); @@ -1536,48 +1528,150 @@ build_check_stmt (location_t location, tree base, gimple_stmt_iterator *iter, make_ssa_name (shadow_type, NULL), t, NULL_TREE); gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); - shadow = gimple_assign_lhs (g); + gsi_insert_after (gsi, g, GSI_NEW_STMT); + return gimple_assign_lhs (g); +} + +/* BASE can already be an SSA_NAME; in that case, do not create a + new SSA_NAME for it. */ + +static tree +maybe_create_ssa_name (location_t loc, tree base, gimple_stmt_iterator *iter, + bool before_p) +{ + if (TREE_CODE (base) == SSA_NAME) + return base; + gimple g + = gimple_build_assign_with_ops (TREE_CODE (base), + make_ssa_name (TREE_TYPE (base), NULL), + base, NULL_TREE); + gimple_set_location (g, loc); + if (before_p) + gsi_insert_before (iter, g, GSI_SAME_STMT); + else + gsi_insert_after (iter, g, GSI_NEW_STMT); + return gimple_assign_lhs (g); +} + +/* LEN can already have necessary size and precision; + in that case, do not create a new variable. */ + +tree +maybe_cast_to_ptrmode (location_t loc, tree len, gimple_stmt_iterator *iter, + bool before_p) +{ + if (ptrofftype_p (len)) + return len; + gimple g + = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (pointer_sized_int_node, NULL), + len, NULL); + gimple_set_location (g, loc); + if (before_p) + gsi_insert_before (iter, g, GSI_SAME_STMT); + else + gsi_insert_after (iter, g, GSI_NEW_STMT); + return gimple_assign_lhs (g); +} + +/* Instrument the memory access instruction BASE. Insert new + statements before or after ITER. - if (size_in_bytes < 8) + Note that the memory access represented by BASE can be either an + SSA_NAME, or a non-SSA expression. LOCATION is the source code + location. IS_STORE is TRUE for a store, FALSE for a load. + BEFORE_P is TRUE for inserting the instrumentation code before + ITER, FALSE for inserting it after ITER. IS_SCALAR_ACCESS is TRUE + for a scalar memory access and FALSE for memory region access. + NON_ZERO_P is TRUE if memory region is guaranteed to have non-zero + length. ALIGN tells alignment of accessed memory object. + + START_INSTRUMENTED and END_INSTRUMENTED are TRUE if start/end of + memory region have already been instrumented. + + If BEFORE_P is TRUE, *ITER is arranged to still point to the + statement it was pointing to prior to calling this function, + otherwise, it points to the statement logically following it. */ + +static void +build_check_stmt (location_t loc, tree base, tree len, + HOST_WIDE_INT size_in_bytes, gimple_stmt_iterator *iter, + bool is_non_zero_len, bool before_p, bool is_store, + bool is_scalar_access, unsigned int align = 0, + bool start_instrumented = false, + bool end_instrumented = false) +{ + gimple_stmt_iterator gsi = *iter; + gimple g; + + gcc_assert (!(size_in_bytes > 0 && !is_non_zero_len)); + + if (start_instrumented && end_instrumented) { - /* Slow path for 1, 2 and 4 byte accesses. - Test (shadow != 0) - & ((base_addr & 7) + (size_in_bytes - 1)) >= shadow). */ - gimple_seq seq = NULL; - gimple shadow_test = build_assign (NE_EXPR, shadow, 0); - gimple_seq_add_stmt (&seq, shadow_test); - gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, base_addr, 7)); - gimple_seq_add_stmt (&seq, build_type_cast (shadow_type, - gimple_seq_last (seq))); - if (size_in_bytes > 1) - gimple_seq_add_stmt (&seq, - build_assign (PLUS_EXPR, gimple_seq_last (seq), - size_in_bytes - 1)); - gimple_seq_add_stmt (&seq, build_assign (GE_EXPR, gimple_seq_last (seq), - shadow)); - gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test, - gimple_seq_last (seq))); - t = gimple_assign_lhs (gimple_seq_last (seq)); - gimple_seq_set_location (seq, location); - gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); + if (!before_p) + gsi_next (iter); + return; } - else - t = shadow; - g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0), - NULL_TREE, NULL_TREE); - gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); + gsi = *iter; - /* Generate call to the run-time library (e.g. __asan_report_load8). */ - gsi = gsi_start_bb (then_bb); - g = gimple_build_call (report_error_func (is_store, size_in_bytes), - 1, base_addr); - gimple_set_location (g, location); - gsi_insert_after (&gsi, g, GSI_NEW_STMT); + base = unshare_expr (base); + base = maybe_create_ssa_name (loc, base, &gsi, before_p); - *iter = gsi_start_bb (else_bb); + if (len) + { + len = unshare_expr (len); + len = maybe_cast_to_ptrmode (loc, len, iter, before_p); + } + else + { + gcc_assert (size_in_bytes != -1); + len = build_int_cst (pointer_sized_int_node, size_in_bytes); + } + + if (size_in_bytes > 1) + { + if ((size_in_bytes & (size_in_bytes - 1)) != 0 + || size_in_bytes > 16) + is_scalar_access = false; + else if (align && align < size_in_bytes * BITS_PER_UNIT) + { + /* On non-strict alignment targets, if + 16-byte access is just 8-byte aligned, + this will result in misaligned shadow + memory 2 byte load, but otherwise can + be handled using one read. */ + if (size_in_bytes != 16 + || STRICT_ALIGNMENT + || align < 8 * BITS_PER_UNIT) + is_scalar_access = false; + } + } + + HOST_WIDE_INT flags = 0; + if (is_store) + flags |= ASAN_CHECK_STORE; + if (is_non_zero_len) + flags |= ASAN_CHECK_NON_ZERO_LEN; + if (is_scalar_access) + flags |= ASAN_CHECK_SCALAR_ACCESS; + if (start_instrumented) + flags |= ASAN_CHECK_START_INSTRUMENTED; + if (end_instrumented) + flags |= ASAN_CHECK_END_INSTRUMENTED; + + g = gimple_build_call_internal (IFN_ASAN_CHECK, 3, + build_int_cst (integer_type_node, flags), + base, len); + gimple_set_location (g, loc); + if (before_p) + gsi_insert_before (&gsi, g, GSI_SAME_STMT); + else + { + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + gsi_next (&gsi); + *iter = gsi; + } } /* If T represents a memory access, add instrumentation code before ITER. @@ -1611,8 +1705,7 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, } size_in_bytes = int_size_in_bytes (type); - if ((size_in_bytes & (size_in_bytes - 1)) != 0 - || (unsigned HOST_WIDE_INT) size_in_bytes - 1 >= 16) + if (size_in_bytes <= 0) return; HOST_WIDE_INT bitsize, bitpos; @@ -1621,20 +1714,21 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, int volatilep = 0, unsignedp = 0; tree inner = get_inner_reference (t, &bitsize, &bitpos, &offset, &mode, &unsignedp, &volatilep, false); - if (bitpos % (size_in_bytes * BITS_PER_UNIT) - || bitsize != size_in_bytes * BITS_PER_UNIT) + + if (TREE_CODE (t) == COMPONENT_REF + && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE) { - if (TREE_CODE (t) == COMPONENT_REF - && DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)) != NULL_TREE) - { - tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)); - instrument_derefs (iter, build3 (COMPONENT_REF, TREE_TYPE (repr), - TREE_OPERAND (t, 0), repr, - NULL_TREE), location, is_store); - } + tree repr = DECL_BIT_FIELD_REPRESENTATIVE (TREE_OPERAND (t, 1)); + instrument_derefs (iter, build3 (COMPONENT_REF, TREE_TYPE (repr), + TREE_OPERAND (t, 0), repr, + NULL_TREE), location, is_store); return; } + if (bitpos % BITS_PER_UNIT + || bitsize != size_in_bytes * BITS_PER_UNIT) + return; + if (TREE_CODE (inner) == VAR_DECL && offset == NULL_TREE && bitpos >= 0 @@ -1666,8 +1760,10 @@ instrument_derefs (gimple_stmt_iterator *iter, tree t, base = build_fold_addr_expr (t); if (!has_mem_ref_been_instrumented (base, size_in_bytes)) { - build_check_stmt (location, base, iter, /*before_p=*/true, - is_store, size_in_bytes); + unsigned int align = get_object_alignment (t); + build_check_stmt (location, base, NULL_TREE, size_in_bytes, iter, + /*is_non_zero_len*/size_in_bytes > 0, /*before_p=*/true, + is_store, /*is_scalar_access*/true, align); update_mem_ref_hash_table (base, size_in_bytes); update_mem_ref_hash_table (t, size_in_bytes); } @@ -1692,142 +1788,24 @@ instrument_mem_region_access (tree base, tree len, || integer_zerop (len)) return; - gimple_stmt_iterator gsi = *iter; - - basic_block fallthrough_bb = NULL, then_bb = NULL; - /* If the beginning of the memory region has already been instrumented, do not instrument it. */ bool start_instrumented = has_mem_ref_been_instrumented (base, 1); /* If the end of the memory region has already been instrumented, do - not instrument it. */ + not instrument it. */ tree end = asan_mem_ref_get_end (base, len); bool end_instrumented = has_mem_ref_been_instrumented (end, 1); - if (start_instrumented && end_instrumented) - return; - - if (!is_gimple_constant (len)) - { - /* So, the length of the memory area to asan-protect is - non-constant. Let's guard the generated instrumentation code - like: - - if (len != 0) - { - //asan instrumentation code goes here. - } - // falltrough instructions, starting with *ITER. */ + HOST_WIDE_INT size_in_bytes = tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1; - gimple g = gimple_build_cond (NE_EXPR, - len, - build_int_cst (TREE_TYPE (len), 0), - NULL_TREE, NULL_TREE); - gimple_set_location (g, location); - insert_if_then_before_iter (g, iter, /*then_more_likely_p=*/true, - &then_bb, &fallthrough_bb); - /* Note that fallthrough_bb starts with the statement that was - pointed to by ITER. */ - - /* The 'then block' of the 'if (len != 0) condition is where - we'll generate the asan instrumentation code now. */ - gsi = gsi_last_bb (then_bb); - } - - if (!start_instrumented) - { - /* Instrument the beginning of the memory region to be accessed, - and arrange for the rest of the intrumentation code to be - inserted in the then block *after* the current gsi. */ - build_check_stmt (location, base, &gsi, /*before_p=*/true, is_store, 1); - - if (then_bb) - /* We are in the case where the length of the region is not - constant; so instrumentation code is being generated in the - 'then block' of the 'if (len != 0) condition. Let's arrange - for the subsequent instrumentation statements to go in the - 'then block'. */ - gsi = gsi_last_bb (then_bb); - else - { - *iter = gsi; - /* Don't remember this access as instrumented, if length - is unknown. It might be zero and not being actually - instrumented, so we can't rely on it being instrumented. */ - update_mem_ref_hash_table (base, 1); - } - } - - if (end_instrumented) - return; - - /* We want to instrument the access at the end of the memory region, - which is at (base + len - 1). */ - - /* offset = len - 1; */ - len = unshare_expr (len); - tree offset; - gimple_seq seq = NULL; - if (TREE_CODE (len) == INTEGER_CST) - offset = fold_build2 (MINUS_EXPR, size_type_node, - fold_convert (size_type_node, len), - build_int_cst (size_type_node, 1)); - else - { - gimple g; - tree t; - - if (TREE_CODE (len) != SSA_NAME) - { - t = make_ssa_name (TREE_TYPE (len), NULL); - g = gimple_build_assign_with_ops (TREE_CODE (len), t, len, NULL); - gimple_set_location (g, location); - gimple_seq_add_stmt_without_update (&seq, g); - len = t; - } - if (!useless_type_conversion_p (size_type_node, TREE_TYPE (len))) - { - t = make_ssa_name (size_type_node, NULL); - g = gimple_build_assign_with_ops (NOP_EXPR, t, len, NULL); - gimple_set_location (g, location); - gimple_seq_add_stmt_without_update (&seq, g); - len = t; - } - - t = make_ssa_name (size_type_node, NULL); - g = gimple_build_assign_with_ops (MINUS_EXPR, t, len, - build_int_cst (size_type_node, 1)); - gimple_set_location (g, location); - gimple_seq_add_stmt_without_update (&seq, g); - offset = gimple_assign_lhs (g); - } + build_check_stmt (location, base, len, size_in_bytes, iter, + /*is_non_zero_len*/size_in_bytes > 0, /*before_p*/true, + is_store, /*is_scalar_access*/false, /*align*/0, + start_instrumented, end_instrumented); - /* _1 = base; */ - base = unshare_expr (base); - gimple region_end = - gimple_build_assign_with_ops (TREE_CODE (base), - make_ssa_name (TREE_TYPE (base), NULL), - base, NULL); - gimple_set_location (region_end, location); - gimple_seq_add_stmt_without_update (&seq, region_end); - - /* _2 = _1 + offset; */ - region_end = - gimple_build_assign_with_ops (POINTER_PLUS_EXPR, - make_ssa_name (TREE_TYPE (base), NULL), - gimple_assign_lhs (region_end), - offset); - gimple_set_location (region_end, location); - gimple_seq_add_stmt_without_update (&seq, region_end); - gsi_insert_seq_before (&gsi, seq, GSI_SAME_STMT); - - /* instrument access at _2; */ - gsi = gsi_for_stmt (region_end); - build_check_stmt (location, gimple_assign_lhs (region_end), - &gsi, /*before_p=*/false, is_store, 1); - - if (then_bb == NULL) + update_mem_ref_hash_table (base, 1); + if (size_in_bytes != -1) update_mem_ref_hash_table (end, 1); *iter = gsi_for_stmt (gsi_stmt (*iter)); @@ -1850,6 +1828,7 @@ instrument_mem_region_access (tree base, tree len, static bool instrument_strlen_call (gimple_stmt_iterator *iter) { + gimple g; gimple call = gsi_stmt (*iter); gcc_assert (is_gimple_call (call)); @@ -1858,6 +1837,8 @@ instrument_strlen_call (gimple_stmt_iterator *iter) && DECL_BUILT_IN_CLASS (callee) == BUILT_IN_NORMAL && DECL_FUNCTION_CODE (callee) == BUILT_IN_STRLEN); + location_t loc = gimple_location (call); + tree len = gimple_call_lhs (call); if (len == NULL) /* Some passes might clear the return value of the strlen call; @@ -1866,50 +1847,35 @@ instrument_strlen_call (gimple_stmt_iterator *iter) return false; gcc_assert (INTEGRAL_TYPE_P (TREE_TYPE (len))); - location_t loc = gimple_location (call); - tree str_arg = gimple_call_arg (call, 0); + len = maybe_cast_to_ptrmode (loc, len, iter, /*before_p*/false); - /* Instrument the access to the first byte of str_arg. i.e: + tree str_arg = gimple_call_arg (call, 0); + bool start_instrumented = has_mem_ref_been_instrumented (str_arg, 1); - _1 = str_arg; instrument (_1); */ tree cptr_type = build_pointer_type (char_type_node); - gimple str_arg_ssa = - gimple_build_assign_with_ops (NOP_EXPR, - make_ssa_name (cptr_type, NULL), - str_arg, NULL); - gimple_set_location (str_arg_ssa, loc); - gimple_stmt_iterator gsi = *iter; - gsi_insert_before (&gsi, str_arg_ssa, GSI_NEW_STMT); - build_check_stmt (loc, gimple_assign_lhs (str_arg_ssa), &gsi, - /*before_p=*/false, /*is_store=*/false, 1); - - /* If we initially had an instruction like: - - int n = strlen (str) - - we now want to instrument the access to str[n], after the - instruction above.*/ - - /* So let's build the access to str[n] that is, access through the - pointer_plus expr: (_1 + len). */ - gimple stmt = - gimple_build_assign_with_ops (POINTER_PLUS_EXPR, - make_ssa_name (cptr_type, NULL), - gimple_assign_lhs (str_arg_ssa), - len); - gimple_set_location (stmt, loc); - gsi_insert_after (&gsi, stmt, GSI_NEW_STMT); - - build_check_stmt (loc, gimple_assign_lhs (stmt), &gsi, - /*before_p=*/false, /*is_store=*/false, 1); - - /* Ensure that iter points to the statement logically following the - one it was initially pointing to. */ - *iter = gsi; - /* As *ITER has been advanced to point to the next statement, let's - return true to inform transform_statements that it shouldn't - advance *ITER anymore; otherwises it will skip that next - statement, which wouldn't be instrumented. */ + g = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (cptr_type, NULL), + str_arg, NULL); + gimple_set_location (g, loc); + gsi_insert_before (iter, g, GSI_SAME_STMT); + str_arg = gimple_assign_lhs (g); + + build_check_stmt (loc, str_arg, NULL_TREE, 1, iter, + /*is_non_zero_len*/true, /*before_p=*/true, + /*is_store=*/false, /*is_scalar_access*/true, /*align*/0, + start_instrumented, start_instrumented); + + g = gimple_build_assign_with_ops (POINTER_PLUS_EXPR, + make_ssa_name (cptr_type, NULL), + str_arg, + len); + gimple_set_location (g, loc); + gsi_insert_after (iter, g, GSI_NEW_STMT); + + build_check_stmt (loc, gimple_assign_lhs (g), NULL_TREE, 1, iter, + /*is_non_zero_len*/true, /*before_p=*/false, + /*is_store=*/false, /*is_scalar_access*/true, /*align*/0); + return true; } @@ -2099,6 +2065,7 @@ transform_statements (void) if (has_stmt_been_instrumented_p (s)) gsi_next (&i); else if (gimple_assign_single_p (s) + && !gimple_clobber_p (s) && maybe_instrument_assignment (&i)) /* Nothing to do as maybe_instrument_assignment advanced the iterator I. */; @@ -2416,8 +2383,11 @@ asan_finish_file (void) nor after .LASAN* array. */ flag_sanitize &= ~SANITIZE_ADDRESS; - tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT); - append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); + if (flag_sanitize & SANITIZE_USER_ADDRESS) + { + tree fn = builtin_decl_implicit (BUILT_IN_ASAN_INIT); + append_to_statement_list (build_call_expr (fn, 0), &asan_ctor_statements); + } FOR_EACH_DEFINED_VARIABLE (vnode) if (TREE_ASM_WRITTEN (vnode->decl) && asan_protect_global (vnode->decl)) @@ -2454,7 +2424,7 @@ asan_finish_file (void) DECL_INITIAL (var) = ctor; varpool_assemble_decl (varpool_node_for_decl (var)); - fn = builtin_decl_implicit (BUILT_IN_ASAN_REGISTER_GLOBALS); + tree fn = builtin_decl_implicit (BUILT_IN_ASAN_REGISTER_GLOBALS); tree gcount_tree = build_int_cst (pointer_sized_int_node, gcount); append_to_statement_list (build_call_expr (fn, 2, build_fold_addr_expr (var), @@ -2469,11 +2439,218 @@ asan_finish_file (void) cgraph_build_static_cdtor ('D', dtor_statements, MAX_RESERVED_INIT_PRIORITY - 1); } - cgraph_build_static_cdtor ('I', asan_ctor_statements, - MAX_RESERVED_INIT_PRIORITY - 1); + if (asan_ctor_statements) + cgraph_build_static_cdtor ('I', asan_ctor_statements, + MAX_RESERVED_INIT_PRIORITY - 1); flag_sanitize |= SANITIZE_ADDRESS; } +/* Expand the ASAN_{LOAD,STORE} builtins. */ + +static bool +asan_expand_check_ifn (gimple_stmt_iterator *iter, bool use_calls) +{ + 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_CHECK_LAST); + bool is_scalar_access = (flags & ASAN_CHECK_SCALAR_ACCESS) != 0; + bool is_store = (flags & ASAN_CHECK_STORE) != 0; + bool is_non_zero_len = (flags & ASAN_CHECK_NON_ZERO_LEN) != 0; + bool start_instrumented = (flags & ASAN_CHECK_START_INSTRUMENTED) != 0; + bool end_instrumented = (flags & ASAN_CHECK_END_INSTRUMENTED) != 0; + + tree base = gimple_call_arg (g, 1); + tree len = gimple_call_arg (g, 2); + + HOST_WIDE_INT size_in_bytes + = is_scalar_access && tree_fits_shwi_p (len) ? tree_to_shwi (len) : -1; + + if (use_calls) + { + /* Instrument using callbacks. */ + gimple g + = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (pointer_sized_int_node, + NULL), + base, NULL_TREE); + gimple_set_location (g, loc); + gsi_insert_before (iter, g, GSI_SAME_STMT); + tree base_addr = gimple_assign_lhs (g); + + int nargs; + tree fun = check_func (is_store, size_in_bytes, &nargs); + if (nargs == 1) + g = gimple_build_call (fun, 1, base_addr); + else + { + gcc_assert (nargs == 2); + g = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (pointer_sized_int_node, + NULL), + len, NULL_TREE); + gimple_set_location (g, loc); + gsi_insert_before (iter, g, GSI_SAME_STMT); + tree sz_arg = gimple_assign_lhs (g); + g = gimple_build_call (fun, nargs, base_addr, sz_arg); + } + gimple_set_location (g, loc); + gsi_replace (iter, g, false); + return false; + } + + HOST_WIDE_INT real_size_in_bytes = size_in_bytes == -1 ? 1 : size_in_bytes; + + tree shadow_ptr_type = shadow_ptr_types[real_size_in_bytes == 16 ? 1 : 0]; + tree shadow_type = TREE_TYPE (shadow_ptr_type); + + gimple_stmt_iterator gsi = *iter; + + if (!is_non_zero_len) + { + /* So, the length of the memory area to asan-protect is + non-constant. Let's guard the generated instrumentation code + like: + + if (len != 0) + { + //asan instrumentation code goes here. + } + // falltrough instructions, starting with *ITER. */ + + g = gimple_build_cond (NE_EXPR, + len, + build_int_cst (TREE_TYPE (len), 0), + NULL_TREE, NULL_TREE); + gimple_set_location (g, loc); + + basic_block then_bb, fallthrough_bb; + insert_if_then_before_iter (g, iter, /*then_more_likely_p=*/true, + &then_bb, &fallthrough_bb); + /* Note that fallthrough_bb starts with the statement that was + pointed to by ITER. */ + + /* The 'then block' of the 'if (len != 0) condition is where + we'll generate the asan instrumentation code now. */ + gsi = gsi_last_bb (then_bb); + } + + /* Get an iterator on the point where we can add the condition + statement for the instrumentation. */ + basic_block then_bb, else_bb; + gsi = create_cond_insert_point (&gsi, /*before_p*/false, + /*then_more_likely_p=*/false, + /*create_then_fallthru_edge=*/false, + &then_bb, + &else_bb); + + g = gimple_build_assign_with_ops (NOP_EXPR, + make_ssa_name (pointer_sized_int_node, + NULL), + base, NULL_TREE); + gimple_set_location (g, loc); + gsi_insert_before (&gsi, g, GSI_NEW_STMT); + tree base_addr = gimple_assign_lhs (g); + + tree t = NULL_TREE; + if (real_size_in_bytes >= 8) + { + tree shadow = build_shadow_mem_access (&gsi, loc, base_addr, + shadow_ptr_type); + t = shadow; + } + else + { + /* Slow path for 1, 2 and 4 byte accesses. */ + + if (!start_instrumented) + { + /* Test (shadow != 0) + & ((base_addr & 7) + (real_size_in_bytes - 1)) >= shadow). */ + tree shadow = build_shadow_mem_access (&gsi, loc, base_addr, + shadow_ptr_type); + gimple shadow_test = build_assign (NE_EXPR, shadow, 0); + gimple_seq seq = NULL; + gimple_seq_add_stmt (&seq, shadow_test); + gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, base_addr, 7)); + gimple_seq_add_stmt (&seq, build_type_cast (shadow_type, + gimple_seq_last (seq))); + if (real_size_in_bytes > 1) + gimple_seq_add_stmt (&seq, + build_assign (PLUS_EXPR, gimple_seq_last (seq), + real_size_in_bytes - 1)); + gimple_seq_add_stmt (&seq, build_assign (GE_EXPR, + gimple_seq_last (seq), + shadow)); + gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test, + gimple_seq_last (seq))); + t = gimple_assign_lhs (gimple_seq_last (seq)); + gimple_seq_set_location (seq, loc); + gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); + } + + /* For non-constant, misaligned or otherwise weird access sizes, + check first and last byte. */ + if (size_in_bytes == -1 && !end_instrumented) + { + g = gimple_build_assign_with_ops (MINUS_EXPR, + make_ssa_name (pointer_sized_int_node, NULL), + len, + build_int_cst (pointer_sized_int_node, 1)); + gimple_set_location (g, loc); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + tree last = gimple_assign_lhs (g); + g = gimple_build_assign_with_ops (PLUS_EXPR, + make_ssa_name (pointer_sized_int_node, NULL), + base_addr, + last); + gimple_set_location (g, loc); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + tree base_end_addr = gimple_assign_lhs (g); + + tree shadow = build_shadow_mem_access (&gsi, loc, base_end_addr, + shadow_ptr_type); + gimple shadow_test = build_assign (NE_EXPR, shadow, 0); + gimple_seq seq = NULL; + gimple_seq_add_stmt (&seq, shadow_test); + gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, + base_end_addr, 7)); + gimple_seq_add_stmt (&seq, build_type_cast (shadow_type, + gimple_seq_last (seq))); + gimple_seq_add_stmt (&seq, build_assign (GE_EXPR, + gimple_seq_last (seq), + shadow)); + gimple_seq_add_stmt (&seq, build_assign (BIT_AND_EXPR, shadow_test, + gimple_seq_last (seq))); + if (!start_instrumented) + gimple_seq_add_stmt (&seq, build_assign (BIT_IOR_EXPR, t, + gimple_seq_last (seq))); + t = gimple_assign_lhs (gimple_seq_last (seq)); + gimple_seq_set_location (seq, loc); + gsi_insert_seq_after (&gsi, seq, GSI_CONTINUE_LINKING); + } + } + + g = gimple_build_cond (NE_EXPR, t, build_int_cst (TREE_TYPE (t), 0), + NULL_TREE, NULL_TREE); + gimple_set_location (g, loc); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + + /* Generate call to the run-time library (e.g. __asan_report_load8). */ + gsi = gsi_start_bb (then_bb); + int nargs; + tree fun = report_error_func (is_store, size_in_bytes, &nargs); + g = gimple_build_call (fun, nargs, base_addr, len); + gimple_set_location (g, loc); + gsi_insert_after (&gsi, g, GSI_NEW_STMT); + + gsi_remove (iter, true); + *iter = gsi_start_bb (else_bb); + + return true; +} + /* Instrument the current function. */ static unsigned int @@ -2585,25 +2762,55 @@ execute_sanopt (void) { basic_block bb; + int asan_num_accesses = 0; + if (flag_sanitize & SANITIZE_ADDRESS) + { + gimple_stmt_iterator gsi; + FOR_EACH_BB_FN (bb, cfun) + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + if (is_gimple_call (stmt) && gimple_call_internal_p (stmt) + && gimple_call_internal_fn (stmt) == IFN_ASAN_CHECK) + ++asan_num_accesses; + } + } + + bool use_calls = ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD < INT_MAX + && (flag_sanitize & SANITIZE_KERNEL_ADDRESS) + && asan_num_accesses >= ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD; + FOR_EACH_BB_FN (bb, cfun) { gimple_stmt_iterator gsi; - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); ) { gimple stmt = gsi_stmt (gsi); + bool no_next = false; if (!is_gimple_call (stmt)) - continue; + { + gsi_next (&gsi); + continue; + } if (gimple_call_internal_p (stmt)) - switch (gimple_call_internal_fn (stmt)) - { - case IFN_UBSAN_NULL: - ubsan_expand_null_ifn (gsi); - break; - default: - break; - } + { + enum internal_fn ifn = gimple_call_internal_fn (stmt); + switch (ifn) + { + case IFN_UBSAN_NULL: + ubsan_expand_null_ifn (gsi); + break; + case IFN_ASAN_CHECK: + { + no_next = asan_expand_check_ifn (&gsi, use_calls); + break; + } + default: + break; + } + } if (dump_file && (dump_flags & TDF_DETAILS)) { @@ -2611,6 +2818,9 @@ execute_sanopt (void) print_gimple_stmt (dump_file, stmt, 0, dump_flags); fprintf (dump_file, "\n"); } + + if (!no_next) + gsi_next (&gsi); } } return 0; diff --git a/gcc-4.9/gcc/auto-profile.c b/gcc-4.9/gcc/auto-profile.c index c69c1e68c..88115840c 100644 --- a/gcc-4.9/gcc/auto-profile.c +++ b/gcc-4.9/gcc/auto-profile.c @@ -1,5 +1,5 @@ -/* Calculate branch probabilities, and basic block execution counts. - Copyright (C) 2012. Free Software Foundation, Inc. +/* Read and annotate call graph profile from the auto profile data file. + Copyright (C) 2014. Free Software Foundation, Inc. Contributed by Dehao Chen (dehao@google.com) This file is part of GCC. @@ -18,19 +18,17 @@ You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ -/* Read and annotate call graph profile from the auto profile data - file. */ +#include "config.h" +#include "system.h" #include #include -#include #include -#include "config.h" -#include "system.h" #include "coretypes.h" #include "tree.h" #include "flags.h" +#include "vec.h" #include "basic-block.h" #include "diagnostic-core.h" #include "gcov-io.h" @@ -73,26 +71,34 @@ along with GCC; see the file COPYING3. If not see Phase 1: Read profile from the profile data file. The following info is read from the profile datafile: - * string_table: a map between function name and its index. - * autofdo_source_profile: a map from function_instance name to - function_instance. This is represented as a forest of - function_instances. - * autofdo_module_profile: a map from module name to its - compilation/aux-module info. - * WorkingSet: a histogram of how many instructions are covered for a - given percentage of total cycles. - - Phase 2: Early inline. + * string_table: a map between function name and its index. + * autofdo_source_profile: a map from function_instance name to + function_instance. This is represented as a forest of + function_instances. + * WorkingSet: a histogram of how many instructions are covered for a + given percentage of total cycles. This is describing the binary + level information (not source level). This info is used to help + decide if we want aggressive optimizations that could increase + code footprint (e.g. loop unroll etc.) + A function instance is an instance of function that could either be a + standalone symbol, or a clone of a function that is inlined into another + function. + + Phase 2: Early inline + valur profile transformation. Early inline uses autofdo_source_profile to find if a callsite is: - * inlined in the profiled binary. - * callee body is hot in the profiling run. + * inlined in the profiled binary. + * callee body is hot in the profiling run. If both condition satisfies, early inline will inline the callsite regardless of the code growth. + Phase 2 is an iterative process. During each iteration, we also check + if an indirect callsite is promoted and inlined in the profiling run. + If yes, vpt will happen to force promote it and in the next iteration, + einline will inline the promoted callsite in the next iteration. Phase 3: Annotate control flow graph. AutoFDO uses a separate pass to: - * Annotate basic block count - * Estimate branch probability + * Annotate basic block count + * Estimate branch probability After the above 3 phases, all profile is readily annotated on the GCC IR. AutoFDO tries to reuse all FDO infrastructure as much as possible to make @@ -102,16 +108,17 @@ along with GCC; see the file COPYING3. If not see #define DEFAULT_AUTO_PROFILE_FILE "fbdata.afdo" -namespace autofdo { +namespace autofdo +{ /* Represent a source location: (function_decl, lineno). */ typedef std::pair decl_lineno; /* Represent an inline stack. vector[0] is the leaf node. */ -typedef std::vector inline_stack; +typedef auto_vec inline_stack; /* String array that stores function names. */ -typedef std::vector string_vector; +typedef auto_vec string_vector; /* Map from function name's index in string_table to target's execution count. */ @@ -130,7 +137,7 @@ struct count_info /* Map from indirect call target to its sample count. */ icall_target_map targets; - /* Whether this inline stack is already used in annotation. + /* Whether this inline stack is already used in annotation. Each inline stack should only be used to annotate IR once. This will be enforced when instruction-level discriminator @@ -141,14 +148,20 @@ struct count_info /* operator< for "const char *". */ struct string_compare { - bool operator() (const char *a, const char *b) const - { return strcmp (a, b) < 0; } + bool operator()(const char *a, const char *b) const + { + return strcmp (a, b) < 0; + } }; /* Store a string array, indexed by string position in the array. */ -class string_table { +class string_table +{ public: - static string_table *create (); + string_table () + {} + + ~string_table (); /* For a given string, returns its index. */ int get_index (const char *name) const; @@ -159,10 +172,10 @@ public: /* For a given index, returns the string. */ const char *get_name (int index) const; -private: - string_table () {} + /* Read profile, return TRUE on success. */ bool read (); +private: typedef std::map string_index_map; string_vector vector_; string_index_map map_; @@ -170,34 +183,47 @@ private: /* Profile of a function instance: 1. total_count of the function. - 2. head_count of the function (only valid when function is a top-level - function_instance, i.e. it is the original copy instead of the - inlined copy). - 3. map from source location (decl_lineno) of the inlined callsite to - profile (count_info). + 2. head_count (entry basic block count) of the function (only valid when + function is a top-level function_instance, i.e. it is the original copy + instead of the inlined copy). + 3. map from source location (decl_lineno) to profile (count_info). 4. map from callsite to callee function_instance. */ -class function_instance { +class function_instance +{ public: - typedef std::vector function_instance_stack; + typedef auto_vec function_instance_stack; /* Read the profile and return a function_instance with head count as HEAD_COUNT. Recursively read callsites to create nested function_instances too. STACK is used to track the recursive creation process. */ - static function_instance *read_function_instance ( - function_instance_stack *stack, gcov_type head_count); + static function_instance * + read_function_instance (function_instance_stack *stack, + gcov_type head_count); /* Recursively deallocate all callsites (nested function_instances). */ ~function_instance (); /* Accessors. */ - int name () const { return name_; } - gcov_type total_count () const { return total_count_; } - gcov_type head_count () const { return head_count_; } + int + name () const + { + return name_; + } + gcov_type + total_count () const + { + return total_count_; + } + gcov_type + head_count () const + { + return head_count_; + } - /* Recursively traverse STACK starting from LEVEL to find the corresponding - function_instance. */ - function_instance *get_function_instance (const inline_stack &stack, - unsigned level); + /* Traverse callsites of the current function_instance to find one at the + location of LINENO. */ + function_instance *get_function_instance_by_decl (unsigned lineno, + tree decl) const; /* Store the profile info for LOC in INFO. Return TRUE if profile info is found. */ @@ -214,12 +240,17 @@ public: void mark_annotated (location_t loc); private: + /* Callsite, represented as (decl_lineno, callee_function_name_index). */ + typedef std::pair callsite; + + /* Map from callsite to callee function_instance. */ + typedef std::map callsite_map; + function_instance (unsigned name, gcov_type head_count) - : name_(name), total_count_(0), head_count_(head_count) {} + : name_ (name), total_count_ (0), head_count_ (head_count) + { + } - /* Map from callsite decl_lineno (lineno in higher 16 bits, discriminator - in lower 16 bits) to callee function_instance. */ - typedef std::map callsite_map; /* Map from source location (decl_lineno) to profile (count_info). */ typedef std::map position_count_map; @@ -240,16 +271,19 @@ private: }; /* Profile for all functions. */ -class autofdo_source_profile { +class autofdo_source_profile +{ public: - static autofdo_source_profile *create () - { - autofdo_source_profile *map = new autofdo_source_profile (); - if (map->read ()) - return map; - delete map; - return NULL; - } + static autofdo_source_profile * + create () + { + autofdo_source_profile *map = new autofdo_source_profile (); + + if (map->read ()) + return map; + delete map; + return NULL; + } ~autofdo_source_profile (); @@ -277,8 +311,7 @@ public: private: /* Map from function_instance name index (in string_table) to function_instance. */ - typedef std::map - name_function_instance_map; + typedef std::map name_function_instance_map; autofdo_source_profile () {} @@ -287,8 +320,8 @@ private: /* Return the function_instance in the profile that correspond to the inline STACK. */ - function_instance *get_function_instance_by_inline_stack ( - const inline_stack &stack) const; + function_instance * + get_function_instance_by_inline_stack (const inline_stack &stack) const; name_function_instance_map map_; }; @@ -300,7 +333,7 @@ public: { autofdo_module_profile *map = new autofdo_module_profile (); if (map->read ()) - return map; + return map; delete map; return NULL; } @@ -332,6 +365,7 @@ private: /* Store the strings read from the profile data file. */ static string_table *afdo_string_table; + /* Store the AutoFDO source profile. */ static autofdo_source_profile *afdo_source_profile; @@ -344,9 +378,10 @@ static struct gcov_ctr_summary *afdo_profile_info; /* Helper functions. */ /* Return the original name of NAME: strip the suffix that starts - with '.' */ + with '.' Caller is responsible for freeing RET. */ -static const char *get_original_name (const char *name) +static char * +get_original_name (const char *name) { char *ret = xstrdup (name); char *find = strchr (ret, '.'); @@ -362,8 +397,9 @@ static const char *get_original_name (const char *name) static unsigned get_combined_location (location_t loc, tree decl) { + /* TODO: allow more bits for line and less bits for discriminator. */ return ((LOCATION_LINE (loc) - DECL_SOURCE_LINE (decl)) << 16) - | get_discriminator_from_locus (loc); + | get_discriminator_from_locus (loc); } /* Return the function decl of a given lexical BLOCK. */ @@ -397,23 +433,23 @@ get_inline_stack (location_t locus, inline_stack *stack) { int level = 0; for (block = BLOCK_SUPERCONTEXT (block); - block && (TREE_CODE (block) == BLOCK); - block = BLOCK_SUPERCONTEXT (block)) - { - location_t tmp_locus = BLOCK_SOURCE_LOCATION (block); - if (LOCATION_LOCUS (tmp_locus) == UNKNOWN_LOCATION) - continue; - - tree decl = get_function_decl_from_block (block); - stack->push_back (std::make_pair ( - decl, get_combined_location (locus, decl))); - locus = tmp_locus; - level++; - } + block && (TREE_CODE (block) == BLOCK); + block = BLOCK_SUPERCONTEXT (block)) + { + location_t tmp_locus = BLOCK_SOURCE_LOCATION (block); + if (LOCATION_LOCUS (tmp_locus) == UNKNOWN_LOCATION) + continue; + + tree decl = get_function_decl_from_block (block); + stack->safe_push ( + std::make_pair (decl, get_combined_location (locus, decl))); + locus = tmp_locus; + level++; + } } - stack->push_back (std::make_pair ( - current_function_decl, - get_combined_location (locus, current_function_decl))); + stack->safe_push ( + std::make_pair (current_function_decl, + get_combined_location (locus, current_function_decl))); } /* Return STMT's combined location, which is a 32bit integer in which @@ -427,12 +463,11 @@ get_relative_location_for_stmt (gimple stmt) if (LOCATION_LOCUS (locus) == UNKNOWN_LOCATION) return UNKNOWN_LOCATION; - for (tree block = gimple_block (stmt); - block && (TREE_CODE (block) == BLOCK); + for (tree block = gimple_block (stmt); block && (TREE_CODE (block) == BLOCK); block = BLOCK_SUPERCONTEXT (block)) if (LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (block)) != UNKNOWN_LOCATION) - return get_combined_location ( - locus, get_function_decl_from_block (block)); + return get_combined_location (locus, + get_function_decl_from_block (block)); return get_combined_location (locus, current_function_decl); } @@ -446,44 +481,50 @@ has_indirect_call (basic_block bb) for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) { gimple stmt = gsi_stmt (gsi); - if (gimple_code (stmt) == GIMPLE_CALL - && (gimple_call_fn (stmt) == NULL - || TREE_CODE (gimple_call_fn (stmt)) != FUNCTION_DECL)) - return true; + if (gimple_code (stmt) == GIMPLE_CALL && !gimple_call_internal_p (stmt) + && (gimple_call_fn (stmt) == NULL + || TREE_CODE (gimple_call_fn (stmt)) != FUNCTION_DECL)) + return true; } return false; } /* Member functions for string_table. */ -string_table * -string_table::create () +/* Deconstructor. */ + +string_table::~string_table () { - string_table *map = new string_table(); - if (map->read ()) - return map; - delete map; - return NULL; + for (unsigned i = 0; i < vector_.length (); i++) + free (vector_[i]); } + +/* Return the index of a given function NAME. Return -1 if NAME is not + found in string table. */ + int string_table::get_index (const char *name) const { if (name == NULL) return -1; string_index_map::const_iterator iter = map_.find (name); - if (iter == map_.end()) + if (iter == map_.end ()) return -1; else return iter->second; } +/* Return the index of a given function DECL. Return -1 if DECL is not + found in string table. */ + int string_table::get_index_by_decl (tree decl) const { - const char *name = get_original_name ( - IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); + char *name + = get_original_name (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl))); int ret = get_index (name); + free (name); if (ret != -1) return ret; ret = get_index (lang_hooks.dwarf_name (decl, 0)); @@ -495,13 +536,17 @@ string_table::get_index_by_decl (tree decl) const return -1; } +/* Return the function name of a given INDEX. */ + const char * string_table::get_name (int index) const { - gcc_assert (index > 0 && index < (int) vector_.size()); + gcc_assert (index > 0 && index < (int)vector_.length ()); return vector_[index]; } +/* Read the string table. Return TRUE if reading is successful. */ + bool string_table::read () { @@ -513,34 +558,47 @@ string_table::read () unsigned string_num = gcov_read_unsigned (); for (unsigned i = 0; i < string_num; i++) { - vector_.push_back (get_original_name (gcov_read_string ())); - map_[vector_.back()] = i; + vector_.safe_push (get_original_name (gcov_read_string ())); + map_[vector_.last ()] = i; } return true; } - /* Member functions for function_instance. */ function_instance::~function_instance () { - for (callsite_map::iterator iter = callsites.begin(); - iter != callsites.end(); ++iter) + for (callsite_map::iterator iter = callsites.begin (); + iter != callsites.end (); ++iter) delete iter->second; } -/* Recursively traverse STACK starting from LEVEL to find the corresponding - function_instance. */ +/* Traverse callsites of the current function_instance to find one at the + location of LINENO and callee name represented in DECL. */ function_instance * -function_instance::get_function_instance ( - const inline_stack &stack, unsigned level) +function_instance::get_function_instance_by_decl (unsigned lineno, + tree decl) const { - if (level == 0) - return this; - callsite_map::const_iterator ret = callsites.find (stack[level].second); - if (ret != callsites.end () && ret->second != NULL) - return ret->second->get_function_instance (stack, level - 1); + int func_name_idx = afdo_string_table->get_index_by_decl (decl); + if (func_name_idx != -1) + { + callsite_map::const_iterator ret + = callsites.find (std::make_pair (lineno, func_name_idx)); + if (ret != callsites.end ()) + return ret->second; + } + func_name_idx + = afdo_string_table->get_index (lang_hooks.dwarf_name (decl, 0)); + if (func_name_idx != -1) + { + callsite_map::const_iterator ret + = callsites.find (std::make_pair (lineno, func_name_idx)); + if (ret != callsites.end ()) + return ret->second; + } + if (DECL_ABSTRACT_ORIGIN (decl)) + return get_function_instance_by_decl (lineno, DECL_ABSTRACT_ORIGIN (decl)); else return NULL; } @@ -573,25 +631,27 @@ function_instance::mark_annotated (location_t loc) MAP, return the total count for all inlined indirect calls. */ gcov_type -function_instance::find_icall_target_map ( - gimple stmt, icall_target_map *map) const +function_instance::find_icall_target_map (gimple stmt, + icall_target_map *map) const { gcov_type ret = 0; unsigned stmt_offset = get_relative_location_for_stmt (stmt); - for (callsite_map::const_iterator iter = callsites.begin(); - iter != callsites.end(); ++iter) + for (callsite_map::const_iterator iter = callsites.begin (); + iter != callsites.end (); ++iter) { - unsigned callee = iter->second->name(); + unsigned callee = iter->second->name (); /* Check if callsite location match the stmt. */ - if (iter->first != stmt_offset) - continue; + if (iter->first.first != stmt_offset) + continue; struct cgraph_node *node = find_func_by_global_id ( - (unsigned long long) afdo_string_table->get_name (callee), true); + (unsigned long long) afdo_string_table->get_name (callee), true); if (node == NULL) - continue; + continue; if (!check_ic_target (stmt, node)) - continue; + continue; + if (!node->definition) + continue; (*map)[callee] = iter->second->total_count (); ret += iter->second->total_count (); } @@ -602,15 +662,42 @@ function_instance::find_icall_target_map ( HEAD_COUNT. Recursively read callsites to create nested function_instances too. STACK is used to track the recursive creation process. */ +/* function instance profile format: + + ENTRY_COUNT: 8 bytes + NAME_INDEX: 4 bytes + NUM_POS_COUNTS: 4 bytes + NUM_CALLSITES: 4 byte + POS_COUNT_1: + POS_1_OFFSET: 4 bytes + NUM_TARGETS: 4 bytes + COUNT: 8 bytes + TARGET_1: + VALUE_PROFILE_TYPE: 4 bytes + TARGET_IDX: 8 bytes + COUNT: 8 bytes + TARGET_2 + ... + TARGET_n + POS_COUNT_2 + ... + POS_COUNT_N + CALLSITE_1: + CALLSITE_1_OFFSET: 4 bytes + FUNCTION_INSTANCE_PROFILE (nested) + CALLSITE_2 + ... + CALLSITE_n. */ + function_instance * -function_instance::read_function_instance ( - function_instance_stack *stack, gcov_type head_count) +function_instance::read_function_instance (function_instance_stack *stack, + gcov_type head_count) { unsigned name = gcov_read_unsigned (); unsigned num_pos_counts = gcov_read_unsigned (); unsigned num_callsites = gcov_read_unsigned (); function_instance *s = new function_instance (name, head_count); - stack->push_back(s); + stack->safe_push (s); for (unsigned i = 0; i < num_pos_counts; i++) { @@ -618,22 +705,25 @@ function_instance::read_function_instance ( unsigned num_targets = gcov_read_unsigned (); gcov_type count = gcov_read_counter (); s->pos_counts[offset].count = count; - for (unsigned j = 0; j < stack->size(); j++) - (*stack)[j]->total_count_ += count; + for (unsigned j = 0; j < stack->length (); j++) + (*stack)[j]->total_count_ += count; for (unsigned j = 0; j < num_targets; j++) - { - /* Only indirect call target histogram is supported now. */ - gcov_read_unsigned (); - gcov_type target_idx = gcov_read_counter (); - s->pos_counts[offset].targets[target_idx] = - gcov_read_counter (); - } + { + /* Only indirect call target histogram is supported now. */ + gcov_read_unsigned (); + gcov_type target_idx = gcov_read_counter (); + s->pos_counts[offset].targets[target_idx] = gcov_read_counter (); + } } - for (unsigned i = 0; i < num_callsites; i++) { - unsigned offset = gcov_read_unsigned (); - s->callsites[offset] = read_function_instance (stack, 0); - } - stack->pop_back(); + for (unsigned i = 0; i < num_callsites; i++) + { + unsigned offset = gcov_read_unsigned (); + function_instance *callee_function_instance + = read_function_instance (stack, 0); + s->callsites[std::make_pair (offset, callee_function_instance->name ())] + = callee_function_instance; + } + stack->pop (); return s; } @@ -643,11 +733,11 @@ gcov_type function_instance::total_annotated_count () const { gcov_type ret = 0; - for (callsite_map::const_iterator iter = callsites.begin(); - iter != callsites.end(); ++iter) + for (callsite_map::const_iterator iter = callsites.begin (); + iter != callsites.end (); ++iter) ret += iter->second->total_annotated_count (); - for (position_count_map::const_iterator iter = pos_counts.begin(); - iter != pos_counts.end(); ++iter) + for (position_count_map::const_iterator iter = pos_counts.begin (); + iter != pos_counts.end (); ++iter) if (iter->second.annotated) ret += iter->second.count; return ret; @@ -671,13 +761,13 @@ autofdo_source_profile::write_annotated_count () const iter != map_.end (); ++iter) if (iter->second->total_count () > 0) { - char buf[1024]; - snprintf (buf, 1024, - "%s:"HOST_WIDEST_INT_PRINT_DEC":"HOST_WIDEST_INT_PRINT_DEC, - afdo_string_table->get_name (iter->first), - iter->second->total_count (), - iter->second->total_annotated_count ()); - dw2_asm_output_nstring (buf, (size_t)-1, NULL); + char buf[1024]; + snprintf (buf, 1024, + "%s:"HOST_WIDEST_INT_PRINT_DEC":"HOST_WIDEST_INT_PRINT_DEC, + afdo_string_table->get_name (iter->first), + iter->second->total_count (), + iter->second->total_annotated_count ()); + dw2_asm_output_nstring (buf, (size_t)-1, NULL); } } @@ -700,7 +790,7 @@ autofdo_source_profile::get_function_instance_by_decl (tree decl) const if (index == -1) return NULL; name_function_instance_map::const_iterator ret = map_.find (index); - return ret == map_.end() ? NULL : ret->second; + return ret == map_.end () ? NULL : ret->second; } /* Find count_info for a given gimple STMT. If found, store the count_info @@ -714,19 +804,22 @@ autofdo_source_profile::get_count_info (gimple stmt, count_info *info) const inline_stack stack; get_inline_stack (gimple_location (stmt), &stack); - if (stack.size () == 0) + if (stack.length () == 0) return false; - const function_instance *s = get_function_instance_by_inline_stack (stack); + function_instance *s = get_function_instance_by_inline_stack (stack); if (s == NULL) return false; return s->get_count_info (stack[0].second, info); } +/* Mark LOC as annotated. */ + void -autofdo_source_profile::mark_annotated (location_t loc) { +autofdo_source_profile::mark_annotated (location_t loc) +{ inline_stack stack; get_inline_stack (loc, &stack); - if (stack.size () == 0) + if (stack.length () == 0) return; function_instance *s = get_function_instance_by_inline_stack (stack); if (s == NULL) @@ -738,8 +831,8 @@ autofdo_source_profile::mark_annotated (location_t loc) { Return true if INFO is updated. */ bool -autofdo_source_profile::update_inlined_ind_target ( - gimple stmt, count_info *info) +autofdo_source_profile::update_inlined_ind_target (gimple stmt, + count_info *info) { if (LOCATION_LOCUS (gimple_location (stmt)) == cfun->function_end_locus) return false; @@ -747,8 +840,8 @@ autofdo_source_profile::update_inlined_ind_target ( count_info old_info; get_count_info (stmt, &old_info); gcov_type total = 0; - for (icall_target_map::const_iterator iter = old_info.targets.begin(); - iter != old_info.targets.end(); ++iter) + for (icall_target_map::const_iterator iter = old_info.targets.begin (); + iter != old_info.targets.end (); ++iter) total += iter->second; /* Program behavior changed, original promoted (and inlined) target is not @@ -758,21 +851,21 @@ autofdo_source_profile::update_inlined_ind_target ( count of the unpromoted targets (stored in old_info). If it is no less than half of the callsite count (stored in INFO), the original promoted target is considered not hot any more. */ - if (total >= info->count * 0.5) + if (total >= info->count / 2) return false; inline_stack stack; get_inline_stack (gimple_location (stmt), &stack); - if (stack.size () == 0) + if (stack.length () == 0) return false; - const function_instance *s = get_function_instance_by_inline_stack (stack); + function_instance *s = get_function_instance_by_inline_stack (stack); if (s == NULL) return false; icall_target_map map; if (s->find_icall_target_map (stmt, &map) == 0) return false; - for (icall_target_map::const_iterator iter = map.begin(); - iter != map.end(); ++iter) + for (icall_target_map::const_iterator iter = map.begin (); + iter != map.end (); ++iter) info->targets[iter->first] = iter->second; return true; } @@ -784,10 +877,10 @@ autofdo_source_profile::get_callsite_total_count ( struct cgraph_edge *edge) const { inline_stack stack; - stack.push_back (std::make_pair(edge->callee->decl, 0)); + stack.safe_push (std::make_pair (edge->callee->decl, 0)); get_inline_stack (gimple_location (edge->call_stmt), &stack); - const function_instance *s = get_function_instance_by_inline_stack (stack); + function_instance *s = get_function_instance_by_inline_stack (stack); if (s == NULL) return 0; else @@ -796,6 +889,16 @@ autofdo_source_profile::get_callsite_total_count ( /* Read AutoFDO profile and returns TRUE on success. */ +/* source profile format: + + GCOV_TAG_AFDO_FUNCTION: 4 bytes + LENGTH: 4 bytes + NUM_FUNCTIONS: 4 bytes + FUNCTION_INSTANCE_1 + FUNCTION_INSTANCE_2 + ... + FUNCTION_INSTANCE_N. */ + bool autofdo_source_profile::read () { @@ -815,7 +918,7 @@ autofdo_source_profile::read () { function_instance::function_instance_stack stack; function_instance *s = function_instance::read_function_instance ( - &stack, gcov_read_counter ()); + &stack, gcov_read_counter ()); afdo_profile_info->sum_all += s->total_count (); map_[s->name ()] = s; } @@ -830,11 +933,18 @@ autofdo_source_profile::get_function_instance_by_inline_stack ( const inline_stack &stack) const { name_function_instance_map::const_iterator iter = map_.find ( - afdo_string_table->get_index_by_decl ( - stack[stack.size() - 1].first)); - return iter == map_.end() - ? NULL - : iter->second->get_function_instance (stack, stack.size() - 1); + afdo_string_table->get_index_by_decl (stack[stack.length () - 1].first)); + if (iter == map_.end()) + return NULL; + function_instance *s = iter->second; + for (unsigned i = stack.length() - 1; i > 0; i--) + { + s = s->get_function_instance_by_decl ( + stack[i].second, stack[i - 1].first); + if (s == NULL) + return NULL; + } + return s; } @@ -863,16 +973,16 @@ autofdo_module_profile::read () unsigned lang = gcov_read_unsigned (); unsigned ggc_memory = gcov_read_unsigned (); for (unsigned j = 0; j < 7; j++) - { - num_array[j] = gcov_read_unsigned (); - total_num += num_array[j]; - } + { + num_array[j] = gcov_read_unsigned (); + total_num += num_array[j]; + } gcov_module_info *module = XCNEWVAR ( - gcov_module_info, - sizeof (gcov_module_info) + sizeof (char *) * total_num); + gcov_module_info, + sizeof (gcov_module_info) + sizeof (char *) * total_num); std::pair ret = map_.insert( - name_target_map::value_type (name, AuxInfo())); + name_target_map::value_type (name, AuxInfo())); gcc_assert (ret.second); ret.first->second.second = module; module->ident = i + 1; @@ -888,14 +998,14 @@ autofdo_module_profile::read () module->is_primary = strcmp (name, in_fnames[0]) == 0; module->flags = module->is_primary ? exported : 1; for (unsigned j = 0; j < num_array[0]; j++) - ret.first->second.first.push_back (xstrdup (gcov_read_string ())); + ret.first->second.first.safe_push (xstrdup (gcov_read_string ())); for (unsigned j = 0; j < total_num - num_array[0]; j++) - module->string_array[j] = xstrdup (gcov_read_string ()); + module->string_array[j] = xstrdup (gcov_read_string ()); } return true; } -/* Read the profile from the profile file. */ +/* Read data from profile data file. */ static void read_profile (void) @@ -913,8 +1023,8 @@ read_profile (void) gcov_read_unsigned (); /* string_table. */ - afdo_string_table = string_table::create (); - if (afdo_string_table == NULL) + afdo_string_table = new string_table (); + if (!afdo_string_table->read()) error ("Cannot read string table from %s.", auto_profile_file); /* autofdo_source_profile. */ @@ -953,7 +1063,7 @@ read_aux_modules (void) const string_vector *aux_modules = afdo_module_profile->get_aux_modules (in_fnames[0]); - unsigned num_aux_modules = aux_modules ? aux_modules->size() : 0; + unsigned num_aux_modules = aux_modules ? aux_modules->length() : 0; module_infos = XCNEWVEC (gcov_module_info *, num_aux_modules + 1); module_infos[0] = module; @@ -962,55 +1072,61 @@ read_aux_modules (void) if (aux_modules == NULL) return; unsigned curr_module = 1, max_group = PARAM_VALUE (PARAM_MAX_LIPO_GROUP); - for (string_vector::const_iterator iter = aux_modules->begin(); - iter != aux_modules->end(); ++iter) - { - gcov_module_info *aux_module = afdo_module_profile->get_module (*iter); - if (aux_module == module) - continue; - if (aux_module == NULL) - { - if (flag_opt_info) - inform (0, "aux module %s cannot be found.", *iter); - continue; - } - if ((aux_module->lang & GCOV_MODULE_LANG_MASK) != - (module->lang & GCOV_MODULE_LANG_MASK)) - { - if (flag_opt_info) - inform (0, "Not importing %s: source language" - " different from primary module's source language", *iter); - continue; - } - if ((aux_module->lang & GCOV_MODULE_ASM_STMTS) - && flag_ripa_disallow_asm_modules) - { - if (flag_opt_info) - inform (0, "Not importing %s: contains " - "assembler statements", *iter); - continue; - } - if (max_group != 0 && curr_module >= max_group) - { - if (flag_opt_info) - inform (0, "Not importing %s: maximum group size reached", *iter); - continue; - } - if (incompatible_cl_args (module, aux_module)) - { - if (flag_opt_info) - inform (0, "Not importing %s: command-line" - " arguments not compatible with primary module", *iter); - continue; - } - module_infos[curr_module++] = aux_module; - add_input_filename (*iter); - record_module_name (aux_module->ident, lbasename (*iter)); - } + int i; + char *str; + FOR_EACH_VEC_ELT (*aux_modules, i, str) + { + gcov_module_info *aux_module = afdo_module_profile->get_module (str); + if (aux_module == module) + continue; + if (aux_module == NULL) + { + if (flag_opt_info) + inform (0, "aux module %s cannot be found.", str); + continue; + } + if ((aux_module->lang & GCOV_MODULE_LANG_MASK) != + (module->lang & GCOV_MODULE_LANG_MASK)) + { + if (flag_opt_info) + inform (0, "Not importing %s: source language" + " different from primary module's source language", str); + continue; + } + if ((aux_module->lang & GCOV_MODULE_ASM_STMTS) + && flag_ripa_disallow_asm_modules) + { + if (flag_opt_info) + inform (0, "Not importing %s: contains " + "assembler statements", str); + continue; + } + if (max_group != 0 && curr_module >= max_group) + { + if (flag_opt_info) + inform (0, "Not importing %s: maximum group size reached", str); + continue; + } + if (incompatible_cl_args (module, aux_module)) + { + if (flag_opt_info) + inform (0, "Not importing %s: command-line" + " arguments not compatible with primary module", str); + continue; + } + module_infos[curr_module++] = aux_module; + add_input_filename (str); + record_module_name (aux_module->ident, lbasename (str)); + } } /* From AutoFDO profiles, find values inside STMT for that we want to measure - histograms for indirect-call optimization. */ + histograms for indirect-call optimization. + + This function is actually served for 2 purposes: +     * before annotation, we need to mark histogram, promote and inline +     * after annotation, we just need to mark, and let follow-up logic to +       decide if it needs to promote and inline. */ static void afdo_indirect_call (gimple_stmt_iterator *gsi, const icall_target_map &map) @@ -1018,7 +1134,7 @@ afdo_indirect_call (gimple_stmt_iterator *gsi, const icall_target_map &map) gimple stmt = gsi_stmt (*gsi); tree callee; - if (map.size() == 0 || gimple_code (stmt) != GIMPLE_CALL + if (map.size () == 0 || gimple_code (stmt) != GIMPLE_CALL || gimple_call_fndecl (stmt) != NULL_TREE) return; @@ -1027,24 +1143,24 @@ afdo_indirect_call (gimple_stmt_iterator *gsi, const icall_target_map &map) histogram_value hist = gimple_alloc_histogram_value ( cfun, HIST_TYPE_INDIR_CALL_TOPN, stmt, callee); hist->n_counters = (GCOV_ICALL_TOPN_VAL << 2) + 1; - hist->hvalue.counters = XNEWVEC (gcov_type, hist->n_counters); + hist->hvalue.counters = XNEWVEC (gcov_type, hist->n_counters); gimple_add_histogram_value (cfun, stmt, hist); gcov_type total = 0; - icall_target_map::const_iterator max_iter1 = map.end(); - icall_target_map::const_iterator max_iter2 = map.end(); + icall_target_map::const_iterator max_iter1 = map.end (); + icall_target_map::const_iterator max_iter2 = map.end (); - for (icall_target_map::const_iterator iter = map.begin(); - iter != map.end(); ++iter) + for (icall_target_map::const_iterator iter = map.begin (); + iter != map.end (); ++iter) { total += iter->second; - if (max_iter1 == map.end() || max_iter1->second < iter->second) - { - max_iter2 = max_iter1; - max_iter1 = iter; - } - else if (max_iter2 == map.end() || max_iter2->second < iter->second) - max_iter2 = iter; + if (max_iter1 == map.end () || max_iter1->second < iter->second) + { + max_iter2 = max_iter1; + max_iter1 = iter; + } + else if (max_iter2 == map.end () || max_iter2->second < iter->second) + max_iter2 = iter; } hist->hvalue.counters[0] = total; @@ -1054,7 +1170,7 @@ afdo_indirect_call (gimple_stmt_iterator *gsi, const icall_target_map &map) if (max_iter2 != map.end()) { hist->hvalue.counters[3] = (unsigned long long) - afdo_string_table->get_name (max_iter2->first); + afdo_string_table->get_name (max_iter2->first); hist->hvalue.counters[4] = max_iter2->second; } else @@ -1073,12 +1189,39 @@ afdo_vpt (gimple_stmt_iterator *gsi, const icall_target_map &map) afdo_indirect_call (gsi, map); } -/* For a given BB, return its execution count. Add the location of annotated - stmt to ANNOTATED. Attach value profile if a stmt is not in PROMOTED, - because we only want to promot an indirect call once. */ +typedef std::set bb_set; +typedef std::set edge_set; + +static bool +is_bb_annotated (const basic_block bb, const bb_set &annotated) +{ + return annotated.find (bb) != annotated.end (); +} + +static void +set_bb_annotated (basic_block bb, bb_set *annotated) +{ + annotated->insert (bb); +} -static gcov_type -afdo_get_bb_count (basic_block bb, const stmt_set &promoted) +static bool +is_edge_annotated (const edge e, const edge_set &annotated) +{ + return annotated.find (e) != annotated.end (); +} + +static void +set_edge_annotated (edge e, edge_set *annotated) +{ + annotated->insert (e); +} + +/* For a given BB, set its execution count. Attach value profile if a stmt + is not in PROMOTED, because we only want to promot an indirect call once. + Return TRUE if BB is annotated. */ + +static bool +afdo_set_bb_count (basic_block bb, const stmt_set &promoted) { gimple_stmt_iterator gsi; edge e; @@ -1090,22 +1233,23 @@ afdo_get_bb_count (basic_block bb, const stmt_set &promoted) { count_info info; gimple stmt = gsi_stmt (gsi); - if (stmt->code == GIMPLE_DEBUG) - continue; + if (gimple_clobber_p (stmt) || is_gimple_debug (stmt)) + continue; if (afdo_source_profile->get_count_info (stmt, &info)) - { - if (info.annotated) - continue; - if (info.count > max_count) - max_count = info.count; - has_annotated = true; - if (info.targets.size() > 0 && promoted.find (stmt) == promoted.end ()) - afdo_vpt (&gsi, info.targets); - } + { + if (info.annotated) + continue; + if (info.count > max_count) + max_count = info.count; + has_annotated = true; + if (info.targets.size () > 0 + && promoted.find (stmt) == promoted.end ()) + afdo_vpt (&gsi, info.targets); + } } if (!has_annotated) - return 0; + return false; for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) afdo_source_profile->mark_annotated (gimple_location (gsi_stmt (gsi))); @@ -1114,13 +1258,13 @@ afdo_get_bb_count (basic_block bb, const stmt_set &promoted) gimple phi = gsi_stmt (gsi); size_t i; for (i = 0; i < gimple_phi_num_args (phi); i++) - afdo_source_profile->mark_annotated (gimple_phi_arg_location (phi, i)); + afdo_source_profile->mark_annotated (gimple_phi_arg_location (phi, i)); } FOR_EACH_EDGE (e, ei, bb->succs) afdo_source_profile->mark_annotated (e->goto_locus); - bb->flags |= BB_ANNOTATED; - return max_count; + bb->count = max_count; + return true; } /* BB1 and BB2 are in an equivalent class iff: @@ -1129,104 +1273,104 @@ afdo_get_bb_count (basic_block bb, const stmt_set &promoted) 3. BB1 and BB2 are in the same loop nest. This function finds the equivalent class for each basic block, and stores a pointer to the first BB in its equivalent class. Meanwhile, - set bb counts for the same equivalent class to be idenical. */ + set bb counts for the same equivalent class to be idenical. Update + ANNOTATED_BB for the first BB in its equivalent class. */ static void -afdo_find_equiv_class (void) +afdo_find_equiv_class (bb_set *annotated_bb) { basic_block bb; FOR_ALL_BB_FN (bb, cfun) - bb->aux = NULL; + bb->aux = NULL; FOR_ALL_BB_FN (bb, cfun) - { - vec dom_bbs; - basic_block bb1; - int i; - - if (bb->aux != NULL) - continue; - bb->aux = bb; - dom_bbs = get_all_dominated_blocks (CDI_DOMINATORS, bb); - FOR_EACH_VEC_ELT (dom_bbs, i, bb1) - if (bb1->aux == NULL - && dominated_by_p (CDI_POST_DOMINATORS, bb, bb1) - && bb1->loop_father == bb->loop_father) - { - bb1->aux = bb; - if (bb1->count > bb->count && (bb1->flags & BB_ANNOTATED) != 0) - { - bb->count = MAX (bb->count, bb1->count); - bb->flags |= BB_ANNOTATED; - } - } - dom_bbs = get_all_dominated_blocks (CDI_POST_DOMINATORS, bb); - FOR_EACH_VEC_ELT (dom_bbs, i, bb1) - if (bb1->aux == NULL - && dominated_by_p (CDI_DOMINATORS, bb, bb1) - && bb1->loop_father == bb->loop_father) - { - bb1->aux = bb; - if (bb1->count > bb->count && (bb1->flags & BB_ANNOTATED) != 0) - { - bb->count = MAX (bb->count, bb1->count); - bb->flags |= BB_ANNOTATED; - } - } - } + { + vec dom_bbs; + basic_block bb1; + int i; + + if (bb->aux != NULL) + continue; + bb->aux = bb; + dom_bbs = get_all_dominated_blocks (CDI_DOMINATORS, bb); + FOR_EACH_VEC_ELT (dom_bbs, i, bb1) + if (bb1->aux == NULL && dominated_by_p (CDI_POST_DOMINATORS, bb, bb1) + && bb1->loop_father == bb->loop_father) + { + bb1->aux = bb; + if (bb1->count > bb->count && is_bb_annotated (bb1, *annotated_bb)) + { + bb->count = MAX (bb->count, bb1->count); + set_bb_annotated (bb, annotated_bb); + } + } + dom_bbs = get_all_dominated_blocks (CDI_POST_DOMINATORS, bb); + FOR_EACH_VEC_ELT (dom_bbs, i, bb1) + if (bb1->aux == NULL && dominated_by_p (CDI_DOMINATORS, bb, bb1) + && bb1->loop_father == bb->loop_father) + { + bb1->aux = bb; + if (bb1->count > bb->count && is_bb_annotated (bb1, *annotated_bb)) + { + bb->count = MAX (bb->count, bb1->count); + set_bb_annotated (bb, annotated_bb); + } + } + } } /* If a basic block's count is known, and only one of its in/out edges' count - is unknown, its count can be calculated. - Meanwhile, if all of the in/out edges' counts are known, then the basic - block's unknown count can also be calculated. + is unknown, its count can be calculated. Meanwhile, if all of the in/out + edges' counts are known, then the basic block's unknown count can also be + calculated. IS_SUCC is true if out edges of a basic blocks are examined. + Update ANNOTATED_BB and ANNOTATED_EDGE accordingly. Return TRUE if any basic block/edge count is changed. */ static bool -afdo_propagate_edge (bool is_succ) +afdo_propagate_edge (bool is_succ, bb_set *annotated_bb, + edge_set *annotated_edge) { basic_block bb; bool changed = false; FOR_EACH_BB_FN (bb, cfun) - { - edge e, unknown_edge = NULL; - edge_iterator ei; - int num_unknown_edge = 0; - gcov_type total_known_count = 0; - - FOR_EACH_EDGE (e, ei, is_succ ? bb->succs : bb->preds) - if ((e->flags & EDGE_ANNOTATED) == 0) - num_unknown_edge ++, unknown_edge = e; - else - total_known_count += e->count; - - if (num_unknown_edge == 0) - { - if (total_known_count > bb->count) - { - bb->count = total_known_count; - changed = true; - } - if ((bb->flags & BB_ANNOTATED) == 0) - { - bb->flags |= BB_ANNOTATED; - changed = true; - } - } - else if (num_unknown_edge == 1 - && (bb->flags & BB_ANNOTATED) != 0) - { - if (bb->count >= total_known_count) - unknown_edge->count = bb->count - total_known_count; - else - unknown_edge->count = 0; - unknown_edge->flags |= EDGE_ANNOTATED; - changed = true; - } - } + { + edge e, unknown_edge = NULL; + edge_iterator ei; + int num_unknown_edge = 0; + gcov_type total_known_count = 0; + + FOR_EACH_EDGE (e, ei, is_succ ? bb->succs : bb->preds) + if (!is_edge_annotated (e, *annotated_edge)) + num_unknown_edge++, unknown_edge = e; + else + total_known_count += e->count; + + if (num_unknown_edge == 0) + { + if (total_known_count > bb->count) + { + bb->count = total_known_count; + changed = true; + } + if (!is_bb_annotated (bb, *annotated_bb)) + { + set_bb_annotated (bb, annotated_bb); + changed = true; + } + } + else if (num_unknown_edge == 1 && is_bb_annotated (bb, *annotated_bb)) + { + if (bb->count >= total_known_count) + unknown_edge->count = bb->count - total_known_count; + else + unknown_edge->count = 0; + set_edge_annotated (unknown_edge, annotated_edge); + changed = true; + } + } return changed; } @@ -1260,95 +1404,103 @@ afdo_propagate_edge (bool is_succ) goto BB3 In this case, we need to propagate through PHI to determine the edge - count of BB1->BB.t1, BB.t1->BB.t2. */ + count of BB1->BB.t1, BB.t1->BB.t2. + Update ANNOTATED_EDGE accordingly. */ static void -afdo_propagate_circuit (void) +afdo_propagate_circuit (const bb_set &annotated_bb, edge_set *annotated_edge) { basic_block bb; FOR_ALL_BB_FN (bb, cfun) + { + gimple phi_stmt; + tree cmp_rhs, cmp_lhs; + gimple cmp_stmt = last_stmt (bb); + edge e; + edge_iterator ei; + + if (!cmp_stmt || gimple_code (cmp_stmt) != GIMPLE_COND) + continue; + cmp_rhs = gimple_cond_rhs (cmp_stmt); + cmp_lhs = gimple_cond_lhs (cmp_stmt); + if (!TREE_CONSTANT (cmp_rhs) + || !(integer_zerop (cmp_rhs) || integer_onep (cmp_rhs))) + continue; + if (TREE_CODE (cmp_lhs) != SSA_NAME) + continue; + if (!is_bb_annotated (bb, annotated_bb)) + continue; + phi_stmt = SSA_NAME_DEF_STMT (cmp_lhs); + while (phi_stmt && gimple_code (phi_stmt) == GIMPLE_ASSIGN + && gimple_assign_single_p (phi_stmt) + && TREE_CODE (gimple_assign_rhs1 (phi_stmt)) == SSA_NAME) + phi_stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (phi_stmt)); + if (!phi_stmt || gimple_code (phi_stmt) != GIMPLE_PHI) + continue; + FOR_EACH_EDGE (e, ei, bb->succs) { - gimple phi_stmt; - tree cmp_rhs, cmp_lhs; - gimple cmp_stmt = last_stmt (bb); - edge e; - edge_iterator ei; - - if (!cmp_stmt || gimple_code (cmp_stmt) != GIMPLE_COND) - continue; - cmp_rhs = gimple_cond_rhs (cmp_stmt); - cmp_lhs = gimple_cond_lhs (cmp_stmt); - if (!TREE_CONSTANT (cmp_rhs) - || !(integer_zerop (cmp_rhs) || integer_onep (cmp_rhs))) - continue; - if (TREE_CODE (cmp_lhs) != SSA_NAME) - continue; - if ((bb->flags & BB_ANNOTATED) == 0) - continue; - phi_stmt = SSA_NAME_DEF_STMT (cmp_lhs); - while (phi_stmt && gimple_code (phi_stmt) == GIMPLE_ASSIGN - && gimple_assign_single_p (phi_stmt) - && TREE_CODE (gimple_assign_rhs1 (phi_stmt)) == SSA_NAME) - phi_stmt = SSA_NAME_DEF_STMT (gimple_assign_rhs1 (phi_stmt)); - if (!phi_stmt || gimple_code (phi_stmt) != GIMPLE_PHI) - continue; - FOR_EACH_EDGE (e, ei, bb->succs) - { - unsigned i, total = 0; - edge only_one; - bool check_value_one = (((integer_onep (cmp_rhs)) - ^ (gimple_cond_code (cmp_stmt) == EQ_EXPR)) - ^ ((e->flags & EDGE_TRUE_VALUE) != 0)); - if ((e->flags & EDGE_ANNOTATED) == 0) - continue; - for (i = 0; i < gimple_phi_num_args (phi_stmt); i++) - { - tree val = gimple_phi_arg_def (phi_stmt, i); - edge ep = gimple_phi_arg_edge (phi_stmt, i); - - if (!TREE_CONSTANT (val) || !(integer_zerop (val) - || integer_onep (val))) - continue; - if (check_value_one ^ integer_onep (val)) - continue; - total++; - only_one = ep; - } - if (total == 1 && (only_one->flags & EDGE_ANNOTATED) == 0) - { - only_one->count = e->count; - only_one->flags |= EDGE_ANNOTATED; - } - } + unsigned i, total = 0; + edge only_one; + bool check_value_one = (((integer_onep (cmp_rhs)) + ^ (gimple_cond_code (cmp_stmt) == EQ_EXPR)) + ^ ((e->flags & EDGE_TRUE_VALUE) != 0)); + if (!is_edge_annotated (e, *annotated_edge)) + continue; + for (i = 0; i < gimple_phi_num_args (phi_stmt); i++) + { + tree val = gimple_phi_arg_def (phi_stmt, i); + edge ep = gimple_phi_arg_edge (phi_stmt, i); + + if (!TREE_CONSTANT (val) + || !(integer_zerop (val) || integer_onep (val))) + continue; + if (check_value_one ^ integer_onep (val)) + continue; + total++; + only_one = ep; + if (e->probability == 0 && !is_edge_annotated (ep, *annotated_edge)) + { + ep->probability = 0; + ep->count = 0; + set_edge_annotated (ep, annotated_edge); + } + } + if (total == 1 && !is_edge_annotated (only_one, *annotated_edge)) + { + only_one->probability = e->probability; + only_one->count = e->count; + set_edge_annotated (only_one, annotated_edge); + } } + } } /* Propagate the basic block count and edge count on the control flow graph. We do the propagation iteratively until stablize. */ static void -afdo_propagate (void) +afdo_propagate (bb_set *annotated_bb, edge_set *annotated_edge) { basic_block bb; bool changed = true; int i = 0; FOR_ALL_BB_FN (bb, cfun) - { - bb->count = ((basic_block) bb->aux)->count; - if ((((basic_block) bb->aux)->flags & BB_ANNOTATED) != 0) - bb->flags |= BB_ANNOTATED; - } + { + bb->count = ((basic_block)bb->aux)->count; + if (is_bb_annotated ((const basic_block)bb->aux, *annotated_bb)) + set_bb_annotated (bb, annotated_bb); + } while (changed && i++ < PARAM_VALUE (PARAM_AUTOFDO_MAX_PROPAGATE_ITERATIONS)) { changed = false; - if (afdo_propagate_edge (true)) - changed = true; - if (afdo_propagate_edge (false)) - changed = true; - afdo_propagate_circuit (); + if (afdo_propagate_edge (true, annotated_bb, annotated_edge)) + changed = true; + if (afdo_propagate_edge (false, annotated_bb, annotated_edge)) + changed = true; + afdo_propagate_circuit (*annotated_bb, annotated_edge); } } @@ -1379,7 +1531,7 @@ get_locus_information (location_t locus, locus_information_t* li) { inline_stack stack; get_inline_stack (locus, &stack); - if (stack.empty ()) + if (stack.is_empty ()) return false; tree function_decl = stack[0].first; @@ -1393,7 +1545,7 @@ get_locus_information (location_t locus, locus_information_t* li) { LOCATION_LINE (DECL_SOURCE_LOCATION (function_decl)); function *f = DECL_STRUCT_FUNCTION (function_decl); unsigned function_length = f? LOCATION_LINE (f->function_end_locus) - - function_lineno : 0; + function_lineno : 0; unsigned branch_offset = li->lineno - function_lineno; int discriminator = get_discriminator_from_locus (locus); @@ -1432,40 +1584,40 @@ record_branch_prediction_results (edge e, int probability) { gimple last = NULL; for (gsi = gsi_last_nondebug_bb (bb); - !gsi_end_p (gsi); - gsi_prev_nondebug (&gsi)) - { - last = gsi_stmt (gsi); + !gsi_end_p (gsi); + gsi_prev_nondebug (&gsi)) + { + last = gsi_stmt (gsi); - if (gimple_has_location (last)) - break; - } + if (gimple_has_location (last)) + break; + } struct locus_information_t li; bool annotated; if (e->flags & EDGE_PREDICTED_BY_EXPECT) - annotated = true; + annotated = true; else - annotated = false; + annotated = false; if (get_locus_information (e->goto_locus, &li)) - ; /* Intentionally do nothing. */ + ; /* Intentionally do nothing. */ else if (get_locus_information (gimple_location (last), &li)) - ; /* Intentionally do nothing. */ + ; /* Intentionally do nothing. */ else - return; /* Can't get locus information, return. */ + return; /* Can't get locus information, return. */ switch_to_section (get_section ( - ".gnu.switches.text.branch.annotation", - SECTION_DEBUG | SECTION_MERGE | - SECTION_STRINGS | (SECTION_ENTSIZE & 1), - NULL)); + ".gnu.switches.text.branch.annotation", + SECTION_DEBUG | SECTION_MERGE | + SECTION_STRINGS | (SECTION_ENTSIZE & 1), + NULL)); char buf[1024]; snprintf (buf, 1024, "%s;%u;" - HOST_WIDEST_INT_PRINT_DEC";%d;%d;%d;%s", - li.filename, li.lineno, bb->count, annotated?1:0, - probability, e->probability, li.hash); + HOST_WIDEST_INT_PRINT_DEC";%d;%d;%d;%s", + li.filename, li.lineno, bb->count, annotated?1:0, + probability, e->probability, li.hash); dw2_asm_output_nstring (buf, (size_t)-1, NULL); } } @@ -1474,14 +1626,14 @@ record_branch_prediction_results (edge e, int probability) { probabilities. */ static void -afdo_calculate_branch_prob (void) +afdo_calculate_branch_prob (bb_set *annotated_bb, edge_set *annotated_edge) { basic_block bb; bool has_sample = false; FOR_EACH_BB_FN (bb, cfun) - if (bb->count > 0) - has_sample = true; + if (bb->count > 0) + has_sample = true; if (!has_sample) return; @@ -1490,59 +1642,55 @@ afdo_calculate_branch_prob (void) calculate_dominance_info (CDI_DOMINATORS); loop_optimizer_init (0); - afdo_find_equiv_class (); - afdo_propagate (); + afdo_find_equiv_class (annotated_bb); + afdo_propagate (annotated_bb, annotated_edge); FOR_EACH_BB_FN (bb, cfun) + { + edge e; + edge_iterator ei; + int num_unknown_succ = 0; + gcov_type total_count = 0; + + FOR_EACH_EDGE (e, ei, bb->succs) { - edge e; - edge_iterator ei; - int num_unknown_succ = 0; - gcov_type total_count = 0; - - FOR_EACH_EDGE (e, ei, bb->succs) - { - if ((e->flags & EDGE_ANNOTATED) == 0) - num_unknown_succ ++; - else - total_count += e->count; - } - if (num_unknown_succ == 0 && total_count > 0) - { - bool first_edge = true; - - FOR_EACH_EDGE (e, ei, bb->succs) - { - double probability = - (double) e->count * REG_BR_PROB_BASE / total_count; - - if (first_edge && flag_check_branch_annotation) - { - record_branch_prediction_results ( - e, static_cast (probability + 0.5)); - first_edge = false; - } - - e->probability = probability; - } - } + if (!is_edge_annotated (e, *annotated_edge)) + num_unknown_succ++; + else + total_count += e->count; + } + if (num_unknown_succ == 0 && total_count > 0) + { + bool first_edge = true; + + FOR_EACH_EDGE (e, ei, bb->succs) + { + int probability = (double) e->count * REG_BR_PROB_BASE / total_count; + + if (first_edge && flag_check_branch_annotation) + { + record_branch_prediction_results (e, probability); + first_edge = false; + } + e->probability = probability; + } } + } FOR_ALL_BB_FN (bb, cfun) + { + edge e; + edge_iterator ei; + + FOR_EACH_EDGE (e, ei, bb->succs) { - edge e; - edge_iterator ei; - - FOR_EACH_EDGE (e, ei, bb->succs) - { - e->count = - (double) bb->count * e->probability / REG_BR_PROB_BASE; - if (flag_check_branch_annotation) - { - e->flags &= ~EDGE_PREDICTED_BY_EXPECT; - } - } - bb->aux = NULL; + e->count = (double)bb->count * e->probability / REG_BR_PROB_BASE; + if (flag_check_branch_annotation) + { + e->flags &= ~EDGE_PREDICTED_BY_EXPECT; + } } + bb->aux = NULL; + } loop_optimizer_finalize (); free_dominance_info (CDI_DOMINATORS); @@ -1558,49 +1706,48 @@ afdo_vpt_for_early_inline (stmt_set *promoted_stmts) { basic_block bb; if (afdo_source_profile->get_function_instance_by_decl ( - current_function_decl) == NULL) + current_function_decl) == NULL) return false; bool has_vpt = false; FOR_EACH_BB_FN (bb, cfun) - { - if (!has_indirect_call (bb)) - continue; - gimple_stmt_iterator gsi; + { + if (!has_indirect_call (bb)) + continue; + gimple_stmt_iterator gsi; - gcov_type bb_count = 0; - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - count_info info; - gimple stmt = gsi_stmt (gsi); - if (afdo_source_profile->get_count_info (stmt, &info)) - bb_count = MAX (bb_count, info.count); - } - - for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) - { - gimple stmt = gsi_stmt (gsi); - /* IC_promotion and early_inline_2 is done in multiple iterations. - No need to promoted the stmt if its in promoted_stmts (means - it is already been promoted in the previous iterations). */ - if (gimple_code (stmt) != GIMPLE_CALL - || (gimple_call_fn (stmt) != NULL - && TREE_CODE (gimple_call_fn (stmt)) == FUNCTION_DECL) - || promoted_stmts->find (stmt) != promoted_stmts->end ()) - continue; - - count_info info; - afdo_source_profile->get_count_info (stmt, &info); - info.count = bb_count; - if (afdo_source_profile->update_inlined_ind_target (stmt, &info)) - { - /* Promote the indirect call and update the promoted_stmts. */ - promoted_stmts->insert (stmt); - afdo_vpt (&gsi, info.targets); - has_vpt = true; - } - } - } + gcov_type bb_count = 0; + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + count_info info; + gimple stmt = gsi_stmt (gsi); + if (afdo_source_profile->get_count_info (stmt, &info)) + bb_count = MAX (bb_count, info.count); + } + + for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi)) + { + gimple stmt = gsi_stmt (gsi); + /* IC_promotion and early_inline_2 is done in multiple iterations. + No need to promoted the stmt if its in promoted_stmts (means + it is already been promoted in the previous iterations). */ + if (gimple_code (stmt) != GIMPLE_CALL || gimple_call_fn (stmt) == NULL + || TREE_CODE (gimple_call_fn (stmt)) == FUNCTION_DECL + || promoted_stmts->find (stmt) != promoted_stmts->end ()) + continue; + + count_info info; + afdo_source_profile->get_count_info (stmt, &info); + info.count = bb_count; + if (afdo_source_profile->update_inlined_ind_target (stmt, &info)) + { + /* Promote the indirect call and update the promoted_stmts. */ + promoted_stmts->insert (stmt); + afdo_vpt (&gsi, info.targets); + has_vpt = true; + } + } + } if (has_vpt && gimple_value_profile_transformations ()) { free_dominance_info (CDI_DOMINATORS); @@ -1622,9 +1769,11 @@ static void afdo_annotate_cfg (const stmt_set &promoted_stmts) { basic_block bb; - const function_instance *s = - afdo_source_profile->get_function_instance_by_decl ( - current_function_decl); + bb_set annotated_bb; + edge_set annotated_edge; + const function_instance *s + = afdo_source_profile->get_function_instance_by_decl ( + current_function_decl); if (s == NULL) return; @@ -1633,35 +1782,32 @@ afdo_annotate_cfg (const stmt_set &promoted_stmts) gcov_type max_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; FOR_EACH_BB_FN (bb, cfun) + { + edge e; + edge_iterator ei; + + bb->count = 0; + FOR_EACH_EDGE (e, ei, bb->succs) + e->count = 0; + + if (afdo_set_bb_count (bb, promoted_stmts)) + set_bb_annotated (bb, &annotated_bb); + if (bb->count > max_count) + max_count = bb->count; + } + if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count + > ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->count) { - edge e; - edge_iterator ei; - - bb->count = 0; - bb->flags &= (~BB_ANNOTATED); - FOR_EACH_EDGE (e, ei, bb->succs) - { - e->count = 0; - e->flags &= (~EDGE_ANNOTATED); - } - - bb->count = afdo_get_bb_count (bb, promoted_stmts); - if (bb->count > max_count) - max_count = bb->count; - } - if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count > - ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->count) - { - ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->count = - ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; - ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->flags |= BB_ANNOTATED; + ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->count + = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; + set_bb_annotated (ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb, &annotated_bb); } - if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count > - EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb->count) + if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count + > EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb->count) { - EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb->count = - ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; - EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb->flags |= BB_ANNOTATED; + EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb->count + = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count; + set_bb_annotated (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb, &annotated_bb); } afdo_source_profile->mark_annotated ( DECL_SOURCE_LOCATION (current_function_decl)); @@ -1669,9 +1815,9 @@ afdo_annotate_cfg (const stmt_set &promoted_stmts) afdo_source_profile->mark_annotated (cfun->function_end_locus); if (max_count > 0) { - profile_status_for_fn (cfun) = PROFILE_READ; - afdo_calculate_branch_prob (); + afdo_calculate_branch_prob (&annotated_bb, &annotated_edge); counts_to_freqs (); + profile_status_for_fn (cfun) = PROFILE_READ; } if (flag_value_profile_transformations) { @@ -1686,7 +1832,8 @@ afdo_annotate_cfg (const stmt_set &promoted_stmts) /* Wrapper function to invoke early inliner. */ -static void early_inline () +static void +early_inline () { compute_inline_parameters (cgraph_get_node (current_function_decl), true); unsigned todo = early_inliner (); @@ -1708,77 +1855,78 @@ auto_profile (void) if (!flag_auto_profile) return 0; - profile_info = autofdo::afdo_profile_info; if (L_IPO_COMP_MODE) lipo_link_and_fixup (); init_node_map (true); + profile_info = autofdo::afdo_profile_info; FOR_EACH_FUNCTION (node) - { - if (!gimple_has_body_p (node->decl)) - continue; - - /* Don't profile functions produced for builtin stuff. */ - if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) - continue; - - push_cfun (DECL_STRUCT_FUNCTION (node->decl)); - - /* First do indirect call promotion and early inline to make the - IR match the profiled binary before actual annotation. - - This is needed because an indirect call might have been promoted - and inlined in the profiled binary. If we do not promote and - inline these indirect calls before annotation, the profile for - these promoted functions will be lost. - - e.g. foo() --indirect_call--> bar() - In profiled binary, the callsite is promoted and inlined, making - the profile look like: - - foo: { - loc_foo_1: count_1 - bar@loc_foo_2: { - loc_bar_1: count_2 - loc_bar_2: count_3 - } - } - - Before AutoFDO pass, loc_foo_2 is not promoted thus not inlined. - If we perform annotation on it, the profile inside bar@loc_foo2 - will be wasted. - - To avoid this, we promote loc_foo_2 and inline the promoted bar - function before annotation, so the profile inside bar@loc_foo2 - will be useful. */ - autofdo::stmt_set promoted_stmts; - for (int i = 0; i < PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS); i++) - { - if (!flag_value_profile_transformations - || !autofdo::afdo_vpt_for_early_inline (&promoted_stmts)) - break; - early_inline (); - } - - early_inline (); - autofdo::afdo_annotate_cfg (promoted_stmts); - compute_function_frequency (); - - /* Local pure-const may imply need to fixup the cfg. */ - if (execute_fixup_cfg () & TODO_cleanup_cfg) - cleanup_tree_cfg (); + { + if (!gimple_has_body_p (node->decl)) + continue; + + /* Don't profile functions produced for builtin stuff. */ + if (DECL_SOURCE_LOCATION (node->decl) == BUILTINS_LOCATION) + continue; + + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + + /* First do indirect call promotion and early inline to make the + IR match the profiled binary before actual annotation. + + This is needed because an indirect call might have been promoted + and inlined in the profiled binary. If we do not promote and + inline these indirect calls before annotation, the profile for + these promoted functions will be lost. + + e.g. foo() --indirect_call--> bar() + In profiled binary, the callsite is promoted and inlined, making + the profile look like: + + foo: { + loc_foo_1: count_1 + bar@loc_foo_2: { + loc_bar_1: count_2 + loc_bar_2: count_3 + } + } + + Before AutoFDO pass, loc_foo_2 is not promoted thus not inlined. + If we perform annotation on it, the profile inside bar@loc_foo2 + will be wasted. + + To avoid this, we promote loc_foo_2 and inline the promoted bar + function before annotation, so the profile inside bar@loc_foo2 + will be useful. */ + autofdo::stmt_set promoted_stmts; + for (int i = 0; i < PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS); i++) + { + if (!flag_value_profile_transformations + || !autofdo::afdo_vpt_for_early_inline (&promoted_stmts)) + break; + early_inline (); + } - free_dominance_info (CDI_DOMINATORS); - free_dominance_info (CDI_POST_DOMINATORS); - rebuild_cgraph_edges (); - pop_cfun (); - } + early_inline (); + autofdo::afdo_annotate_cfg (promoted_stmts); + compute_function_frequency (); + + /* Local pure-const may imply need to fixup the cfg. */ + if (execute_fixup_cfg () & TODO_cleanup_cfg) + cleanup_tree_cfg (); + + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + rebuild_cgraph_edges (); + compute_inline_parameters (cgraph_get_node (current_function_decl), true); + pop_cfun (); + } if (flag_auto_profile_record_coverage_in_elf) autofdo::afdo_source_profile->write_annotated_count (); return TODO_rebuild_cgraph_edges; } -} /* namespace autofdo. */ +} /* namespace autofdo. */ /* Read the profile from the profile data file. */ @@ -1788,8 +1936,8 @@ init_auto_profile (void) if (auto_profile_file == NULL) auto_profile_file = DEFAULT_AUTO_PROFILE_FILE; - autofdo::afdo_profile_info = (struct gcov_ctr_summary *) - xcalloc (1, sizeof (struct gcov_ctr_summary)); + autofdo::afdo_profile_info = (struct gcov_ctr_summary *)xcalloc ( + 1, sizeof (struct gcov_ctr_summary)); autofdo::afdo_profile_info->runs = 1; autofdo::afdo_profile_info->sum_max = 0; autofdo::afdo_profile_info->sum_all = 0; @@ -1817,14 +1965,14 @@ end_auto_profile (void) bool afdo_callsite_hot_enough_for_early_inline (struct cgraph_edge *edge) { - gcov_type count = - autofdo::afdo_source_profile->get_callsite_total_count (edge); + gcov_type count + = autofdo::afdo_source_profile->get_callsite_total_count (edge); if (count > 0) { bool is_hot; const struct gcov_ctr_summary *saved_profile_info = profile_info; /* At earling inline stage, profile_info is not set yet. We need to - temporarily set it to afdo_profile_info to calculate hotness. */ + temporarily set it to afdo_profile_info to calculate hotness. */ profile_info = autofdo::afdo_profile_info; is_hot = maybe_hot_count_p (NULL, count); profile_info = saved_profile_info; diff --git a/gcc-4.9/gcc/c-family/ChangeLog b/gcc-4.9/gcc/c-family/ChangeLog index e3c8c8300..701d1cef7 100644 --- a/gcc-4.9/gcc/c-family/ChangeLog +++ b/gcc-4.9/gcc/c-family/ChangeLog @@ -1,3 +1,29 @@ +2015-01-20 Marek Polacek + + Backport from mainline + 2014-06-23 Marek Polacek + + PR c/61553 + * c-common.c (get_atomic_generic_size): Don't segfault if the + type doesn't have a size. + +2014-10-30 Release Manager + + * GCC 4.9.2 released. + +2014-10-10 Jakub Jelinek + + PR c/63495 + * c-common.c (min_align_of_type): Don't decrease alignment + through BIGGEST_FIELD_ALIGNMENT or ADJUST_FIELD_ALIGN if + TYPE_USER_ALIGN is set. + +2014-10-08 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement SD-6: SG10 Feature Test Recommendations + * c-cppbuiltin.c (c_cpp_builtins()): Define language feature + macros and the __has_header macro. + 2014-08-12 Igor Zamyatin PR other/61962 diff --git a/gcc-4.9/gcc/c-family/c-common.c b/gcc-4.9/gcc/c-family/c-common.c index 9923928fe..41f81221f 100644 --- a/gcc-4.9/gcc/c-family/c-common.c +++ b/gcc-4.9/gcc/c-family/c-common.c @@ -336,6 +336,7 @@ static tree handle_mode_attribute (tree *, tree, tree, int, bool *); static tree handle_section_attribute (tree *, tree, tree, int, bool *); static tree handle_aligned_attribute (tree *, tree, tree, int, bool *); static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ; +static tree handle_noplt_attribute (tree *, tree, tree, int, bool *) ; static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *); static tree handle_ifunc_attribute (tree *, tree, tree, int, bool *); static tree handle_alias_attribute (tree *, tree, tree, int, bool *); @@ -673,6 +674,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_aligned_attribute, false }, { "weak", 0, 0, true, false, false, handle_weak_attribute, false }, + { "noplt", 0, 0, true, false, false, + handle_noplt_attribute, false }, { "ifunc", 1, 1, true, false, false, handle_ifunc_attribute, false }, { "alias", 1, 1, true, false, false, @@ -4948,16 +4951,18 @@ min_align_of_type (tree type) { unsigned int align = TYPE_ALIGN (type); align = MIN (align, BIGGEST_ALIGNMENT); + if (!TYPE_USER_ALIGN (type)) + { #ifdef BIGGEST_FIELD_ALIGNMENT - align = MIN (align, BIGGEST_FIELD_ALIGNMENT); + align = MIN (align, BIGGEST_FIELD_ALIGNMENT); #endif - unsigned int field_align = align; + unsigned int field_align = align; #ifdef ADJUST_FIELD_ALIGN - tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, - type); - field_align = ADJUST_FIELD_ALIGN (field, field_align); + tree field = build_decl (UNKNOWN_LOCATION, FIELD_DECL, NULL_TREE, type); + field_align = ADJUST_FIELD_ALIGN (field, field_align); #endif - align = MIN (align, field_align); + align = MIN (align, field_align); + } return align / BITS_PER_UNIT; } @@ -7666,6 +7671,25 @@ handle_weak_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle a "noplt" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_noplt_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool * ARG_UNUSED (no_add_attrs)) +{ + if (TREE_CODE (*node) != FUNCTION_DECL) + { + warning (OPT_Wattributes, + "%qE attribute is only applicable on functions", name); + *no_add_attrs = true; + return NULL_TREE; + } + return NULL_TREE; +} + /* Handle an "alias" or "ifunc" attribute; arguments as in struct attribute_spec.handler, except that IS_ALIAS tells us whether this is an alias as opposed to ifunc attribute. */ @@ -10454,7 +10478,8 @@ get_atomic_generic_size (location_t loc, tree function, function); return 0; } - size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type))); + tree type_size = TYPE_SIZE_UNIT (TREE_TYPE (type)); + size = type_size ? tree_to_uhwi (type_size) : 0; if (size != size_0) { error_at (loc, "size mismatch in argument %d of %qE", x + 1, diff --git a/gcc-4.9/gcc/c-family/c-cppbuiltin.c b/gcc-4.9/gcc/c-family/c-cppbuiltin.c index 6a697f666..930ee1a0f 100644 --- a/gcc-4.9/gcc/c-family/c-cppbuiltin.c +++ b/gcc-4.9/gcc/c-family/c-cppbuiltin.c @@ -794,18 +794,66 @@ c_cpp_builtins (cpp_reader *pfile) /* For stddef.h. They require macros defined in c-common.c. */ c_stddef_cpp_builtins (); + /* Set include test macros for all C/C++ (not for just C++11 etc.) + the builtins __has_include__ and __has_include_next__ are defined + in libcpp. */ + cpp_define (pfile, "__has_include(STR)=__has_include__(STR)"); + cpp_define (pfile, "__has_include_next(STR)=__has_include_next__(STR)"); + if (c_dialect_cxx ()) { if (flag_weak && SUPPORTS_ONE_ONLY) cpp_define (pfile, "__GXX_WEAK__=1"); else cpp_define (pfile, "__GXX_WEAK__=0"); + if (warn_deprecated) cpp_define (pfile, "__DEPRECATED"); + if (flag_rtti) cpp_define (pfile, "__GXX_RTTI"); + if (cxx_dialect >= cxx11) cpp_define (pfile, "__GXX_EXPERIMENTAL_CXX0X__"); + + /* Binary literals have been allowed in g++ before C++11 + and were standardized for C++14. */ + if (!pedantic || cxx_dialect > cxx11) + cpp_define (pfile, "__cpp_binary_literals=201304"); + if (cxx_dialect >= cxx11) + { + /* Set feature test macros for C++11 */ + cpp_define (pfile, "__cpp_unicode_characters=200704"); + cpp_define (pfile, "__cpp_raw_strings=200710"); + cpp_define (pfile, "__cpp_unicode_literals=200710"); + cpp_define (pfile, "__cpp_user_defined_literals=200809"); + cpp_define (pfile, "__cpp_lambdas=200907"); + cpp_define (pfile, "__cpp_constexpr=200704"); + cpp_define (pfile, "__cpp_static_assert=200410"); + cpp_define (pfile, "__cpp_decltype=200707"); + cpp_define (pfile, "__cpp_attributes=200809"); + cpp_define (pfile, "__cpp_rvalue_reference=200610"); + cpp_define (pfile, "__cpp_variadic_templates=200704"); + cpp_define (pfile, "__cpp_alias_templates=200704"); + } + if (cxx_dialect > cxx11) + { + /* Set feature test macros for C++14 */ + cpp_define (pfile, "__cpp_return_type_deduction=201304"); + cpp_define (pfile, "__cpp_init_captures=201304"); + cpp_define (pfile, "__cpp_generic_lambdas=201304"); + //cpp_undef (pfile, "__cpp_constexpr"); + //cpp_define (pfile, "__cpp_constexpr=201304"); + cpp_define (pfile, "__cpp_decltype_auto=201304"); + //cpp_define (pfile, "__cpp_aggregate_nsdmi=201304"); + //cpp_define (pfile, "__cpp_variable_templates=201304"); + cpp_define (pfile, "__cpp_digit_separators=201309"); + cpp_define (pfile, "__cpp_attribute_deprecated=201309"); + //cpp_define (pfile, "__cpp_sized_deallocation=201309"); + /* We'll have to see where runtime arrays wind up. + Let's put it in C++14 for now. */ + cpp_define (pfile, "__cpp_runtime_arrays=201304"); + } } /* Note that we define this for C as well, so that we know if __attribute__((cleanup)) will interface with EH. */ diff --git a/gcc-4.9/gcc/c-family/c-ubsan.c b/gcc-4.9/gcc/c-family/c-ubsan.c index e89ebc187..2c0d009a2 100644 --- a/gcc-4.9/gcc/c-family/c-ubsan.c +++ b/gcc-4.9/gcc/c-family/c-ubsan.c @@ -98,19 +98,19 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, tree op1_utype = unsigned_type_for (type1); HOST_WIDE_INT op0_prec = TYPE_PRECISION (type0); tree uprecm1 = build_int_cst (op1_utype, op0_prec - 1); - tree precm1 = build_int_cst (type1, op0_prec - 1); t = fold_convert_loc (loc, op1_utype, op1); t = fold_build2 (GT_EXPR, boolean_type_node, t, uprecm1); /* For signed x << y, in C99/C11, the following: - (unsigned) x >> (precm1 - y) + (unsigned) x >> (uprecm1 - y) if non-zero, is undefined. */ if (code == LSHIFT_EXPR && !TYPE_UNSIGNED (type0) && flag_isoc99) { - tree x = fold_build2 (MINUS_EXPR, integer_type_node, precm1, op1); + tree x = fold_build2 (MINUS_EXPR, unsigned_type_node, uprecm1, + fold_convert (op1_utype, op1)); tt = fold_convert_loc (loc, unsigned_type_for (type0), op0); tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x); tt = fold_build2 (NE_EXPR, boolean_type_node, tt, @@ -118,13 +118,14 @@ ubsan_instrument_shift (location_t loc, enum tree_code code, } /* For signed x << y, in C++11/C++14, the following: - x < 0 || ((unsigned) x >> (precm1 - y)) + x < 0 || ((unsigned) x >> (uprecm1 - y)) if > 1, is undefined. */ if (code == LSHIFT_EXPR && !TYPE_UNSIGNED (TREE_TYPE (op0)) && (cxx_dialect == cxx11 || cxx_dialect == cxx1y)) { - tree x = fold_build2 (MINUS_EXPR, integer_type_node, precm1, op1); + tree x = fold_build2 (MINUS_EXPR, unsigned_type_node, uprecm1, + fold_convert (op1_utype, op1)); tt = fold_convert_loc (loc, unsigned_type_for (type0), op0); tt = fold_build2 (RSHIFT_EXPR, TREE_TYPE (tt), tt, x); tt = fold_build2 (GT_EXPR, boolean_type_node, tt, diff --git a/gcc-4.9/gcc/c/ChangeLog b/gcc-4.9/gcc/c/ChangeLog index 6fb49c62c..deb70eb72 100644 --- a/gcc-4.9/gcc/c/ChangeLog +++ b/gcc-4.9/gcc/c/ChangeLog @@ -1,3 +1,22 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + +2014-09-25 Thomas Schwinge + + PR c++/63249 + * c-parser.c (c_parser_omp_variable_list): Call mark_exp_read + on low_bound and length. + +2014-09-03 Marek Polacek + + PR c/62294 + * c-typeck.c (convert_arguments): Get location of a parameter. Change + error and warning calls to error_at and warning_at. Pass location of + a parameter to it. + (convert_for_assignment): Add parameter to WARN_FOR_ASSIGNMENT and + WARN_FOR_QUALIFIERS. Pass expr_loc to those. + 2014-08-22 Igor Zamyatin PR other/62008 diff --git a/gcc-4.9/gcc/c/c-parser.c b/gcc-4.9/gcc/c/c-parser.c index 6ce277c9b..264c17026 100644 --- a/gcc-4.9/gcc/c/c-parser.c +++ b/gcc-4.9/gcc/c/c-parser.c @@ -9764,7 +9764,10 @@ c_parser_omp_variable_list (c_parser *parser, c_parser_consume_token (parser); if (!c_parser_next_token_is (parser, CPP_COLON)) - low_bound = c_parser_expression (parser).value; + { + low_bound = c_parser_expression (parser).value; + mark_exp_read (low_bound); + } if (c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) length = integer_one_node; else @@ -9777,7 +9780,10 @@ c_parser_omp_variable_list (c_parser *parser, break; } if (!c_parser_next_token_is (parser, CPP_CLOSE_SQUARE)) - length = c_parser_expression (parser).value; + { + length = c_parser_expression (parser).value; + mark_exp_read (length); + } } /* Look for the closing `]'. */ if (!c_parser_require (parser, CPP_CLOSE_SQUARE, diff --git a/gcc-4.9/gcc/c/c-typeck.c b/gcc-4.9/gcc/c/c-typeck.c index 5838d6a72..d096ad405 100644 --- a/gcc-4.9/gcc/c/c-typeck.c +++ b/gcc-4.9/gcc/c/c-typeck.c @@ -3071,6 +3071,12 @@ convert_arguments (location_t loc, vec arg_loc, tree typelist, bool excess_precision = false; bool npc; tree parmval; + /* Some __atomic_* builtins have additional hidden argument at + position 0. */ + location_t ploc + = !arg_loc.is_empty () && values->length () == arg_loc.length () + ? expansion_point_location_if_in_system_header (arg_loc[parmnum]) + : input_location; if (type == void_type_node) { @@ -3113,7 +3119,8 @@ convert_arguments (location_t loc, vec arg_loc, tree typelist, if (type == error_mark_node || !COMPLETE_TYPE_P (type)) { - error ("type of formal parameter %d is incomplete", parmnum + 1); + error_at (ploc, "type of formal parameter %d is incomplete", + parmnum + 1); parmval = val; } else @@ -3128,34 +3135,34 @@ convert_arguments (location_t loc, vec arg_loc, tree typelist, if (INTEGRAL_TYPE_P (type) && TREE_CODE (valtype) == REAL_TYPE) - warning (0, "passing argument %d of %qE as integer " - "rather than floating due to prototype", - argnum, rname); + warning_at (ploc, 0, "passing argument %d of %qE as " + "integer rather than floating due to " + "prototype", argnum, rname); if (INTEGRAL_TYPE_P (type) && TREE_CODE (valtype) == COMPLEX_TYPE) - warning (0, "passing argument %d of %qE as integer " - "rather than complex due to prototype", - argnum, rname); + warning_at (ploc, 0, "passing argument %d of %qE as " + "integer rather than complex due to " + "prototype", argnum, rname); else if (TREE_CODE (type) == COMPLEX_TYPE && TREE_CODE (valtype) == REAL_TYPE) - warning (0, "passing argument %d of %qE as complex " - "rather than floating due to prototype", - argnum, rname); + warning_at (ploc, 0, "passing argument %d of %qE as " + "complex rather than floating due to " + "prototype", argnum, rname); else if (TREE_CODE (type) == REAL_TYPE && INTEGRAL_TYPE_P (valtype)) - warning (0, "passing argument %d of %qE as floating " - "rather than integer due to prototype", - argnum, rname); + warning_at (ploc, 0, "passing argument %d of %qE as " + "floating rather than integer due to " + "prototype", argnum, rname); else if (TREE_CODE (type) == COMPLEX_TYPE && INTEGRAL_TYPE_P (valtype)) - warning (0, "passing argument %d of %qE as complex " - "rather than integer due to prototype", - argnum, rname); + warning_at (ploc, 0, "passing argument %d of %qE as " + "complex rather than integer due to " + "prototype", argnum, rname); else if (TREE_CODE (type) == REAL_TYPE && TREE_CODE (valtype) == COMPLEX_TYPE) - warning (0, "passing argument %d of %qE as floating " - "rather than complex due to prototype", - argnum, rname); + warning_at (ploc, 0, "passing argument %d of %qE as " + "floating rather than complex due to " + "prototype", argnum, rname); /* ??? At some point, messages should be written about conversions between complex types, but that's too messy to do now. */ @@ -3166,9 +3173,10 @@ convert_arguments (location_t loc, vec arg_loc, tree typelist, since without a prototype it would be `double'. */ if (formal_prec == TYPE_PRECISION (float_type_node) && type != dfloat32_type_node) - warning (0, "passing argument %d of %qE as % " - "rather than % due to prototype", - argnum, rname); + warning_at (ploc, 0, + "passing argument %d of %qE as % " + "rather than % due to prototype", + argnum, rname); /* Warn if mismatch between argument and prototype for decimal float types. Warn of conversions with @@ -3191,9 +3199,10 @@ convert_arguments (location_t loc, vec arg_loc, tree typelist, || (type == dfloat64_type_node && (valtype != dfloat32_type_node)))) - warning (0, "passing argument %d of %qE as %qT " - "rather than %qT due to prototype", - argnum, rname, type, valtype); + warning_at (ploc, 0, + "passing argument %d of %qE as %qT " + "rather than %qT due to prototype", + argnum, rname, type, valtype); } /* Detect integer changing in width or signedness. @@ -3212,10 +3221,10 @@ convert_arguments (location_t loc, vec arg_loc, tree typelist, and the actual arg is that enum type. */ ; else if (formal_prec != TYPE_PRECISION (type1)) - warning (OPT_Wtraditional_conversion, - "passing argument %d of %qE " - "with different width due to prototype", - argnum, rname); + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE " + "with different width due to prototype", + argnum, rname); else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1)) ; /* Don't complain if the formal parameter type @@ -3236,14 +3245,15 @@ convert_arguments (location_t loc, vec arg_loc, tree typelist, && TYPE_UNSIGNED (valtype)) ; else if (TYPE_UNSIGNED (type)) - warning (OPT_Wtraditional_conversion, - "passing argument %d of %qE " - "as unsigned due to prototype", - argnum, rname); + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE " + "as unsigned due to prototype", + argnum, rname); else - warning (OPT_Wtraditional_conversion, - "passing argument %d of %qE " - "as signed due to prototype", argnum, rname); + warning_at (ploc, OPT_Wtraditional_conversion, + "passing argument %d of %qE " + "as signed due to prototype", + argnum, rname); } } @@ -3252,13 +3262,7 @@ convert_arguments (location_t loc, vec arg_loc, tree typelist, if (excess_precision) val = build1 (EXCESS_PRECISION_EXPR, valtype, val); origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum]; - bool arg_loc_ok = !arg_loc.is_empty () - /* Some __atomic_* builtins have additional - hidden argument at position 0. */ - && values->length () == arg_loc.length (); - parmval = convert_for_assignment (loc, - arg_loc_ok ? arg_loc[parmnum] - : UNKNOWN_LOCATION, type, + parmval = convert_for_assignment (loc, ploc, type, val, origtype, ic_argpass, npc, fundecl, function, parmnum + 1); @@ -3282,10 +3286,10 @@ convert_arguments (location_t loc, vec arg_loc, tree typelist, { /* Convert `float' to `double'. */ if (warn_double_promotion && !c_inhibit_evaluation_warnings) - warning_at (arg_loc[parmnum], OPT_Wdouble_promotion, - "implicit conversion from %qT to %qT when passing " - "argument to function", - valtype, double_type_node); + warning_at (ploc, OPT_Wdouble_promotion, + "implicit conversion from %qT to %qT when passing " + "argument to function", + valtype, double_type_node); parmval = convert (double_type_node, val); } } @@ -5591,14 +5595,14 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, /* This macro is used to emit diagnostics to ensure that all format strings are complete sentences, visible to gettext and checked at compile time. */ -#define WARN_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE) \ +#define WARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE) \ do { \ switch (errtype) \ { \ case ic_argpass: \ - if (pedwarn (LOCATION, OPT, AR, parmnum, rname)) \ + if (pedwarn (PLOC, OPT, AR, parmnum, rname)) \ inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \ - ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \ + ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \ "expected %qT but argument is of type %qT", \ type, rhstype); \ break; \ @@ -5621,22 +5625,22 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, compile time. It is the same as WARN_FOR_ASSIGNMENT but with an extra parameter to enumerate qualifiers. */ -#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS) \ +#define WARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \ do { \ switch (errtype) \ { \ case ic_argpass: \ - if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS)) \ + if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \ inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \ - ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \ + ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \ "expected %qT but argument is of type %qT", \ type, rhstype); \ break; \ case ic_assign: \ - pedwarn (LOCATION, OPT, AS, QUALS); \ + pedwarn (LOCATION, OPT, AS, QUALS); \ break; \ case ic_init: \ - pedwarn (LOCATION, OPT, IN, QUALS); \ + pedwarn (LOCATION, OPT, IN, QUALS); \ break; \ case ic_return: \ pedwarn (LOCATION, OPT, RE, QUALS); \ @@ -5688,7 +5692,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, && TREE_CODE (type) == ENUMERAL_TYPE && TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type)) { - WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat, + WARN_FOR_ASSIGNMENT (input_location, expr_loc, OPT_Wc___compat, G_("enum conversion when passing argument " "%d of %qE is invalid in C++"), G_("enum conversion in assignment is " @@ -5851,7 +5855,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, vice-versa. */ if (TYPE_QUALS_NO_ADDR_SPACE (ttl) & ~TYPE_QUALS_NO_ADDR_SPACE (ttr)) - WARN_FOR_QUALIFIERS (location, 0, + WARN_FOR_QUALIFIERS (location, expr_loc, 0, G_("passing argument %d of %qE " "makes %q#v qualified function " "pointer from unqualified"), @@ -5867,7 +5871,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, } else if (TYPE_QUALS_NO_ADDR_SPACE (ttr) & ~TYPE_QUALS_NO_ADDR_SPACE (ttl)) - WARN_FOR_QUALIFIERS (location, 0, + WARN_FOR_QUALIFIERS (location, expr_loc, 0, G_("passing argument %d of %qE discards " "%qv qualifier from pointer target type"), G_("assignment discards %qv qualifier " @@ -6029,7 +6033,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, (VOID_TYPE_P (ttr) && !null_pointer_constant && TREE_CODE (ttl) == FUNCTION_TYPE))) - WARN_FOR_ASSIGNMENT (location, OPT_Wpedantic, + WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic, G_("ISO C forbids passing argument %d of " "%qE between function pointer " "and %"), @@ -6048,7 +6052,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr) & ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl)) { - WARN_FOR_QUALIFIERS (location, 0, + WARN_FOR_QUALIFIERS (location, expr_loc, 0, G_("passing argument %d of %qE discards " "%qv qualifier from pointer target type"), G_("assignment discards %qv qualifier " @@ -6066,7 +6070,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, ; /* If there is a mismatch, do warn. */ else if (warn_pointer_sign) - WARN_FOR_ASSIGNMENT (location, OPT_Wpointer_sign, + WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign, G_("pointer targets in passing argument " "%d of %qE differ in signedness"), G_("pointer targets in assignment " @@ -6085,7 +6089,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, where an ordinary one is wanted, but not vice-versa. */ if (TYPE_QUALS_NO_ADDR_SPACE (ttl) & ~TYPE_QUALS_NO_ADDR_SPACE (ttr)) - WARN_FOR_QUALIFIERS (location, 0, + WARN_FOR_QUALIFIERS (location, expr_loc, 0, G_("passing argument %d of %qE makes " "%q#v qualified function pointer " "from unqualified"), @@ -6101,7 +6105,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, else /* Avoid warning about the volatile ObjC EH puts on decls. */ if (!objc_ok) - WARN_FOR_ASSIGNMENT (location, 0, + WARN_FOR_ASSIGNMENT (location, expr_loc, 0, G_("passing argument %d of %qE from " "incompatible pointer type"), G_("assignment from incompatible pointer type"), @@ -6124,7 +6128,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, or one that results from arithmetic, even including a cast to integer type. */ if (!null_pointer_constant) - WARN_FOR_ASSIGNMENT (location, 0, + WARN_FOR_ASSIGNMENT (location, expr_loc, 0, G_("passing argument %d of %qE makes " "pointer from integer without a cast"), G_("assignment makes pointer from integer " @@ -6138,7 +6142,7 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, } else if (codel == INTEGER_TYPE && coder == POINTER_TYPE) { - WARN_FOR_ASSIGNMENT (location, 0, + WARN_FOR_ASSIGNMENT (location, expr_loc, 0, G_("passing argument %d of %qE makes integer " "from pointer without a cast"), G_("assignment makes integer from pointer " diff --git a/gcc-4.9/gcc/calls.c b/gcc-4.9/gcc/calls.c index f0c92ddc0..5d7df8b63 100644 --- a/gcc-4.9/gcc/calls.c +++ b/gcc-4.9/gcc/calls.c @@ -184,6 +184,18 @@ prepare_call_address (tree fndecl, rtx funexp, rtx static_chain_value, && targetm.small_register_classes_for_mode_p (FUNCTION_MODE)) ? force_not_mem (memory_address (FUNCTION_MODE, funexp)) : memory_address (FUNCTION_MODE, funexp)); + else if (flag_pic + && fndecl + && TREE_CODE (fndecl) == FUNCTION_DECL + && (!flag_plt + || lookup_attribute ("noplt", DECL_ATTRIBUTES (fndecl))) + && !targetm.binds_local_p (fndecl)) + { + /* This is done only for PIC code. There is no easy interface to force the + function address into GOT for non-PIC case. non-PIC case needs to be + handled specially by the backend. */ + funexp = force_reg (Pmode, funexp); + } else if (! sibcallp) { #ifndef NO_FUNCTION_CSE diff --git a/gcc-4.9/gcc/cfg-flags.def b/gcc-4.9/gcc/cfg-flags.def index a28ba34b5..afd239463 100644 --- a/gcc-4.9/gcc/cfg-flags.def +++ b/gcc-4.9/gcc/cfg-flags.def @@ -93,9 +93,8 @@ DEF_BASIC_BLOCK_FLAG(VISITED, 13) demand, and is available after calling compute_transaction_bits(). */ DEF_BASIC_BLOCK_FLAG(IN_TRANSACTION, 14) -/* Set on blocks that has been annotated during AutoFDO profile - attribution. */ -DEF_BASIC_BLOCK_FLAG(ANNOTATED, 15) +/* Set on blocks that fp could be used freely. */ +DEF_BASIC_BLOCK_FLAG(FP_IS_FREE, 15) #endif #ifdef DEF_EDGE_FLAG @@ -180,9 +179,6 @@ DEF_EDGE_FLAG(TM_UNINSTRUMENTED, 15) /* Abort (over) edge out of a GIMPLE_TRANSACTION statement. */ DEF_EDGE_FLAG(TM_ABORT, 16) -/* Annotated during AutoFDO profile attribution. */ -DEF_EDGE_FLAG(ANNOTATED, 17) - /* Edge probability predicted by __builtin_expect. */ DEF_EDGE_FLAG(PREDICTED_BY_EXPECT, 18) diff --git a/gcc-4.9/gcc/cfgcleanup.c b/gcc-4.9/gcc/cfgcleanup.c index de307da54..53ea30028 100644 --- a/gcc-4.9/gcc/cfgcleanup.c +++ b/gcc-4.9/gcc/cfgcleanup.c @@ -1174,7 +1174,7 @@ old_insns_match_p (int mode ATTRIBUTE_UNUSED, rtx i1, rtx i2) && DECL_FUNCTION_CODE (SYMBOL_REF_DECL (symbol)) >= BUILT_IN_ASAN_REPORT_LOAD1 && DECL_FUNCTION_CODE (SYMBOL_REF_DECL (symbol)) - <= BUILT_IN_ASAN_REPORT_STORE16) + <= BUILT_IN_ASAN_STOREN) return dir_none; } } diff --git a/gcc-4.9/gcc/cfgloop.c b/gcc-4.9/gcc/cfgloop.c index 14693f1c9..e4b60f5d8 100644 --- a/gcc-4.9/gcc/cfgloop.c +++ b/gcc-4.9/gcc/cfgloop.c @@ -1875,7 +1875,8 @@ record_niter_bound (struct loop *loop, double_int i_bound, bool realistic, } if (realistic && (!loop->any_estimate - || i_bound.ult (loop->nb_iterations_estimate))) + || (!flag_auto_profile && + i_bound.ult (loop->nb_iterations_estimate)))) { loop->any_estimate = true; loop->nb_iterations_estimate = i_bound; diff --git a/gcc-4.9/gcc/cfgrtl.c b/gcc-4.9/gcc/cfgrtl.c index 2c5ca2ac1..ed1c37cd4 100644 --- a/gcc-4.9/gcc/cfgrtl.c +++ b/gcc-4.9/gcc/cfgrtl.c @@ -1453,7 +1453,24 @@ emit_barrier_after_bb (basic_block bb) gcc_assert (current_ir_type () == IR_RTL_CFGRTL || current_ir_type () == IR_RTL_CFGLAYOUT); if (current_ir_type () == IR_RTL_CFGLAYOUT) - BB_FOOTER (bb) = unlink_insn_chain (barrier, barrier); + { + rtx insn = unlink_insn_chain (barrier, barrier); + + if (BB_FOOTER (bb)) + { + rtx footer_tail = BB_FOOTER (bb); + + while (NEXT_INSN (footer_tail)) + footer_tail = NEXT_INSN (footer_tail); + if (!BARRIER_P (footer_tail)) + { + NEXT_INSN (footer_tail) = insn; + PREV_INSN (insn) = footer_tail; + } + } + else + BB_FOOTER (bb) = insn; + } } /* Like force_nonfallthru below, but additionally performs redirection @@ -1761,6 +1778,22 @@ rtl_tidy_fallthru_edge (edge e) && (any_uncondjump_p (q) || single_succ_p (b))) { + rtx label, table; + + if (tablejump_p (q, &label, &table)) + { + /* The label is likely mentioned in some instruction before + the tablejump and might not be DCEd, so turn it into + a note instead and move before the tablejump that is going to + be deleted. */ + const char *name = LABEL_NAME (label); + PUT_CODE (label, NOTE); + NOTE_KIND (label) = NOTE_INSN_DELETED_LABEL; + NOTE_DELETED_LABEL_NAME (label) = name; + reorder_insns (label, label, PREV_INSN (q)); + delete_insn (table); + } + #ifdef HAVE_cc0 /* If this was a conditional jump, we need to also delete the insn that set cc0. */ @@ -2481,7 +2514,6 @@ rtl_verify_edges (void) | EDGE_LOOP_EXIT | EDGE_CROSSING | EDGE_PRESERVE - | EDGE_ANNOTATED | EDGE_PREDICTED_BY_EXPECT)) == 0) n_branch++; diff --git a/gcc-4.9/gcc/cgraph.c b/gcc-4.9/gcc/cgraph.c index 63b7b4d60..532d09b28 100644 --- a/gcc-4.9/gcc/cgraph.c +++ b/gcc-4.9/gcc/cgraph.c @@ -64,6 +64,7 @@ along with GCC; see the file COPYING3. If not see #include "gimple-pretty-print.h" #include "expr.h" #include "tree-dfa.h" +#include "opts.h" /* FIXME: Only for PROP_loops, but cgraph shouldn't have to know about this. */ #include "tree-pass.h" @@ -546,6 +547,7 @@ cgraph_create_node (tree decl) node->next_nested = node->origin->nested; node->origin->nested = node; } + pattern_match_function_attributes (decl); return node; } @@ -2462,6 +2464,11 @@ cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node) /* Extern inlines can always go, we will use the external definition. */ if (DECL_EXTERNAL (node->decl)) return true; + /* Aux functions are safe to remove, but only once static promotion is + complete since they may affect promoted names if they are the context + for any static variables. */ + if (cgraph_pre_profiling_inlining_done && cgraph_is_aux_decl_external (node)) + return true; /* When function is needed, we can not remove it. */ if (node->force_output || node->used_from_other_partition) return false; diff --git a/gcc-4.9/gcc/cgraph.h b/gcc-4.9/gcc/cgraph.h index ee32bcb6b..414c2c9d0 100644 --- a/gcc-4.9/gcc/cgraph.h +++ b/gcc-4.9/gcc/cgraph.h @@ -816,6 +816,7 @@ void cgraph_unnest_node (struct cgraph_node *); enum availability cgraph_function_body_availability (struct cgraph_node *); void cgraph_add_new_function (tree, bool); +void cgraph_analyze_function (struct cgraph_node *); const char* cgraph_inline_failed_string (cgraph_inline_failed_t); cgraph_inline_failed_type_t cgraph_inline_failed_type (cgraph_inline_failed_t); diff --git a/gcc-4.9/gcc/cgraphbuild.c b/gcc-4.9/gcc/cgraphbuild.c index c6b04be5a..879a77a44 100644 --- a/gcc-4.9/gcc/cgraphbuild.c +++ b/gcc-4.9/gcc/cgraphbuild.c @@ -665,6 +665,45 @@ record_references_in_initializer (tree decl, bool only_vars) pointer_set_destroy (visited_nodes); } +typedef struct _fixup_decl_info { + tree orig_decl; + tree new_decl; +} fixup_decl_info; + +/* Check the tree at TP to see if it contains the original decl stored in + DATA and if so replace it with the new decl. If original decl is + found set WALK_SUBTREES to 0 so the subtree under TP is not traversed. + Returns the updated parent tree T or NULL if no update performed. */ + +static tree +fixup_all_refs_1 (tree *tp, int *walk_subtrees, void *data) +{ + tree t = *tp; + fixup_decl_info *info = (fixup_decl_info *) data; + + /* The original function decl is always the first tree operand. */ + if (TREE_OPERAND (t,0) == info->orig_decl) + { + TREE_OPERAND (t,0) = info->new_decl; + *walk_subtrees = 0; + return t; + } + return NULL_TREE; +} + +/* Walk the whole tree rooted at TP and invoke fixup_all_refs_1 to + replace any references to the original decl with the new decl + stored in INFO. */ + +static inline void +fixup_all_refs (tree *tp, fixup_decl_info *info) +{ + tree t = walk_tree (tp, fixup_all_refs_1, info, NULL); + /* This is invoked when we found the original decl, so we expect + to have replaced a reference. */ + gcc_assert (t != NULL_TREE); +} + /* Update any function decl references in base ADDR of operand OP to refer to the resolved node. */ @@ -674,13 +713,16 @@ fixup_ref (gimple, tree addr, tree op) addr = get_base_address (addr); if (addr && TREE_CODE (addr) == FUNCTION_DECL) { - gcc_assert (TREE_CODE (op) == ADDR_EXPR); - gcc_assert (TREE_OPERAND (op,0) == addr); struct cgraph_node *real_callee; real_callee = cgraph_lipo_get_resolved_node (addr); if (addr == real_callee->decl) return false; - TREE_OPERAND (op,0) = real_callee->decl; + /* We need to locate and update the tree operand within OP + that contains ADDR and update it to the real callee's decl. */ + fixup_decl_info info; + info.orig_decl = addr; + info.new_decl = real_callee->decl; + fixup_all_refs (&op, &info); } return false; } diff --git a/gcc-4.9/gcc/cgraphclones.c b/gcc-4.9/gcc/cgraphclones.c index 9fec2a04d..c23509c28 100644 --- a/gcc-4.9/gcc/cgraphclones.c +++ b/gcc-4.9/gcc/cgraphclones.c @@ -315,6 +315,11 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node) if (thunk_of->thunk.thunk_p) node = duplicate_thunk_for_node (thunk_of, node); + /* We need to copy arguments, at LTO these mat not be read from function + section. */ + if (!DECL_ARGUMENTS (thunk->decl)) + cgraph_get_body (thunk); + struct cgraph_edge *cs; for (cs = node->callers; cs; cs = cs->next_caller) if (cs->caller->thunk.thunk_p @@ -339,6 +344,22 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node) node->clone.args_to_skip, false); } + + tree *link = &DECL_ARGUMENTS (new_decl); + int i = 0; + for (tree pd = DECL_ARGUMENTS (thunk->decl); pd; pd = DECL_CHAIN (pd), i++) + { + if (!node->clone.args_to_skip + || !bitmap_bit_p (node->clone.args_to_skip, i)) + { + tree nd = copy_node (pd); + DECL_CONTEXT (nd) = new_decl; + *link = nd; + link = &DECL_CHAIN (nd); + } + } + *link = NULL_TREE; + gcc_checking_assert (!DECL_STRUCT_FUNCTION (new_decl)); gcc_checking_assert (!DECL_INITIAL (new_decl)); gcc_checking_assert (!DECL_RESULT (new_decl)); @@ -363,6 +384,11 @@ duplicate_thunk_for_node (cgraph_node *thunk, cgraph_node *node) cgraph_call_edge_duplication_hooks (thunk->callees, e); if (!expand_thunk (new_thunk, false)) new_thunk->analyzed = true; + else + { + new_thunk->thunk.thunk_p = false; + cgraph_analyze_function (new_thunk); + } cgraph_call_node_duplication_hooks (thunk, new_thunk); return new_thunk; } diff --git a/gcc-4.9/gcc/cgraphunit.c b/gcc-4.9/gcc/cgraphunit.c index bff2833a1..6ddc7fb10 100644 --- a/gcc-4.9/gcc/cgraphunit.c +++ b/gcc-4.9/gcc/cgraphunit.c @@ -221,7 +221,6 @@ cgraph_node_set cgraph_new_nodes; static void expand_all_functions (void); static void mark_functions_to_output (void); static void expand_function (struct cgraph_node *); -static void analyze_function (struct cgraph_node *); static void handle_alias_pairs (void); FILE *cgraph_dump_file; @@ -340,7 +339,7 @@ cgraph_process_new_functions (void) gimple_register_cfg_hooks (); if (!node->analyzed) - analyze_function (node); + cgraph_analyze_function (node); push_cfun (DECL_STRUCT_FUNCTION (fndecl)); if (cgraph_state == CGRAPH_STATE_IPA_SSA && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl))) @@ -551,7 +550,7 @@ cgraph_add_new_function (tree fndecl, bool lowered) if (lowered) node->lowered = true; node->definition = true; - analyze_function (node); + cgraph_analyze_function (node); push_cfun (DECL_STRUCT_FUNCTION (fndecl)); gimple_register_cfg_hooks (); bitmap_obstack_initialize (NULL); @@ -607,8 +606,8 @@ output_asm_statements (void) } /* Analyze the function scheduled to be output. */ -static void -analyze_function (struct cgraph_node *node) +void +cgraph_analyze_function (struct cgraph_node *node) { tree decl = node->decl; location_t saved_loc = input_location; @@ -1024,7 +1023,7 @@ analyze_functions (void) } if (!cnode->analyzed) - analyze_function (cnode); + cgraph_analyze_function (cnode); for (edge = cnode->callees; edge; edge = edge->next_callee) if (edge->callee->definition) @@ -1049,7 +1048,7 @@ analyze_functions (void) if (DECL_ABSTRACT_ORIGIN (decl)) { struct cgraph_node *origin_node - = cgraph_get_node (DECL_ABSTRACT_ORIGIN (decl)); + = cgraph_get_create_node (DECL_ABSTRACT_ORIGIN (decl)); origin_node->used_as_abstract_origin = true; enqueue_node (origin_node); } @@ -1181,7 +1180,7 @@ handle_alias_pairs (void) /* We use local aliases for C++ thunks to force the tailcall to bind locally. This is a hack - to keep it working do the following (which is not strictly correct). */ - && (! TREE_CODE (target_node->decl) == FUNCTION_DECL + && (TREE_CODE (target_node->decl) != FUNCTION_DECL || ! DECL_VIRTUAL_P (target_node->decl)) && ! lookup_attribute ("weakref", DECL_ATTRIBUTES (p->decl))) { diff --git a/gcc-4.9/gcc/collect2.c b/gcc-4.9/gcc/collect2.c index 5a2ec0b5d..ddc190487 100644 --- a/gcc-4.9/gcc/collect2.c +++ b/gcc-4.9/gcc/collect2.c @@ -1345,6 +1345,12 @@ main (int argc, char **argv) ld1--; ld2--; } + else if (strncmp (arg, "-fno-lto", 8) == 0) + { + /* Do not pass -fno-lto to the linker. */ + ld1--; + ld2--; + } #ifdef TARGET_AIX_VERSION else { diff --git a/gcc-4.9/gcc/combine.c b/gcc-4.9/gcc/combine.c index 7c0045205..adea2c161 100644 --- a/gcc-4.9/gcc/combine.c +++ b/gcc-4.9/gcc/combine.c @@ -1529,8 +1529,8 @@ setup_incoming_promotions (rtx first) uns3 = TYPE_UNSIGNED (DECL_ARG_TYPE (arg)); /* The mode and signedness of the argument as it is actually passed, - after any TARGET_PROMOTE_FUNCTION_ARGS-driven ABI promotions. */ - mode3 = promote_function_mode (DECL_ARG_TYPE (arg), mode2, &uns3, + see assign_parm_setup_reg in function.c. */ + mode3 = promote_function_mode (TREE_TYPE (arg), mode1, &uns3, TREE_TYPE (cfun->decl), 0); /* The mode of the register in which the argument is being passed. */ diff --git a/gcc-4.9/gcc/common.opt b/gcc-4.9/gcc/common.opt index 40607738a..d4e989b40 100644 --- a/gcc-4.9/gcc/common.opt +++ b/gcc-4.9/gcc/common.opt @@ -322,6 +322,9 @@ Common Alias(Wpedantic) -pedantic-errors Common Alias(pedantic-errors) +-no-pie +Driver Alias(no-pie) + -pie Driver Alias(pie) @@ -1210,10 +1213,23 @@ fdwarf2-cfi-asm Common Report Var(flag_dwarf2_cfi_asm) Init(HAVE_GAS_CFI_DIRECTIVE) Enable CFI tables via GAS assembler directives. +ftwo-level-all-subprogs +Common Report Var(flag_two_level_all_subprogs) Init(0) +When generating two-level line tables in DWARF (experimental), +add linkage names for all functions (not just inlined functions). + +ftwo-level-line-tables +Common Report Var(flag_two_level_line_tables) Init(0) +Use two-level line tables in DWARF (experimental). + fripa Common Report Var(flag_dyn_ipa) Perform Dynamic Inter-Procedural Analysis. +fripa-allow-debug +Common Report Var(flag_dyn_ipa_allow_debug) Init(0) +Allow -g enablement for -fripa -fprofile-generate compiles. + fripa-disallow-asm-modules Common Report Var(flag_ripa_disallow_asm_modules) Don't import an auxiliary module if it contains asm statements @@ -1324,6 +1340,10 @@ Enum(fp_contract_mode) String(on) Value(FP_CONTRACT_OFF) EnumValue Enum(fp_contract_mode) String(fast) Value(FP_CONTRACT_FAST) +ffunction-attribute-list= +Common Joined RejectNegative Var(common_deferred_options) Defer +-ffunction-attribute-list=attribute:name,... Add attribute to named functions + ; Nonzero means don't put addresses of constant functions in registers. ; Used for compiling the Unix kernel, where strange substitutions are ; done on the assembly output. @@ -1715,6 +1735,10 @@ fomit-frame-pointer Common Report Var(flag_omit_frame_pointer) Optimization When possible do not generate stack frames +fshrink-wrap-frame-pointer +Common Report Var(flag_shrink_wrap_frame_pointer) Optimization +Framepointer shrinkwrapping optimization. + fopt-info Common Report Var(flag_opt_info) Optimization Enable all optimization info dumps on stderr @@ -1787,6 +1811,10 @@ fpie Common Report Var(flag_pie,1) Negative(fPIC) Generate position-independent code for executables if possible (small mode) +fplt +Common Report Var(flag_plt) Init(1) Optimization +Use PLT for PIC calls (-fno-plt: load the address from GOT at call site) + fplugin= Common Joined RejectNegative Var(common_deferred_options) Defer Specify a plugin to load @@ -1845,6 +1873,10 @@ fprofile-generate-sampling Common Var(flag_profile_generate_sampling) Turn on instrumentation sampling with -fprofile-generate with rate set by --param profile-generate-sampling-rate or environment variable GCOV_SAMPLING_RATE +fprofile-generate-buildinfo= +Common RejectNegative Joined Var(flag_profile_generate_buildinfo) +-fprofile-generate-buildinfo=filename Read build info to include in gcda file from filename + femit-function-names Common Var(flag_emit_function_names) Print to stderr the mapping from module name and function id to assembler @@ -1909,6 +1941,11 @@ fregmove Common Ignore Does nothing. Preserved for backward compatibility. +flifetime-dse +Common Report Var(flag_lifetime_dse) Init(1) Optimization +Tell DSE that the storage for a C++ object is dead when the constructor +starts and when the destructor finishes. + flive-range-shrinkage Common Report Var(flag_live_range_shrinkage) Init(0) Optimization Relief of register pressure through live range shrinkage @@ -2638,6 +2675,10 @@ ggdb Common JoinedOrMissing Generate debug information in default extended format +gline-tables-only +Common RejectNegative Var(debug_line_tables_only) Init(0) +Generate DWARF line number tables and no other debug sections + gno-pubnames Common Negative(gpubnames) Var(debug_generate_pub_sections, 0) Init(-1) Don't generate DWARF pubnames and pubtypes sections. @@ -2845,7 +2886,7 @@ x Driver Joined Separate shared -Driver RejectNegative Negative(pie) +Driver RejectNegative Negative(no-pie) Create a shared library shared-libgcc @@ -2889,6 +2930,10 @@ Driver symbolic Driver +no-pie +Driver RejectNegative Negative(pie) +Create a position dependent executable + pie Driver RejectNegative Negative(shared) Create a position independent executable diff --git a/gcc-4.9/gcc/config.gcc b/gcc-4.9/gcc/config.gcc index 9f68a8efe..925658a82 100644 --- a/gcc-4.9/gcc/config.gcc +++ b/gcc-4.9/gcc/config.gcc @@ -791,7 +791,13 @@ case ${target} in ;; *-*-rtems*) case ${enable_threads} in - yes) thread_file='rtems' ;; + "" | yes | rtems) thread_file='rtems' ;; + posix) thread_file='posix' ;; + no) ;; + *) + echo 'Unknown thread configuration for RTEMS' + exit 1 + ;; esac tmake_file="${tmake_file} t-rtems" extra_options="${extra_options} rtems.opt" @@ -1038,12 +1044,6 @@ arm*-*-linux-*) # ARM GNU/Linux with ELF tmake_file="$tmake_file arm/t-linux-androideabi" ;; esac - # Pull in spec changes for GRTE configurations. - case ${target} in - *-grte*) - tm_file="${tm_file} linux-grte.h arm/linux-grte.h" - ;; - esac # The BPABI long long divmod functions return a 128-bit value in # registers r0-r3. Correctly modeling that requires the use of # TImode. @@ -1463,12 +1463,6 @@ i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | i else tm_file="${tm_file} i386/gnu-user-common.h i386/gnu-user.h i386/linux-common.h i386/linux.h" fi - # Pull in spec changes for GRTE configurations. - case ${target} in - *-grte*) - tm_file="${tm_file} linux-grte.h" - ;; - esac ;; i[34567]86-*-knetbsd*-gnu) tm_file="${tm_file} i386/gnu-user-common.h i386/gnu-user.h knetbsd-gnu.h i386/knetbsd-gnu.h" @@ -1493,12 +1487,6 @@ x86_64-*-linux* | x86_64-*-kfreebsd*-gnu | x86_64-*-knetbsd*-gnu) extra_options="${extra_options} linux-android.opt" # Assume modern glibc default_gnu_indirect_function=yes - # Pull in spec changes for GRTE configurations. - case ${target} in - *-grte*) - tm_file="${tm_file} linux-grte.h" - ;; - esac ;; x86_64-*-kfreebsd*-gnu) tm_file="${tm_file} kfreebsd-gnu.h i386/kfreebsd-gnu64.h" @@ -2417,12 +2405,6 @@ powerpc*-*-linux*) if test x${enable_secureplt} = xyes; then tm_file="rs6000/secureplt.h ${tm_file}" fi - # Pull in spec changes for GRTE configurations. - case ${target} in - *-grte*) - tm_file="${tm_file} rs6000/linux-grte.h" - ;; - esac ;; powerpc-wrs-vxworks|powerpc-wrs-vxworksae) tm_file="${tm_file} elfos.h freebsd-spec.h rs6000/sysv4.h" @@ -2751,7 +2733,7 @@ sparc-*-elf*) ;; sparc-*-rtems*) tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h sparc/sp-elf.h sparc/rtemself.h rtems.h newlib-stdint.h" - tmake_file="${tmake_file} sparc/t-sparc sparc/t-elf sparc/t-rtems" + tmake_file="${tmake_file} sparc/t-sparc sparc/t-rtems" ;; sparc-*-linux*) tm_file="${tm_file} dbxelf.h elfos.h sparc/sysv4.h gnu-user.h linux.h glibc-stdint.h sparc/tso.h" @@ -3294,6 +3276,9 @@ if test x$with_cpu = x ; then *-leon[3-9]*) with_cpu=leon3 ;; + *-leon[3-9]v7*) + with_cpu=leon3v7 + ;; *) with_cpu="`echo ${target} | sed 's/-.*$//'`" ;; @@ -3629,20 +3614,17 @@ case "${target}" in ;; esac - case "$with_fpu" in - "" \ - | vfp | vfp3 | vfpv3 \ - | vfpv3-fp16 | vfpv3-d16 | vfpv3-d16-fp16 | vfpv3xd \ - | vfpv3xd-fp16 | neon | neon-fp16 | vfpv4 | vfpv4-d16 \ - | fpv4-sp-d16 | neon-vfpv4 | fp-arm-v8 | neon-fp-armv8 \ - | crypto-neon-fp-armv8) - # OK - ;; - *) - echo "Unknown fpu used in --with-fpu=$with_fpu" 2>&1 - exit 1 - ;; - esac + # see if it matches any of the entries in arm-fpus.def + if [ x"$with_fpu" = x ] \ + || grep "^ARM_FPU(\"$with_fpu\"," \ + ${srcdir}/config/arm/arm-fpus.def \ + > /dev/null; then + # OK + true + else + echo "Unknown fpu used in --with-fpu=$with_fpu" 1>&2 + exit 1 + fi case "$with_abi" in "" \ @@ -4111,7 +4093,7 @@ case "${target}" in case ${val} in "" | sparc | sparcv9 | sparc64 \ | v7 | cypress \ - | v8 | supersparc | hypersparc | leon | leon3 \ + | v8 | supersparc | hypersparc | leon | leon3 | leon3v7 \ | sparclite | f930 | f934 | sparclite86x \ | sparclet | tsc701 \ | v9 | ultrasparc | ultrasparc3 | niagara | niagara2 \ diff --git a/gcc-4.9/gcc/config.in b/gcc-4.9/gcc/config.in index 8527ea7d7..7883eb362 100644 --- a/gcc-4.9/gcc/config.in +++ b/gcc-4.9/gcc/config.in @@ -1223,6 +1223,12 @@ #endif +/* Define if isl_schedule_constraints_compute_schedule exists. */ +#ifndef USED_FOR_TARGET +#undef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE +#endif + + /* Define to 1 if you have the `kill' function. */ #ifndef USED_FOR_TARGET #undef HAVE_KILL @@ -1327,6 +1333,12 @@ #endif +/* Define 0/1 if your linker supports -pie option with copy reloc. */ +#ifndef USED_FOR_TARGET +#undef HAVE_LD_PIE_COPYRELOC +#endif + + /* Define if your linker links a mix of read-only and read-write sections into a read-write section. */ #ifndef USED_FOR_TARGET diff --git a/gcc-4.9/gcc/config/aarch64/aarch64-builtins.c b/gcc-4.9/gcc/config/aarch64/aarch64-builtins.c index 55cfe0ab2..a5af874bf 100644 --- a/gcc-4.9/gcc/config/aarch64/aarch64-builtins.c +++ b/gcc-4.9/gcc/config/aarch64/aarch64-builtins.c @@ -371,6 +371,12 @@ static aarch64_simd_builtin_datum aarch64_simd_builtin_data[] = { enum aarch64_builtins { AARCH64_BUILTIN_MIN, + + AARCH64_BUILTIN_GET_FPCR, + AARCH64_BUILTIN_SET_FPCR, + AARCH64_BUILTIN_GET_FPSR, + AARCH64_BUILTIN_SET_FPSR, + AARCH64_SIMD_BUILTIN_BASE, #include "aarch64-simd-builtins.def" AARCH64_SIMD_BUILTIN_MAX = AARCH64_SIMD_BUILTIN_BASE @@ -752,6 +758,24 @@ aarch64_init_simd_builtins (void) void aarch64_init_builtins (void) { + tree ftype_set_fpr + = build_function_type_list (void_type_node, unsigned_type_node, NULL); + tree ftype_get_fpr + = build_function_type_list (unsigned_type_node, NULL); + + aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR] + = add_builtin_function ("__builtin_aarch64_get_fpcr", ftype_get_fpr, + AARCH64_BUILTIN_GET_FPCR, BUILT_IN_MD, NULL, NULL_TREE); + aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR] + = add_builtin_function ("__builtin_aarch64_set_fpcr", ftype_set_fpr, + AARCH64_BUILTIN_SET_FPCR, BUILT_IN_MD, NULL, NULL_TREE); + aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR] + = add_builtin_function ("__builtin_aarch64_get_fpsr", ftype_get_fpr, + AARCH64_BUILTIN_GET_FPSR, BUILT_IN_MD, NULL, NULL_TREE); + aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR] + = add_builtin_function ("__builtin_aarch64_set_fpsr", ftype_set_fpr, + AARCH64_BUILTIN_SET_FPSR, BUILT_IN_MD, NULL, NULL_TREE); + if (TARGET_SIMD) aarch64_init_simd_builtins (); } @@ -964,6 +988,36 @@ aarch64_expand_builtin (tree exp, { tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0); int fcode = DECL_FUNCTION_CODE (fndecl); + int icode; + rtx pat, op0; + tree arg0; + + switch (fcode) + { + case AARCH64_BUILTIN_GET_FPCR: + case AARCH64_BUILTIN_SET_FPCR: + case AARCH64_BUILTIN_GET_FPSR: + case AARCH64_BUILTIN_SET_FPSR: + if ((fcode == AARCH64_BUILTIN_GET_FPCR) + || (fcode == AARCH64_BUILTIN_GET_FPSR)) + { + icode = (fcode == AARCH64_BUILTIN_GET_FPSR) ? + CODE_FOR_get_fpsr : CODE_FOR_get_fpcr; + target = gen_reg_rtx (SImode); + pat = GEN_FCN (icode) (target); + } + else + { + target = NULL_RTX; + icode = (fcode == AARCH64_BUILTIN_SET_FPSR) ? + CODE_FOR_set_fpsr : CODE_FOR_set_fpcr; + arg0 = CALL_EXPR_ARG (exp, 0); + op0 = expand_normal (arg0); + pat = GEN_FCN (icode) (op0); + } + emit_insn (pat); + return target; + } if (fcode >= AARCH64_SIMD_BUILTIN_BASE) return aarch64_simd_expand_builtin (fcode, exp, target); @@ -1196,6 +1250,106 @@ aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi) return changed; } +void +aarch64_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update) +{ + const unsigned AARCH64_FE_INVALID = 1; + const unsigned AARCH64_FE_DIVBYZERO = 2; + const unsigned AARCH64_FE_OVERFLOW = 4; + const unsigned AARCH64_FE_UNDERFLOW = 8; + const unsigned AARCH64_FE_INEXACT = 16; + const unsigned HOST_WIDE_INT AARCH64_FE_ALL_EXCEPT = (AARCH64_FE_INVALID + | AARCH64_FE_DIVBYZERO + | AARCH64_FE_OVERFLOW + | AARCH64_FE_UNDERFLOW + | AARCH64_FE_INEXACT); + const unsigned HOST_WIDE_INT AARCH64_FE_EXCEPT_SHIFT = 8; + tree fenv_cr, fenv_sr, get_fpcr, set_fpcr, mask_cr, mask_sr; + tree ld_fenv_cr, ld_fenv_sr, masked_fenv_cr, masked_fenv_sr, hold_fnclex_cr; + tree hold_fnclex_sr, new_fenv_var, reload_fenv, restore_fnenv, get_fpsr, set_fpsr; + tree update_call, atomic_feraiseexcept, hold_fnclex, masked_fenv, ld_fenv; + + /* Generate the equivalence of : + unsigned int fenv_cr; + fenv_cr = __builtin_aarch64_get_fpcr (); + + unsigned int fenv_sr; + fenv_sr = __builtin_aarch64_get_fpsr (); + + Now set all exceptions to non-stop + unsigned int mask_cr + = ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT); + unsigned int masked_cr; + masked_cr = fenv_cr & mask_cr; + + And clear all exception flags + unsigned int maske_sr = ~AARCH64_FE_ALL_EXCEPT; + unsigned int masked_cr; + masked_sr = fenv_sr & mask_sr; + + __builtin_aarch64_set_cr (masked_cr); + __builtin_aarch64_set_sr (masked_sr); */ + + fenv_cr = create_tmp_var (unsigned_type_node, NULL); + fenv_sr = create_tmp_var (unsigned_type_node, NULL); + + get_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPCR]; + set_fpcr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPCR]; + get_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_GET_FPSR]; + set_fpsr = aarch64_builtin_decls[AARCH64_BUILTIN_SET_FPSR]; + + mask_cr = build_int_cst (unsigned_type_node, + ~(AARCH64_FE_ALL_EXCEPT << AARCH64_FE_EXCEPT_SHIFT)); + mask_sr = build_int_cst (unsigned_type_node, + ~(AARCH64_FE_ALL_EXCEPT)); + + ld_fenv_cr = build2 (MODIFY_EXPR, unsigned_type_node, + fenv_cr, build_call_expr (get_fpcr, 0)); + ld_fenv_sr = build2 (MODIFY_EXPR, unsigned_type_node, + fenv_sr, build_call_expr (get_fpsr, 0)); + + masked_fenv_cr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_cr, mask_cr); + masked_fenv_sr = build2 (BIT_AND_EXPR, unsigned_type_node, fenv_sr, mask_sr); + + hold_fnclex_cr = build_call_expr (set_fpcr, 1, masked_fenv_cr); + hold_fnclex_sr = build_call_expr (set_fpsr, 1, masked_fenv_sr); + + hold_fnclex = build2 (COMPOUND_EXPR, void_type_node, hold_fnclex_cr, + hold_fnclex_sr); + masked_fenv = build2 (COMPOUND_EXPR, void_type_node, masked_fenv_cr, + masked_fenv_sr); + ld_fenv = build2 (COMPOUND_EXPR, void_type_node, ld_fenv_cr, ld_fenv_sr); + + *hold = build2 (COMPOUND_EXPR, void_type_node, + build2 (COMPOUND_EXPR, void_type_node, masked_fenv, ld_fenv), + hold_fnclex); + + /* Store the value of masked_fenv to clear the exceptions: + __builtin_aarch64_set_fpsr (masked_fenv_sr); */ + + *clear = build_call_expr (set_fpsr, 1, masked_fenv_sr); + + /* Generate the equivalent of : + unsigned int new_fenv_var; + new_fenv_var = __builtin_aarch64_get_fpsr (); + + __builtin_aarch64_set_fpsr (fenv_sr); + + __atomic_feraiseexcept (new_fenv_var); */ + + new_fenv_var = create_tmp_var (unsigned_type_node, NULL); + reload_fenv = build2 (MODIFY_EXPR, unsigned_type_node, + new_fenv_var, build_call_expr (get_fpsr, 0)); + restore_fnenv = build_call_expr (set_fpsr, 1, fenv_sr); + atomic_feraiseexcept = builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT); + update_call = build_call_expr (atomic_feraiseexcept, 1, + fold_convert (integer_type_node, new_fenv_var)); + *update = build2 (COMPOUND_EXPR, void_type_node, + build2 (COMPOUND_EXPR, void_type_node, + reload_fenv, restore_fnenv), update_call); +} + + #undef AARCH64_CHECK_BUILTIN_MODE #undef AARCH64_FIND_FRINT_VARIANT #undef BUILTIN_DX diff --git a/gcc-4.9/gcc/config/aarch64/aarch64-elf-raw.h b/gcc-4.9/gcc/config/aarch64/aarch64-elf-raw.h index eafdd551d..bb5c88d53 100644 --- a/gcc-4.9/gcc/config/aarch64/aarch64-elf-raw.h +++ b/gcc-4.9/gcc/config/aarch64/aarch64-elf-raw.h @@ -33,6 +33,14 @@ " %{mfix-cortex-a53-835769:--fix-cortex-a53-835769}" #endif +#ifdef TARGET_FIX_ERR_A53_835769_DEFAULT +#define CA53_ERR_835769_SPEC \ + " %{!mno-fix-cortex-a53-835769:--fix-cortex-a53-835769}" +#else +#define CA53_ERR_835769_SPEC \ + " %{mfix-cortex-a53-835769:--fix-cortex-a53-835769}" +#endif + #ifndef LINK_SPEC #define LINK_SPEC "%{mbig-endian:-EB} %{mlittle-endian:-EL} -X \ -maarch64elf%{mabi=ilp32*:32}%{mbig-endian:b}" \ diff --git a/gcc-4.9/gcc/config/aarch64/aarch64-linux.h b/gcc-4.9/gcc/config/aarch64/aarch64-linux.h index b77becd23..651abe3ce 100644 --- a/gcc-4.9/gcc/config/aarch64/aarch64-linux.h +++ b/gcc-4.9/gcc/config/aarch64/aarch64-linux.h @@ -50,7 +50,16 @@ #define LINUX_TARGET_LINK_SPEC LINUX_TARGET_LINK_SPEC0 CA53_ERR_835769_SPEC -#define LINK_SPEC LINUX_TARGET_LINK_SPEC +#ifdef TARGET_FIX_ERR_A53_835769_DEFAULT +#define CA53_ERR_835769_SPEC \ + " %{!mno-fix-cortex-a53-835769:--fix-cortex-a53-835769}" +#else +#define CA53_ERR_835769_SPEC \ + " %{mfix-cortex-a53-835769:--fix-cortex-a53-835769}" +#endif + +#define LINK_SPEC LINUX_TARGET_LINK_SPEC \ + CA53_ERR_835769_SPEC #define TARGET_OS_CPP_BUILTINS() \ do \ diff --git a/gcc-4.9/gcc/config/aarch64/aarch64-protos.h b/gcc-4.9/gcc/config/aarch64/aarch64-protos.h index bef58bf71..8b0a70538 100644 --- a/gcc-4.9/gcc/config/aarch64/aarch64-protos.h +++ b/gcc-4.9/gcc/config/aarch64/aarch64-protos.h @@ -291,4 +291,5 @@ extern bool aarch64_madd_needs_nop (rtx); extern void aarch64_final_prescan_insn (rtx); extern bool aarch64_expand_vec_perm_const (rtx target, rtx op0, rtx op1, rtx sel); +void aarch64_atomic_assign_expand_fenv (tree *, tree *, tree *); #endif /* GCC_AARCH64_PROTOS_H */ diff --git a/gcc-4.9/gcc/config/aarch64/aarch64-simd.md b/gcc-4.9/gcc/config/aarch64/aarch64-simd.md index 851e77a02..7626ed31f 100644 --- a/gcc-4.9/gcc/config/aarch64/aarch64-simd.md +++ b/gcc-4.9/gcc/config/aarch64/aarch64-simd.md @@ -934,6 +934,41 @@ [(set_attr "type" "neon_minmax")] ) +(define_expand "v2di3" + [(parallel [ + (set (match_operand:V2DI 0 "register_operand" "") + (MAXMIN:V2DI (match_operand:V2DI 1 "register_operand" "") + (match_operand:V2DI 2 "register_operand" ""))) + (clobber (reg:CC CC_REGNUM))])] + "TARGET_SIMD" +{ + enum rtx_code cmp_operator; + rtx cmp_fmt; + + switch () + { + case UMIN: + cmp_operator = LTU; + break; + case SMIN: + cmp_operator = LT; + break; + case UMAX: + cmp_operator = GTU; + break; + case SMAX: + cmp_operator = GT; + break; + default: + gcc_unreachable (); + } + + cmp_fmt = gen_rtx_fmt_ee (cmp_operator, V2DImode, operands[1], operands[2]); + emit_insn (gen_aarch64_vcond_internalv2div2di (operands[0], operands[1], + operands[2], cmp_fmt, operands[1], operands[2])); + DONE; +}) + ;; vec_concat gives a new vector with the low elements from operand 1, and ;; the high elements from operand 2. That is to say, given op1 = { a, b } ;; op2 = { c, d }, vec_concat (op1, op2) = { a, b, c, d }. @@ -4565,8 +4600,8 @@ }) (define_insn "*aarch64_simd_ld1r" - [(set (match_operand:VALLDI 0 "register_operand" "=w") - (vec_duplicate:VALLDI + [(set (match_operand:VALL 0 "register_operand" "=w") + (vec_duplicate:VALL (match_operand: 1 "aarch64_simd_struct_operand" "Utv")))] "TARGET_SIMD" "ld1r\\t{%0.}, %1" diff --git a/gcc-4.9/gcc/config/aarch64/aarch64.c b/gcc-4.9/gcc/config/aarch64/aarch64.c index 2ff6c7cb8..029c54ca3 100644 --- a/gcc-4.9/gcc/config/aarch64/aarch64.c +++ b/gcc-4.9/gcc/config/aarch64/aarch64.c @@ -3874,7 +3874,7 @@ aarch64_print_operand_address (FILE *f, rtx x) switch (GET_CODE (x)) { case PRE_INC: - asm_fprintf (f, "[%s,%d]!", reg_names [REGNO (addr.base)], + asm_fprintf (f, "[%s,%d]!", reg_names [REGNO (addr.base)], GET_MODE_SIZE (aarch64_memory_reference_mode)); return; case POST_INC: @@ -5152,7 +5152,6 @@ aarch64_parse_cpu (void) if (strlen (cpu->name) == len && strncmp (cpu->name, str, len) == 0) { selected_cpu = cpu; - selected_tune = cpu; aarch64_isa_flags = selected_cpu->flags; if (ext != NULL) @@ -5248,9 +5247,8 @@ aarch64_override_options (void) gcc_assert (selected_cpu); - /* The selected cpu may be an architecture, so lookup tuning by core ID. */ if (!selected_tune) - selected_tune = &all_cores[selected_cpu->core]; + selected_tune = selected_cpu; aarch64_tune_flags = selected_tune->flags; aarch64_tune = selected_tune->core; @@ -7194,7 +7192,7 @@ aarch64_expand_vector_init (rtx target, rtx vals) x = XVECEXP (vals, 0, 0); if (!CONST_INT_P (x) && !CONST_DOUBLE_P (x)) n_var = 1, one_var = 0; - + for (i = 1; i < n_elts; ++i) { x = XVECEXP (vals, 0, i); @@ -8642,6 +8640,10 @@ aarch64_cannot_change_mode_class (enum machine_mode from, #define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_SIZES \ aarch64_autovectorize_vector_sizes +#undef TARGET_ATOMIC_ASSIGN_EXPAND_FENV +#define TARGET_ATOMIC_ASSIGN_EXPAND_FENV \ + aarch64_atomic_assign_expand_fenv + /* Section anchor support. */ #undef TARGET_MIN_ANCHOR_OFFSET diff --git a/gcc-4.9/gcc/config/aarch64/aarch64.md b/gcc-4.9/gcc/config/aarch64/aarch64.md index 319f80591..05f5e1b35 100644 --- a/gcc-4.9/gcc/config/aarch64/aarch64.md +++ b/gcc-4.9/gcc/config/aarch64/aarch64.md @@ -107,6 +107,10 @@ (define_c_enum "unspecv" [ UNSPECV_EH_RETURN ; Represent EH_RETURN + UNSPECV_GET_FPCR ; Represent fetch of FPCR content. + UNSPECV_SET_FPCR ; Represent assign of FPCR content. + UNSPECV_GET_FPSR ; Represent fetch of FPSR content. + UNSPECV_SET_FPSR ; Represent assign of FPSR content. ] ) @@ -1102,7 +1106,7 @@ add\\t%x0, %x1, %x2 sub\\t%x0, %x1, #%n2 add\\t%d0, %d1, %d2" - [(set_attr "type" "alu_imm,alu_reg,alu_imm,alu_reg") + [(set_attr "type" "alu_imm,alu_reg,alu_imm,neon_add") (set_attr "simd" "*,*,*,yes")] ) @@ -2782,7 +2786,7 @@ ;; Logical right shift using SISD or Integer instruction (define_insn "*aarch64_lshr_sisd_or_int_3" - [(set (match_operand:GPI 0 "register_operand" "=w,w,r") + [(set (match_operand:GPI 0 "register_operand" "=w,&w,r") (lshiftrt:GPI (match_operand:GPI 1 "register_operand" "w,w,r") (match_operand:QI 2 "aarch64_reg_or_shift_imm_" "Us,w,rUs")))] @@ -2801,11 +2805,13 @@ (match_operand:DI 1 "aarch64_simd_register") (match_operand:QI 2 "aarch64_simd_register")))] "TARGET_SIMD && reload_completed" - [(set (match_dup 2) + [(set (match_dup 3) (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG)) (set (match_dup 0) - (unspec:DI [(match_dup 1) (match_dup 2)] UNSPEC_SISD_USHL))] - "" + (unspec:DI [(match_dup 1) (match_dup 3)] UNSPEC_SISD_USHL))] + { + operands[3] = gen_lowpart (QImode, operands[0]); + } ) (define_split @@ -2814,11 +2820,13 @@ (match_operand:SI 1 "aarch64_simd_register") (match_operand:QI 2 "aarch64_simd_register")))] "TARGET_SIMD && reload_completed" - [(set (match_dup 2) + [(set (match_dup 3) (unspec:QI [(match_dup 2)] UNSPEC_SISD_NEG)) (set (match_dup 0) - (unspec:SI [(match_dup 1) (match_dup 2)] UNSPEC_USHL_2S))] - "" + (unspec:SI [(match_dup 1) (match_dup 3)] UNSPEC_USHL_2S))] + { + operands[3] = gen_lowpart (QImode, operands[0]); + } ) ;; Arithmetic right shift using SISD or Integer instruction @@ -3642,6 +3650,37 @@ DONE; }) +;; Write Floating-point Control Register. +(define_insn "set_fpcr" + [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPCR)] + "" + "msr\\tfpcr, %0\;isb" + [(set_attr "type" "mrs")]) + +;; Read Floating-point Control Register. +(define_insn "get_fpcr" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPCR))] + "" + "mrs\\t%0, fpcr" + [(set_attr "type" "mrs")]) + +;; Write Floating-point Status Register. +(define_insn "set_fpsr" + [(unspec_volatile [(match_operand:SI 0 "register_operand" "r")] UNSPECV_SET_FPSR)] + "" + "msr\\tfpsr, %0" + [(set_attr "type" "mrs")]) + +;; Read Floating-point Status Register. +(define_insn "get_fpsr" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec_volatile:SI [(const_int 0)] UNSPECV_GET_FPSR))] + "" + "mrs\\t%0, fpsr" + [(set_attr "type" "mrs")]) + + ;; AdvSIMD Stuff (include "aarch64-simd.md") diff --git a/gcc-4.9/gcc/config/aarch64/arm_neon.h b/gcc-4.9/gcc/config/aarch64/arm_neon.h index c01669b2c..ae0ae9c1b 100644 --- a/gcc-4.9/gcc/config/aarch64/arm_neon.h +++ b/gcc-4.9/gcc/config/aarch64/arm_neon.h @@ -39,9 +39,6 @@ typedef __builtin_aarch64_simd_hi int16x4_t typedef __builtin_aarch64_simd_si int32x2_t __attribute__ ((__vector_size__ (8))); typedef int64_t int64x1_t; -typedef int32_t int32x1_t; -typedef int16_t int16x1_t; -typedef int8_t int8x1_t; typedef double float64x1_t; typedef __builtin_aarch64_simd_sf float32x2_t __attribute__ ((__vector_size__ (8))); @@ -56,9 +53,6 @@ typedef __builtin_aarch64_simd_uhi uint16x4_t typedef __builtin_aarch64_simd_usi uint32x2_t __attribute__ ((__vector_size__ (8))); typedef uint64_t uint64x1_t; -typedef uint32_t uint32x1_t; -typedef uint16_t uint16x1_t; -typedef uint8_t uint8x1_t; typedef __builtin_aarch64_simd_qi int8x16_t __attribute__ ((__vector_size__ (16))); typedef __builtin_aarch64_simd_hi int16x8_t @@ -8400,7 +8394,7 @@ vmul_n_u32 (uint32x2_t a, uint32_t b) #define vmull_high_lane_s16(a, b, c) \ __extension__ \ ({ \ - int16x8_t b_ = (b); \ + int16x4_t b_ = (b); \ int16x8_t a_ = (a); \ int32x4_t result; \ __asm__ ("smull2 %0.4s, %1.8h, %2.h[%3]" \ @@ -8413,7 +8407,7 @@ vmul_n_u32 (uint32x2_t a, uint32_t b) #define vmull_high_lane_s32(a, b, c) \ __extension__ \ ({ \ - int32x4_t b_ = (b); \ + int32x2_t b_ = (b); \ int32x4_t a_ = (a); \ int64x2_t result; \ __asm__ ("smull2 %0.2d, %1.4s, %2.s[%3]" \ @@ -8426,7 +8420,7 @@ vmul_n_u32 (uint32x2_t a, uint32_t b) #define vmull_high_lane_u16(a, b, c) \ __extension__ \ ({ \ - uint16x8_t b_ = (b); \ + uint16x4_t b_ = (b); \ uint16x8_t a_ = (a); \ uint32x4_t result; \ __asm__ ("umull2 %0.4s, %1.8h, %2.h[%3]" \ @@ -8439,7 +8433,7 @@ vmul_n_u32 (uint32x2_t a, uint32_t b) #define vmull_high_lane_u32(a, b, c) \ __extension__ \ ({ \ - uint32x4_t b_ = (b); \ + uint32x2_t b_ = (b); \ uint32x4_t a_ = (a); \ uint64x2_t result; \ __asm__ ("umull2 %0.2d, %1.4s, %2.s[%3]" \ @@ -20925,42 +20919,42 @@ vqabsq_s64 (int64x2_t __a) return (int64x2_t) __builtin_aarch64_sqabsv2di (__a); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqabsb_s8 (int8x1_t __a) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqabsb_s8 (int8_t __a) { - return (int8x1_t) __builtin_aarch64_sqabsqi (__a); + return (int8_t) __builtin_aarch64_sqabsqi (__a); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqabsh_s16 (int16x1_t __a) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqabsh_s16 (int16_t __a) { - return (int16x1_t) __builtin_aarch64_sqabshi (__a); + return (int16_t) __builtin_aarch64_sqabshi (__a); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqabss_s32 (int32x1_t __a) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqabss_s32 (int32_t __a) { - return (int32x1_t) __builtin_aarch64_sqabssi (__a); + return (int32_t) __builtin_aarch64_sqabssi (__a); } /* vqadd */ -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqaddb_s8 (int8x1_t __a, int8x1_t __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqaddb_s8 (int8_t __a, int8_t __b) { - return (int8x1_t) __builtin_aarch64_sqaddqi (__a, __b); + return (int8_t) __builtin_aarch64_sqaddqi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqaddh_s16 (int16x1_t __a, int16x1_t __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqaddh_s16 (int16_t __a, int16_t __b) { - return (int16x1_t) __builtin_aarch64_sqaddhi (__a, __b); + return (int16_t) __builtin_aarch64_sqaddhi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqadds_s32 (int32x1_t __a, int32x1_t __b) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqadds_s32 (int32_t __a, int32_t __b) { - return (int32x1_t) __builtin_aarch64_sqaddsi (__a, __b); + return (int32_t) __builtin_aarch64_sqaddsi (__a, __b); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) @@ -20969,22 +20963,22 @@ vqaddd_s64 (int64x1_t __a, int64x1_t __b) return (int64x1_t) __builtin_aarch64_sqadddi (__a, __b); } -__extension__ static __inline uint8x1_t __attribute__ ((__always_inline__)) -vqaddb_u8 (uint8x1_t __a, uint8x1_t __b) +__extension__ static __inline uint8_t __attribute__ ((__always_inline__)) +vqaddb_u8 (uint8_t __a, uint8_t __b) { - return (uint8x1_t) __builtin_aarch64_uqaddqi (__a, __b); + return (uint8_t) __builtin_aarch64_uqaddqi (__a, __b); } -__extension__ static __inline uint16x1_t __attribute__ ((__always_inline__)) -vqaddh_u16 (uint16x1_t __a, uint16x1_t __b) +__extension__ static __inline uint16_t __attribute__ ((__always_inline__)) +vqaddh_u16 (uint16_t __a, uint16_t __b) { - return (uint16x1_t) __builtin_aarch64_uqaddhi (__a, __b); + return (uint16_t) __builtin_aarch64_uqaddhi (__a, __b); } -__extension__ static __inline uint32x1_t __attribute__ ((__always_inline__)) -vqadds_u32 (uint32x1_t __a, uint32x1_t __b) +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +vqadds_u32 (uint32_t __a, uint32_t __b) { - return (uint32x1_t) __builtin_aarch64_uqaddsi (__a, __b); + return (uint32_t) __builtin_aarch64_uqaddsi (__a, __b); } __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) @@ -21095,26 +21089,26 @@ vqdmlal_n_s32 (int64x2_t __a, int32x2_t __b, int32_t __c) return __builtin_aarch64_sqdmlal_nv2si (__a, __b, __c); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqdmlalh_s16 (int32x1_t __a, int16x1_t __b, int16x1_t __c) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqdmlalh_s16 (int32_t __a, int16_t __b, int16_t __c) { return __builtin_aarch64_sqdmlalhi (__a, __b, __c); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqdmlalh_lane_s16 (int32x1_t __a, int16x1_t __b, int16x4_t __c, const int __d) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqdmlalh_lane_s16 (int32_t __a, int16_t __b, int16x4_t __c, const int __d) { return __builtin_aarch64_sqdmlal_lanehi (__a, __b, __c, __d); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) -vqdmlals_s32 (int64x1_t __a, int32x1_t __b, int32x1_t __c) +vqdmlals_s32 (int64x1_t __a, int32_t __b, int32_t __c) { return __builtin_aarch64_sqdmlalsi (__a, __b, __c); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) -vqdmlals_lane_s32 (int64x1_t __a, int32x1_t __b, int32x2_t __c, const int __d) +vqdmlals_lane_s32 (int64x1_t __a, int32_t __b, int32x2_t __c, const int __d) { return __builtin_aarch64_sqdmlal_lanesi (__a, __b, __c, __d); } @@ -21221,26 +21215,26 @@ vqdmlsl_n_s32 (int64x2_t __a, int32x2_t __b, int32_t __c) return __builtin_aarch64_sqdmlsl_nv2si (__a, __b, __c); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqdmlslh_s16 (int32x1_t __a, int16x1_t __b, int16x1_t __c) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqdmlslh_s16 (int32_t __a, int16_t __b, int16_t __c) { return __builtin_aarch64_sqdmlslhi (__a, __b, __c); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqdmlslh_lane_s16 (int32x1_t __a, int16x1_t __b, int16x4_t __c, const int __d) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqdmlslh_lane_s16 (int32_t __a, int16_t __b, int16x4_t __c, const int __d) { return __builtin_aarch64_sqdmlsl_lanehi (__a, __b, __c, __d); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) -vqdmlsls_s32 (int64x1_t __a, int32x1_t __b, int32x1_t __c) +vqdmlsls_s32 (int64x1_t __a, int32_t __b, int32_t __c) { return __builtin_aarch64_sqdmlslsi (__a, __b, __c); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) -vqdmlsls_lane_s32 (int64x1_t __a, int32x1_t __b, int32x2_t __c, const int __d) +vqdmlsls_lane_s32 (int64x1_t __a, int32_t __b, int32x2_t __c, const int __d) { return __builtin_aarch64_sqdmlsl_lanesi (__a, __b, __c, __d); } @@ -21271,26 +21265,26 @@ vqdmulhq_lane_s32 (int32x4_t __a, int32x2_t __b, const int __c) return __builtin_aarch64_sqdmulh_lanev4si (__a, __b, __c); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqdmulhh_s16 (int16x1_t __a, int16x1_t __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqdmulhh_s16 (int16_t __a, int16_t __b) { - return (int16x1_t) __builtin_aarch64_sqdmulhhi (__a, __b); + return (int16_t) __builtin_aarch64_sqdmulhhi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqdmulhh_lane_s16 (int16x1_t __a, int16x4_t __b, const int __c) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqdmulhh_lane_s16 (int16_t __a, int16x4_t __b, const int __c) { return __builtin_aarch64_sqdmulh_lanehi (__a, __b, __c); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqdmulhs_s32 (int32x1_t __a, int32x1_t __b) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqdmulhs_s32 (int32_t __a, int32_t __b) { - return (int32x1_t) __builtin_aarch64_sqdmulhsi (__a, __b); + return (int32_t) __builtin_aarch64_sqdmulhsi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqdmulhs_lane_s32 (int32x1_t __a, int32x2_t __b, const int __c) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqdmulhs_lane_s32 (int32_t __a, int32x2_t __b, const int __c) { return __builtin_aarch64_sqdmulh_lanesi (__a, __b, __c); } @@ -21393,26 +21387,26 @@ vqdmull_n_s32 (int32x2_t __a, int32_t __b) return __builtin_aarch64_sqdmull_nv2si (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqdmullh_s16 (int16x1_t __a, int16x1_t __b) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqdmullh_s16 (int16_t __a, int16_t __b) { - return (int32x1_t) __builtin_aarch64_sqdmullhi (__a, __b); + return (int32_t) __builtin_aarch64_sqdmullhi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqdmullh_lane_s16 (int16x1_t __a, int16x4_t __b, const int __c) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqdmullh_lane_s16 (int16_t __a, int16x4_t __b, const int __c) { return __builtin_aarch64_sqdmull_lanehi (__a, __b, __c); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) -vqdmulls_s32 (int32x1_t __a, int32x1_t __b) +vqdmulls_s32 (int32_t __a, int32_t __b) { return (int64x1_t) __builtin_aarch64_sqdmullsi (__a, __b); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) -vqdmulls_lane_s32 (int32x1_t __a, int32x2_t __b, const int __c) +vqdmulls_lane_s32 (int32_t __a, int32x2_t __b, const int __c) { return __builtin_aarch64_sqdmull_lanesi (__a, __b, __c); } @@ -21455,40 +21449,40 @@ vqmovn_u64 (uint64x2_t __a) return (uint32x2_t) __builtin_aarch64_uqmovnv2di ((int64x2_t) __a); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqmovnh_s16 (int16x1_t __a) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqmovnh_s16 (int16_t __a) { - return (int8x1_t) __builtin_aarch64_sqmovnhi (__a); + return (int8_t) __builtin_aarch64_sqmovnhi (__a); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqmovns_s32 (int32x1_t __a) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqmovns_s32 (int32_t __a) { - return (int16x1_t) __builtin_aarch64_sqmovnsi (__a); + return (int16_t) __builtin_aarch64_sqmovnsi (__a); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) vqmovnd_s64 (int64x1_t __a) { - return (int32x1_t) __builtin_aarch64_sqmovndi (__a); + return (int32_t) __builtin_aarch64_sqmovndi (__a); } -__extension__ static __inline uint8x1_t __attribute__ ((__always_inline__)) -vqmovnh_u16 (uint16x1_t __a) +__extension__ static __inline uint8_t __attribute__ ((__always_inline__)) +vqmovnh_u16 (uint16_t __a) { - return (uint8x1_t) __builtin_aarch64_uqmovnhi (__a); + return (uint8_t) __builtin_aarch64_uqmovnhi (__a); } -__extension__ static __inline uint16x1_t __attribute__ ((__always_inline__)) -vqmovns_u32 (uint32x1_t __a) +__extension__ static __inline uint16_t __attribute__ ((__always_inline__)) +vqmovns_u32 (uint32_t __a) { - return (uint16x1_t) __builtin_aarch64_uqmovnsi (__a); + return (uint16_t) __builtin_aarch64_uqmovnsi (__a); } -__extension__ static __inline uint32x1_t __attribute__ ((__always_inline__)) +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) vqmovnd_u64 (uint64x1_t __a) { - return (uint32x1_t) __builtin_aarch64_uqmovndi (__a); + return (uint32_t) __builtin_aarch64_uqmovndi (__a); } /* vqmovun */ @@ -21511,22 +21505,22 @@ vqmovun_s64 (int64x2_t __a) return (uint32x2_t) __builtin_aarch64_sqmovunv2di (__a); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqmovunh_s16 (int16x1_t __a) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqmovunh_s16 (int16_t __a) { - return (int8x1_t) __builtin_aarch64_sqmovunhi (__a); + return (int8_t) __builtin_aarch64_sqmovunhi (__a); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqmovuns_s32 (int32x1_t __a) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqmovuns_s32 (int32_t __a) { - return (int16x1_t) __builtin_aarch64_sqmovunsi (__a); + return (int16_t) __builtin_aarch64_sqmovunsi (__a); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) vqmovund_s64 (int64x1_t __a) { - return (int32x1_t) __builtin_aarch64_sqmovundi (__a); + return (int32_t) __builtin_aarch64_sqmovundi (__a); } /* vqneg */ @@ -21537,22 +21531,22 @@ vqnegq_s64 (int64x2_t __a) return (int64x2_t) __builtin_aarch64_sqnegv2di (__a); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqnegb_s8 (int8x1_t __a) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqnegb_s8 (int8_t __a) { - return (int8x1_t) __builtin_aarch64_sqnegqi (__a); + return (int8_t) __builtin_aarch64_sqnegqi (__a); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqnegh_s16 (int16x1_t __a) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqnegh_s16 (int16_t __a) { - return (int16x1_t) __builtin_aarch64_sqneghi (__a); + return (int16_t) __builtin_aarch64_sqneghi (__a); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqnegs_s32 (int32x1_t __a) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqnegs_s32 (int32_t __a) { - return (int32x1_t) __builtin_aarch64_sqnegsi (__a); + return (int32_t) __builtin_aarch64_sqnegsi (__a); } /* vqrdmulh */ @@ -21581,26 +21575,26 @@ vqrdmulhq_lane_s32 (int32x4_t __a, int32x2_t __b, const int __c) return __builtin_aarch64_sqrdmulh_lanev4si (__a, __b, __c); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqrdmulhh_s16 (int16x1_t __a, int16x1_t __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqrdmulhh_s16 (int16_t __a, int16_t __b) { - return (int16x1_t) __builtin_aarch64_sqrdmulhhi (__a, __b); + return (int16_t) __builtin_aarch64_sqrdmulhhi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqrdmulhh_lane_s16 (int16x1_t __a, int16x4_t __b, const int __c) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqrdmulhh_lane_s16 (int16_t __a, int16x4_t __b, const int __c) { return __builtin_aarch64_sqrdmulh_lanehi (__a, __b, __c); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqrdmulhs_s32 (int32x1_t __a, int32x1_t __b) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqrdmulhs_s32 (int32_t __a, int32_t __b) { - return (int32x1_t) __builtin_aarch64_sqrdmulhsi (__a, __b); + return (int32_t) __builtin_aarch64_sqrdmulhsi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqrdmulhs_lane_s32 (int32x1_t __a, int32x2_t __b, const int __c) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqrdmulhs_lane_s32 (int32_t __a, int32x2_t __b, const int __c) { return __builtin_aarch64_sqrdmulh_lanesi (__a, __b, __c); } @@ -21703,20 +21697,20 @@ vqrshlq_u64 (uint64x2_t __a, int64x2_t __b) return (uint64x2_t) __builtin_aarch64_uqrshlv2di ((int64x2_t) __a, __b); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqrshlb_s8 (int8x1_t __a, int8x1_t __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqrshlb_s8 (int8_t __a, int8_t __b) { return __builtin_aarch64_sqrshlqi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqrshlh_s16 (int16x1_t __a, int16x1_t __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqrshlh_s16 (int16_t __a, int16_t __b) { return __builtin_aarch64_sqrshlhi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqrshls_s32 (int32x1_t __a, int32x1_t __b) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqrshls_s32 (int32_t __a, int32_t __b) { return __builtin_aarch64_sqrshlsi (__a, __b); } @@ -21727,22 +21721,22 @@ vqrshld_s64 (int64x1_t __a, int64x1_t __b) return __builtin_aarch64_sqrshldi (__a, __b); } -__extension__ static __inline uint8x1_t __attribute__ ((__always_inline__)) -vqrshlb_u8 (uint8x1_t __a, uint8x1_t __b) +__extension__ static __inline uint8_t __attribute__ ((__always_inline__)) +vqrshlb_u8 (uint8_t __a, uint8_t __b) { - return (uint8x1_t) __builtin_aarch64_uqrshlqi (__a, __b); + return (uint8_t) __builtin_aarch64_uqrshlqi (__a, __b); } -__extension__ static __inline uint16x1_t __attribute__ ((__always_inline__)) -vqrshlh_u16 (uint16x1_t __a, uint16x1_t __b) +__extension__ static __inline uint16_t __attribute__ ((__always_inline__)) +vqrshlh_u16 (uint16_t __a, uint16_t __b) { - return (uint16x1_t) __builtin_aarch64_uqrshlhi (__a, __b); + return (uint16_t) __builtin_aarch64_uqrshlhi (__a, __b); } -__extension__ static __inline uint32x1_t __attribute__ ((__always_inline__)) -vqrshls_u32 (uint32x1_t __a, uint32x1_t __b) +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +vqrshls_u32 (uint32_t __a, uint32_t __b) { - return (uint32x1_t) __builtin_aarch64_uqrshlsi (__a, __b); + return (uint32_t) __builtin_aarch64_uqrshlsi (__a, __b); } __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) @@ -21789,40 +21783,40 @@ vqrshrn_n_u64 (uint64x2_t __a, const int __b) return (uint32x2_t) __builtin_aarch64_uqrshrn_nv2di ((int64x2_t) __a, __b); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqrshrnh_n_s16 (int16x1_t __a, const int __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqrshrnh_n_s16 (int16_t __a, const int __b) { - return (int8x1_t) __builtin_aarch64_sqrshrn_nhi (__a, __b); + return (int8_t) __builtin_aarch64_sqrshrn_nhi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqrshrns_n_s32 (int32x1_t __a, const int __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqrshrns_n_s32 (int32_t __a, const int __b) { - return (int16x1_t) __builtin_aarch64_sqrshrn_nsi (__a, __b); + return (int16_t) __builtin_aarch64_sqrshrn_nsi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) vqrshrnd_n_s64 (int64x1_t __a, const int __b) { - return (int32x1_t) __builtin_aarch64_sqrshrn_ndi (__a, __b); + return (int32_t) __builtin_aarch64_sqrshrn_ndi (__a, __b); } -__extension__ static __inline uint8x1_t __attribute__ ((__always_inline__)) -vqrshrnh_n_u16 (uint16x1_t __a, const int __b) +__extension__ static __inline uint8_t __attribute__ ((__always_inline__)) +vqrshrnh_n_u16 (uint16_t __a, const int __b) { - return (uint8x1_t) __builtin_aarch64_uqrshrn_nhi (__a, __b); + return (uint8_t) __builtin_aarch64_uqrshrn_nhi (__a, __b); } -__extension__ static __inline uint16x1_t __attribute__ ((__always_inline__)) -vqrshrns_n_u32 (uint32x1_t __a, const int __b) +__extension__ static __inline uint16_t __attribute__ ((__always_inline__)) +vqrshrns_n_u32 (uint32_t __a, const int __b) { - return (uint16x1_t) __builtin_aarch64_uqrshrn_nsi (__a, __b); + return (uint16_t) __builtin_aarch64_uqrshrn_nsi (__a, __b); } -__extension__ static __inline uint32x1_t __attribute__ ((__always_inline__)) +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) vqrshrnd_n_u64 (uint64x1_t __a, const int __b) { - return (uint32x1_t) __builtin_aarch64_uqrshrn_ndi (__a, __b); + return (uint32_t) __builtin_aarch64_uqrshrn_ndi (__a, __b); } /* vqrshrun */ @@ -21845,22 +21839,22 @@ vqrshrun_n_s64 (int64x2_t __a, const int __b) return (uint32x2_t) __builtin_aarch64_sqrshrun_nv2di (__a, __b); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqrshrunh_n_s16 (int16x1_t __a, const int __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqrshrunh_n_s16 (int16_t __a, const int __b) { - return (int8x1_t) __builtin_aarch64_sqrshrun_nhi (__a, __b); + return (int8_t) __builtin_aarch64_sqrshrun_nhi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqrshruns_n_s32 (int32x1_t __a, const int __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqrshruns_n_s32 (int32_t __a, const int __b) { - return (int16x1_t) __builtin_aarch64_sqrshrun_nsi (__a, __b); + return (int16_t) __builtin_aarch64_sqrshrun_nsi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) vqrshrund_n_s64 (int64x1_t __a, const int __b) { - return (int32x1_t) __builtin_aarch64_sqrshrun_ndi (__a, __b); + return (int32_t) __builtin_aarch64_sqrshrun_ndi (__a, __b); } /* vqshl */ @@ -21961,20 +21955,20 @@ vqshlq_u64 (uint64x2_t __a, int64x2_t __b) return (uint64x2_t) __builtin_aarch64_uqshlv2di ((int64x2_t) __a, __b); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqshlb_s8 (int8x1_t __a, int8x1_t __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqshlb_s8 (int8_t __a, int8_t __b) { return __builtin_aarch64_sqshlqi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqshlh_s16 (int16x1_t __a, int16x1_t __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqshlh_s16 (int16_t __a, int16_t __b) { return __builtin_aarch64_sqshlhi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqshls_s32 (int32x1_t __a, int32x1_t __b) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqshls_s32 (int32_t __a, int32_t __b) { return __builtin_aarch64_sqshlsi (__a, __b); } @@ -21985,22 +21979,22 @@ vqshld_s64 (int64x1_t __a, int64x1_t __b) return __builtin_aarch64_sqshldi (__a, __b); } -__extension__ static __inline uint8x1_t __attribute__ ((__always_inline__)) -vqshlb_u8 (uint8x1_t __a, uint8x1_t __b) +__extension__ static __inline uint8_t __attribute__ ((__always_inline__)) +vqshlb_u8 (uint8_t __a, uint8_t __b) { - return (uint8x1_t) __builtin_aarch64_uqshlqi (__a, __b); + return (uint8_t) __builtin_aarch64_uqshlqi (__a, __b); } -__extension__ static __inline uint16x1_t __attribute__ ((__always_inline__)) -vqshlh_u16 (uint16x1_t __a, uint16x1_t __b) +__extension__ static __inline uint16_t __attribute__ ((__always_inline__)) +vqshlh_u16 (uint16_t __a, uint16_t __b) { - return (uint16x1_t) __builtin_aarch64_uqshlhi (__a, __b); + return (uint16_t) __builtin_aarch64_uqshlhi (__a, __b); } -__extension__ static __inline uint32x1_t __attribute__ ((__always_inline__)) -vqshls_u32 (uint32x1_t __a, uint32x1_t __b) +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +vqshls_u32 (uint32_t __a, uint32_t __b) { - return (uint32x1_t) __builtin_aarch64_uqshlsi (__a, __b); + return (uint32_t) __builtin_aarch64_uqshlsi (__a, __b); } __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) @@ -22105,22 +22099,22 @@ vqshlq_n_u64 (uint64x2_t __a, const int __b) return (uint64x2_t) __builtin_aarch64_uqshl_nv2di ((int64x2_t) __a, __b); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqshlb_n_s8 (int8x1_t __a, const int __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqshlb_n_s8 (int8_t __a, const int __b) { - return (int8x1_t) __builtin_aarch64_sqshl_nqi (__a, __b); + return (int8_t) __builtin_aarch64_sqshl_nqi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqshlh_n_s16 (int16x1_t __a, const int __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqshlh_n_s16 (int16_t __a, const int __b) { - return (int16x1_t) __builtin_aarch64_sqshl_nhi (__a, __b); + return (int16_t) __builtin_aarch64_sqshl_nhi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqshls_n_s32 (int32x1_t __a, const int __b) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqshls_n_s32 (int32_t __a, const int __b) { - return (int32x1_t) __builtin_aarch64_sqshl_nsi (__a, __b); + return (int32_t) __builtin_aarch64_sqshl_nsi (__a, __b); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) @@ -22129,22 +22123,22 @@ vqshld_n_s64 (int64x1_t __a, const int __b) return (int64x1_t) __builtin_aarch64_sqshl_ndi (__a, __b); } -__extension__ static __inline uint8x1_t __attribute__ ((__always_inline__)) -vqshlb_n_u8 (uint8x1_t __a, const int __b) +__extension__ static __inline uint8_t __attribute__ ((__always_inline__)) +vqshlb_n_u8 (uint8_t __a, const int __b) { - return (uint8x1_t) __builtin_aarch64_uqshl_nqi (__a, __b); + return (uint8_t) __builtin_aarch64_uqshl_nqi (__a, __b); } -__extension__ static __inline uint16x1_t __attribute__ ((__always_inline__)) -vqshlh_n_u16 (uint16x1_t __a, const int __b) +__extension__ static __inline uint16_t __attribute__ ((__always_inline__)) +vqshlh_n_u16 (uint16_t __a, const int __b) { - return (uint16x1_t) __builtin_aarch64_uqshl_nhi (__a, __b); + return (uint16_t) __builtin_aarch64_uqshl_nhi (__a, __b); } -__extension__ static __inline uint32x1_t __attribute__ ((__always_inline__)) -vqshls_n_u32 (uint32x1_t __a, const int __b) +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +vqshls_n_u32 (uint32_t __a, const int __b) { - return (uint32x1_t) __builtin_aarch64_uqshl_nsi (__a, __b); + return (uint32_t) __builtin_aarch64_uqshl_nsi (__a, __b); } __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) @@ -22203,22 +22197,22 @@ vqshluq_n_s64 (int64x2_t __a, const int __b) return (uint64x2_t) __builtin_aarch64_sqshlu_nv2di (__a, __b); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqshlub_n_s8 (int8x1_t __a, const int __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqshlub_n_s8 (int8_t __a, const int __b) { - return (int8x1_t) __builtin_aarch64_sqshlu_nqi (__a, __b); + return (int8_t) __builtin_aarch64_sqshlu_nqi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqshluh_n_s16 (int16x1_t __a, const int __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqshluh_n_s16 (int16_t __a, const int __b) { - return (int16x1_t) __builtin_aarch64_sqshlu_nhi (__a, __b); + return (int16_t) __builtin_aarch64_sqshlu_nhi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqshlus_n_s32 (int32x1_t __a, const int __b) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqshlus_n_s32 (int32_t __a, const int __b) { - return (int32x1_t) __builtin_aarch64_sqshlu_nsi (__a, __b); + return (int32_t) __builtin_aarch64_sqshlu_nsi (__a, __b); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) @@ -22265,40 +22259,40 @@ vqshrn_n_u64 (uint64x2_t __a, const int __b) return (uint32x2_t) __builtin_aarch64_uqshrn_nv2di ((int64x2_t) __a, __b); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqshrnh_n_s16 (int16x1_t __a, const int __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqshrnh_n_s16 (int16_t __a, const int __b) { - return (int8x1_t) __builtin_aarch64_sqshrn_nhi (__a, __b); + return (int8_t) __builtin_aarch64_sqshrn_nhi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqshrns_n_s32 (int32x1_t __a, const int __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqshrns_n_s32 (int32_t __a, const int __b) { - return (int16x1_t) __builtin_aarch64_sqshrn_nsi (__a, __b); + return (int16_t) __builtin_aarch64_sqshrn_nsi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) vqshrnd_n_s64 (int64x1_t __a, const int __b) { - return (int32x1_t) __builtin_aarch64_sqshrn_ndi (__a, __b); + return (int32_t) __builtin_aarch64_sqshrn_ndi (__a, __b); } -__extension__ static __inline uint8x1_t __attribute__ ((__always_inline__)) -vqshrnh_n_u16 (uint16x1_t __a, const int __b) +__extension__ static __inline uint8_t __attribute__ ((__always_inline__)) +vqshrnh_n_u16 (uint16_t __a, const int __b) { - return (uint8x1_t) __builtin_aarch64_uqshrn_nhi (__a, __b); + return (uint8_t) __builtin_aarch64_uqshrn_nhi (__a, __b); } -__extension__ static __inline uint16x1_t __attribute__ ((__always_inline__)) -vqshrns_n_u32 (uint32x1_t __a, const int __b) +__extension__ static __inline uint16_t __attribute__ ((__always_inline__)) +vqshrns_n_u32 (uint32_t __a, const int __b) { - return (uint16x1_t) __builtin_aarch64_uqshrn_nsi (__a, __b); + return (uint16_t) __builtin_aarch64_uqshrn_nsi (__a, __b); } -__extension__ static __inline uint32x1_t __attribute__ ((__always_inline__)) +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) vqshrnd_n_u64 (uint64x1_t __a, const int __b) { - return (uint32x1_t) __builtin_aarch64_uqshrn_ndi (__a, __b); + return (uint32_t) __builtin_aarch64_uqshrn_ndi (__a, __b); } /* vqshrun */ @@ -22321,42 +22315,42 @@ vqshrun_n_s64 (int64x2_t __a, const int __b) return (uint32x2_t) __builtin_aarch64_sqshrun_nv2di (__a, __b); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqshrunh_n_s16 (int16x1_t __a, const int __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqshrunh_n_s16 (int16_t __a, const int __b) { - return (int8x1_t) __builtin_aarch64_sqshrun_nhi (__a, __b); + return (int8_t) __builtin_aarch64_sqshrun_nhi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqshruns_n_s32 (int32x1_t __a, const int __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqshruns_n_s32 (int32_t __a, const int __b) { - return (int16x1_t) __builtin_aarch64_sqshrun_nsi (__a, __b); + return (int16_t) __builtin_aarch64_sqshrun_nsi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) vqshrund_n_s64 (int64x1_t __a, const int __b) { - return (int32x1_t) __builtin_aarch64_sqshrun_ndi (__a, __b); + return (int32_t) __builtin_aarch64_sqshrun_ndi (__a, __b); } /* vqsub */ -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vqsubb_s8 (int8x1_t __a, int8x1_t __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vqsubb_s8 (int8_t __a, int8_t __b) { - return (int8x1_t) __builtin_aarch64_sqsubqi (__a, __b); + return (int8_t) __builtin_aarch64_sqsubqi (__a, __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vqsubh_s16 (int16x1_t __a, int16x1_t __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vqsubh_s16 (int16_t __a, int16_t __b) { - return (int16x1_t) __builtin_aarch64_sqsubhi (__a, __b); + return (int16_t) __builtin_aarch64_sqsubhi (__a, __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vqsubs_s32 (int32x1_t __a, int32x1_t __b) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vqsubs_s32 (int32_t __a, int32_t __b) { - return (int32x1_t) __builtin_aarch64_sqsubsi (__a, __b); + return (int32_t) __builtin_aarch64_sqsubsi (__a, __b); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) @@ -22365,22 +22359,22 @@ vqsubd_s64 (int64x1_t __a, int64x1_t __b) return (int64x1_t) __builtin_aarch64_sqsubdi (__a, __b); } -__extension__ static __inline uint8x1_t __attribute__ ((__always_inline__)) -vqsubb_u8 (uint8x1_t __a, uint8x1_t __b) +__extension__ static __inline uint8_t __attribute__ ((__always_inline__)) +vqsubb_u8 (uint8_t __a, uint8_t __b) { - return (uint8x1_t) __builtin_aarch64_uqsubqi (__a, __b); + return (uint8_t) __builtin_aarch64_uqsubqi (__a, __b); } -__extension__ static __inline uint16x1_t __attribute__ ((__always_inline__)) -vqsubh_u16 (uint16x1_t __a, uint16x1_t __b) +__extension__ static __inline uint16_t __attribute__ ((__always_inline__)) +vqsubh_u16 (uint16_t __a, uint16_t __b) { - return (uint16x1_t) __builtin_aarch64_uqsubhi (__a, __b); + return (uint16_t) __builtin_aarch64_uqsubhi (__a, __b); } -__extension__ static __inline uint32x1_t __attribute__ ((__always_inline__)) -vqsubs_u32 (uint32x1_t __a, uint32x1_t __b) +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +vqsubs_u32 (uint32_t __a, uint32_t __b) { - return (uint32x1_t) __builtin_aarch64_uqsubsi (__a, __b); + return (uint32_t) __builtin_aarch64_uqsubsi (__a, __b); } __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) @@ -23596,22 +23590,22 @@ vsqaddq_u64 (uint64x2_t __a, int64x2_t __b) (int64x2_t) __b); } -__extension__ static __inline uint8x1_t __attribute__ ((__always_inline__)) -vsqaddb_u8 (uint8x1_t __a, int8x1_t __b) +__extension__ static __inline uint8_t __attribute__ ((__always_inline__)) +vsqaddb_u8 (uint8_t __a, int8_t __b) { - return (uint8x1_t) __builtin_aarch64_usqaddqi ((int8x1_t) __a, __b); + return (uint8_t) __builtin_aarch64_usqaddqi ((int8_t) __a, __b); } -__extension__ static __inline uint16x1_t __attribute__ ((__always_inline__)) -vsqaddh_u16 (uint16x1_t __a, int16x1_t __b) +__extension__ static __inline uint16_t __attribute__ ((__always_inline__)) +vsqaddh_u16 (uint16_t __a, int16_t __b) { - return (uint16x1_t) __builtin_aarch64_usqaddhi ((int16x1_t) __a, __b); + return (uint16_t) __builtin_aarch64_usqaddhi ((int16_t) __a, __b); } -__extension__ static __inline uint32x1_t __attribute__ ((__always_inline__)) -vsqadds_u32 (uint32x1_t __a, int32x1_t __b) +__extension__ static __inline uint32_t __attribute__ ((__always_inline__)) +vsqadds_u32 (uint32_t __a, int32_t __b) { - return (uint32x1_t) __builtin_aarch64_usqaddsi ((int32x1_t) __a, __b); + return (uint32_t) __builtin_aarch64_usqaddsi ((int32_t) __a, __b); } __extension__ static __inline uint64x1_t __attribute__ ((__always_inline__)) @@ -25251,22 +25245,22 @@ vuqaddq_s64 (int64x2_t __a, uint64x2_t __b) return (int64x2_t) __builtin_aarch64_suqaddv2di (__a, (int64x2_t) __b); } -__extension__ static __inline int8x1_t __attribute__ ((__always_inline__)) -vuqaddb_s8 (int8x1_t __a, uint8x1_t __b) +__extension__ static __inline int8_t __attribute__ ((__always_inline__)) +vuqaddb_s8 (int8_t __a, uint8_t __b) { - return (int8x1_t) __builtin_aarch64_suqaddqi (__a, (int8x1_t) __b); + return (int8_t) __builtin_aarch64_suqaddqi (__a, (int8_t) __b); } -__extension__ static __inline int16x1_t __attribute__ ((__always_inline__)) -vuqaddh_s16 (int16x1_t __a, uint16x1_t __b) +__extension__ static __inline int16_t __attribute__ ((__always_inline__)) +vuqaddh_s16 (int16_t __a, uint16_t __b) { - return (int16x1_t) __builtin_aarch64_suqaddhi (__a, (int16x1_t) __b); + return (int16_t) __builtin_aarch64_suqaddhi (__a, (int16_t) __b); } -__extension__ static __inline int32x1_t __attribute__ ((__always_inline__)) -vuqadds_s32 (int32x1_t __a, uint32x1_t __b) +__extension__ static __inline int32_t __attribute__ ((__always_inline__)) +vuqadds_s32 (int32_t __a, uint32_t __b) { - return (int32x1_t) __builtin_aarch64_suqaddsi (__a, (int32x1_t) __b); + return (int32_t) __builtin_aarch64_suqaddsi (__a, (int32_t) __b); } __extension__ static __inline int64x1_t __attribute__ ((__always_inline__)) diff --git a/gcc-4.9/gcc/config/alpha/alpha.c b/gcc-4.9/gcc/config/alpha/alpha.c index d5c7908be..19ae3665a 100644 --- a/gcc-4.9/gcc/config/alpha/alpha.c +++ b/gcc-4.9/gcc/config/alpha/alpha.c @@ -9918,12 +9918,6 @@ alpha_canonicalize_comparison (int *code, rtx *op0, rtx *op1, #undef TARGET_EXPAND_BUILTIN_VA_START #define TARGET_EXPAND_BUILTIN_VA_START alpha_va_start -/* The Alpha architecture does not require sequential consistency. See - http://www.cs.umd.edu/~pugh/java/memoryModel/AlphaReordering.html - for an example of how it can be violated in practice. */ -#undef TARGET_RELAXED_ORDERING -#define TARGET_RELAXED_ORDERING true - #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE alpha_option_override diff --git a/gcc-4.9/gcc/config/alpha/alpha.md b/gcc-4.9/gcc/config/alpha/alpha.md index 795b4df3f..1179d572d 100644 --- a/gcc-4.9/gcc/config/alpha/alpha.md +++ b/gcc-4.9/gcc/config/alpha/alpha.md @@ -5984,16 +5984,38 @@ [(set_attr "type" "jsr") (set_attr "length" "*,*,8")]) -(define_insn_and_split "call_value_osf_tlsgd" +(define_int_iterator TLS_CALL + [UNSPEC_TLSGD_CALL + UNSPEC_TLSLDM_CALL]) + +(define_int_attr tls + [(UNSPEC_TLSGD_CALL "tlsgd") + (UNSPEC_TLSLDM_CALL "tlsldm")]) + +(define_insn "call_value_osf_" [(set (match_operand 0) (call (mem:DI (match_operand:DI 1 "symbolic_operand")) (const_int 0))) - (unspec [(match_operand:DI 2 "const_int_operand")] UNSPEC_TLSGD_CALL) + (unspec [(match_operand:DI 2 "const_int_operand")] TLS_CALL) (use (reg:DI 29)) (clobber (reg:DI 26))] "HAVE_AS_TLS" - "#" - "&& reload_completed" + "ldq $27,%1($29)\t\t!literal!%2\;jsr $26,($27),%1\t\t!lituse_!%2\;ldah $29,0($26)\t\t!gpdisp!%*\;lda $29,0($29)\t\t!gpdisp!%*" + [(set_attr "type" "jsr") + (set_attr "length" "16")]) + +;; We must use peep2 instead of a split because we need accurate life +;; information for $gp. +(define_peephole2 + [(parallel + [(set (match_operand 0) + (call (mem:DI (match_operand:DI 1 "symbolic_operand")) + (const_int 0))) + (unspec [(match_operand:DI 2 "const_int_operand")] TLS_CALL) + (use (reg:DI 29)) + (clobber (reg:DI 26))])] + "HAVE_AS_TLS && reload_completed + && peep2_regno_dead_p (1, 29)" [(set (match_dup 3) (unspec:DI [(match_dup 5) (match_dup 1) @@ -6001,10 +6023,9 @@ (parallel [(set (match_dup 0) (call (mem:DI (match_dup 3)) (const_int 0))) - (set (match_dup 5) - (unspec:DI [(match_dup 5) (match_dup 4)] UNSPEC_LDGP1)) + (use (match_dup 5)) (use (match_dup 1)) - (use (unspec [(match_dup 2)] UNSPEC_TLSGD_CALL)) + (use (unspec [(match_dup 2)] TLS_CALL)) (clobber (reg:DI 26))]) (set (match_dup 5) (unspec:DI [(match_dup 5) (match_dup 4)] UNSPEC_LDGP2))] @@ -6012,19 +6033,18 @@ operands[3] = gen_rtx_REG (Pmode, 27); operands[4] = GEN_INT (alpha_next_sequence_number++); operands[5] = pic_offset_table_rtx; -} - [(set_attr "type" "multi")]) +}) -(define_insn_and_split "call_value_osf_tlsldm" - [(set (match_operand 0) - (call (mem:DI (match_operand:DI 1 "symbolic_operand")) - (const_int 0))) - (unspec [(match_operand:DI 2 "const_int_operand")] UNSPEC_TLSLDM_CALL) - (use (reg:DI 29)) - (clobber (reg:DI 26))] - "HAVE_AS_TLS" - "#" - "&& reload_completed" +(define_peephole2 + [(parallel + [(set (match_operand 0) + (call (mem:DI (match_operand:DI 1 "symbolic_operand")) + (const_int 0))) + (unspec [(match_operand:DI 2 "const_int_operand")] TLS_CALL) + (use (reg:DI 29)) + (clobber (reg:DI 26))])] + "HAVE_AS_TLS && reload_completed + && !peep2_regno_dead_p (1, 29)" [(set (match_dup 3) (unspec:DI [(match_dup 5) (match_dup 1) @@ -6035,7 +6055,7 @@ (set (match_dup 5) (unspec:DI [(match_dup 5) (match_dup 4)] UNSPEC_LDGP1)) (use (match_dup 1)) - (use (unspec [(match_dup 2)] UNSPEC_TLSLDM_CALL)) + (use (unspec [(match_dup 2)] TLS_CALL)) (clobber (reg:DI 26))]) (set (match_dup 5) (unspec:DI [(match_dup 5) (match_dup 4)] UNSPEC_LDGP2))] @@ -6043,8 +6063,7 @@ operands[3] = gen_rtx_REG (Pmode, 27); operands[4] = GEN_INT (alpha_next_sequence_number++); operands[5] = pic_offset_table_rtx; -} - [(set_attr "type" "multi")]) +}) (define_insn "*call_value_osf_1" [(set (match_operand 0) diff --git a/gcc-4.9/gcc/config/arm/arm-protos.h b/gcc-4.9/gcc/config/arm/arm-protos.h index 13874ee6e..2ac3b3009 100644 --- a/gcc-4.9/gcc/config/arm/arm-protos.h +++ b/gcc-4.9/gcc/config/arm/arm-protos.h @@ -56,6 +56,7 @@ extern int arm_split_constant (RTX_CODE, enum machine_mode, rtx, extern int legitimate_pic_operand_p (rtx); extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); extern rtx legitimize_tls_address (rtx, rtx); +extern bool arm_legitimate_address_p (enum machine_mode, rtx, bool); extern int arm_legitimate_address_outer_p (enum machine_mode, rtx, RTX_CODE, int); extern int thumb_legitimate_offset_p (enum machine_mode, HOST_WIDE_INT); extern bool arm_legitimize_reload_address (rtx *, enum machine_mode, int, int, @@ -294,4 +295,6 @@ extern void arm_emit_eabi_attribute (const char *, int, int); /* Defined in gcc/common/config/arm-common.c. */ extern const char *arm_rewrite_selected_cpu (const char *name); +extern bool arm_is_constant_pool_ref (rtx); + #endif /* ! GCC_ARM_PROTOS_H */ diff --git a/gcc-4.9/gcc/config/arm/arm.c b/gcc-4.9/gcc/config/arm/arm.c index 3c237cb6d..b79bb48b1 100644 --- a/gcc-4.9/gcc/config/arm/arm.c +++ b/gcc-4.9/gcc/config/arm/arm.c @@ -89,7 +89,6 @@ static rtx arm_legitimize_address (rtx, rtx, enum machine_mode); static reg_class_t arm_preferred_reload_class (rtx, reg_class_t); static rtx thumb_legitimize_address (rtx, rtx, enum machine_mode); inline static int thumb1_index_register_rtx_p (rtx, int); -static bool arm_legitimate_address_p (enum machine_mode, rtx, bool); static int thumb_far_jump_used_p (void); static bool thumb_force_lr_save (void); static unsigned arm_size_return_regs (void); @@ -13952,9 +13951,9 @@ arm_block_move_unaligned_straight (rtx dstbase, rtx srcbase, HOST_WIDE_INT srcoffset, dstoffset; HOST_WIDE_INT src_autoinc, dst_autoinc; rtx mem, addr; - + gcc_assert (1 <= interleave_factor && interleave_factor <= 4); - + /* Use hard registers if we have aligned source or destination so we can use load/store multiple with contiguous registers. */ if (dst_aligned || src_aligned) @@ -13968,7 +13967,7 @@ arm_block_move_unaligned_straight (rtx dstbase, rtx srcbase, src = copy_addr_to_reg (XEXP (srcbase, 0)); srcoffset = dstoffset = 0; - + /* Calls to arm_gen_load_multiple and arm_gen_store_multiple update SRC/DST. For copying the last bytes we want to subtract this offset again. */ src_autoinc = dst_autoinc = 0; @@ -14022,14 +14021,14 @@ arm_block_move_unaligned_straight (rtx dstbase, rtx srcbase, remaining -= block_size_bytes; } - + /* Copy any whole words left (note these aren't interleaved with any subsequent halfword/byte load/stores in the interests of simplicity). */ - + words = remaining / UNITS_PER_WORD; gcc_assert (words < interleave_factor); - + if (src_aligned && words > 1) { emit_insn (arm_gen_load_multiple (regnos, words, src, TRUE, srcbase, @@ -14069,11 +14068,11 @@ arm_block_move_unaligned_straight (rtx dstbase, rtx srcbase, } remaining -= words * UNITS_PER_WORD; - + gcc_assert (remaining < 4); - + /* Copy a halfword if necessary. */ - + if (remaining >= 2) { halfword_tmp = gen_reg_rtx (SImode); @@ -14097,11 +14096,11 @@ arm_block_move_unaligned_straight (rtx dstbase, rtx srcbase, remaining -= 2; srcoffset += 2; } - + gcc_assert (remaining < 2); - + /* Copy last byte. */ - + if ((remaining & 1) != 0) { byte_tmp = gen_reg_rtx (SImode); @@ -14122,9 +14121,9 @@ arm_block_move_unaligned_straight (rtx dstbase, rtx srcbase, remaining--; srcoffset++; } - + /* Store last halfword if we haven't done so already. */ - + if (halfword_tmp) { addr = plus_constant (Pmode, dst, dstoffset - dst_autoinc); @@ -14143,7 +14142,7 @@ arm_block_move_unaligned_straight (rtx dstbase, rtx srcbase, emit_move_insn (mem, gen_lowpart (QImode, byte_tmp)); dstoffset++; } - + gcc_assert (remaining == 0 && srcoffset == dstoffset); } @@ -14162,7 +14161,7 @@ arm_adjust_block_mem (rtx mem, HOST_WIDE_INT length, rtx *loop_reg, rtx *loop_mem) { *loop_reg = copy_addr_to_reg (XEXP (mem, 0)); - + /* Although the new mem does not refer to a known location, it does keep up to LENGTH bytes of alignment. */ *loop_mem = change_address (mem, BLKmode, *loop_reg); @@ -14182,14 +14181,14 @@ arm_block_move_unaligned_loop (rtx dest, rtx src, HOST_WIDE_INT length, { rtx label, src_reg, dest_reg, final_src, test; HOST_WIDE_INT leftover; - + leftover = length % bytes_per_iter; length -= leftover; - + /* Create registers and memory references for use within the loop. */ arm_adjust_block_mem (src, bytes_per_iter, &src_reg, &src); arm_adjust_block_mem (dest, bytes_per_iter, &dest_reg, &dest); - + /* Calculate the value that SRC_REG should have after the last iteration of the loop. */ final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length), @@ -14198,7 +14197,7 @@ arm_block_move_unaligned_loop (rtx dest, rtx src, HOST_WIDE_INT length, /* Emit the start of the loop. */ label = gen_label_rtx (); emit_label (label); - + /* Emit the loop body. */ arm_block_move_unaligned_straight (dest, src, bytes_per_iter, interleave_factor); @@ -14206,11 +14205,11 @@ arm_block_move_unaligned_loop (rtx dest, rtx src, HOST_WIDE_INT length, /* Move on to the next block. */ emit_move_insn (src_reg, plus_constant (Pmode, src_reg, bytes_per_iter)); emit_move_insn (dest_reg, plus_constant (Pmode, dest_reg, bytes_per_iter)); - + /* Emit the loop condition. */ test = gen_rtx_NE (VOIDmode, src_reg, final_src); emit_jump_insn (gen_cbranchsi4 (test, src_reg, final_src, label)); - + /* Mop up any left-over bytes. */ if (leftover) arm_block_move_unaligned_straight (dest, src, leftover, interleave_factor); @@ -14224,7 +14223,7 @@ static int arm_movmemqi_unaligned (rtx *operands) { HOST_WIDE_INT length = INTVAL (operands[2]); - + if (optimize_size) { bool src_aligned = MEM_ALIGN (operands[1]) >= BITS_PER_WORD; @@ -14235,7 +14234,7 @@ arm_movmemqi_unaligned (rtx *operands) resulting code can be smaller. */ unsigned int interleave_factor = (src_aligned || dst_aligned) ? 2 : 1; HOST_WIDE_INT bytes_per_iter = (src_aligned || dst_aligned) ? 8 : 4; - + if (length > 12) arm_block_move_unaligned_loop (operands[0], operands[1], length, interleave_factor, bytes_per_iter); @@ -14253,7 +14252,7 @@ arm_movmemqi_unaligned (rtx *operands) else arm_block_move_unaligned_straight (operands[0], operands[1], length, 4); } - + return 1; } @@ -28520,7 +28519,11 @@ arm_set_return_address (rtx source, rtx scratch) addr = plus_constant (Pmode, addr, delta); } - emit_move_insn (gen_frame_mem (Pmode, addr), source); + /* The store needs to be marked as frame related in order to prevent + DSE from deleting it as dead if it is based on fp. */ + rtx insn = emit_move_insn (gen_frame_mem (Pmode, addr), source); + RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (Pmode, LR_REGNUM)); } } @@ -28572,7 +28575,11 @@ thumb_set_return_address (rtx source, rtx scratch) else addr = plus_constant (Pmode, addr, delta); - emit_move_insn (gen_frame_mem (Pmode, addr), source); + /* The store needs to be marked as frame related in order to prevent + DSE from deleting it as dead if it is based on fp. */ + rtx insn = emit_move_insn (gen_frame_mem (Pmode, addr), source); + RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_CFA_RESTORE, gen_rtx_REG (Pmode, LR_REGNUM)); } else emit_move_insn (gen_rtx_REG (Pmode, LR_REGNUM), source); @@ -29828,10 +29835,10 @@ int vfp3_const_double_for_fract_bits (rtx operand) { REAL_VALUE_TYPE r0; - + if (!CONST_DOUBLE_P (operand)) return 0; - + REAL_VALUE_FROM_CONST_DOUBLE (r0, operand); if (exact_real_inverse (DFmode, &r0)) { @@ -30825,7 +30832,7 @@ arm_autoinc_modes_ok_p (enum machine_mode mode, enum arm_auto_incmodes code) else return false; } - + return true; case ARM_POST_DEC: @@ -30842,10 +30849,10 @@ arm_autoinc_modes_ok_p (enum machine_mode mode, enum arm_auto_incmodes code) return false; return true; - + default: return false; - + } return false; @@ -30856,7 +30863,7 @@ arm_autoinc_modes_ok_p (enum machine_mode mode, enum arm_auto_incmodes code) Additionally, the default expansion code is not available or suitable for post-reload insn splits (this can occur when the register allocator chooses not to do a shift in NEON). - + This function is used in both initial expand and post-reload splits, and handles all kinds of 64-bit shifts. @@ -31109,7 +31116,7 @@ arm_validize_comparison (rtx *comparison, rtx * op1, rtx * op2) { enum rtx_code code = GET_CODE (*comparison); int code_int; - enum machine_mode mode = (GET_MODE (*op1) == VOIDmode) + enum machine_mode mode = (GET_MODE (*op1) == VOIDmode) ? GET_MODE (*op2) : GET_MODE (*op1); gcc_assert (GET_MODE (*op1) != VOIDmode || GET_MODE (*op2) != VOIDmode); @@ -31163,7 +31170,7 @@ arm_asan_shadow_offset (void) /* This is a temporary fix for PR60655. Ideally we need to handle most of these cases in the generic part but - currently we reject minus (..) (sym_ref). We try to + currently we reject minus (..) (sym_ref). We try to ameliorate the case with minus (sym_ref1) (sym_ref2) where they are in the same section. */ @@ -31393,4 +31400,13 @@ arm_load_global_address (rtx symbol, rtx offset_reg, df_insn_rescan (load_insn); } +/* return TRUE if x is a reference to a value in a constant pool */ +extern bool +arm_is_constant_pool_ref (rtx x) +{ + return (MEM_P (x) + && GET_CODE (XEXP (x, 0)) == SYMBOL_REF + && CONSTANT_POOL_ADDRESS_P (XEXP (x, 0))); +} + #include "gt-arm.h" diff --git a/gcc-4.9/gcc/config/arm/arm.h b/gcc-4.9/gcc/config/arm/arm.h index ab5167a8b..433a3dd77 100644 --- a/gcc-4.9/gcc/config/arm/arm.h +++ b/gcc-4.9/gcc/config/arm/arm.h @@ -74,8 +74,8 @@ extern char arm_arch_name[]; builtin_define_with_int_value ( \ "__ARM_SIZEOF_MINIMAL_ENUM", \ flag_short_enums ? 1 : 4); \ - builtin_define_with_int_value ( \ - "__ARM_SIZEOF_WCHAR_T", WCHAR_TYPE_SIZE); \ + builtin_define_type_sizeof ("__ARM_SIZEOF_WCHAR_T", \ + wchar_type_node); \ if (TARGET_ARM_ARCH_PROFILE) \ builtin_define_with_int_value ( \ "__ARM_ARCH_PROFILE", TARGET_ARM_ARCH_PROFILE); \ @@ -2139,9 +2139,10 @@ extern int making_const_table; ? reverse_condition_maybe_unordered (code) \ : reverse_condition (code)) -/* The arm5 clz instruction returns 32. */ -#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1) -#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) ((VALUE) = 32, 1) +#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \ + ((VALUE) = GET_MODE_UNIT_BITSIZE (MODE)) +#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \ + ((VALUE) = GET_MODE_UNIT_BITSIZE (MODE)) #define CC_STATUS_INIT \ do { cfun->machine->thumb1_cc_insn = NULL_RTX; } while (0) diff --git a/gcc-4.9/gcc/config/arm/arm.md b/gcc-4.9/gcc/config/arm/arm.md index 467f9ce4e..1153a1e34 100644 --- a/gcc-4.9/gcc/config/arm/arm.md +++ b/gcc-4.9/gcc/config/arm/arm.md @@ -127,9 +127,10 @@ ; This can be "a" for ARM, "t" for either of the Thumbs, "32" for ; TARGET_32BIT, "t1" or "t2" to specify a specific Thumb mode. "v6" ; for ARM or Thumb-2 with arm_arch6, and nov6 for ARM without -; arm_arch6. This attribute is used to compute attribute "enabled", -; use type "any" to enable an alternative in all cases. -(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2" +; arm_arch6. "v6t2" for Thumb-2 with arm_arch6. This attribute is +; used to compute attribute "enabled", use type "any" to enable an +; alternative in all cases. +(define_attr "arch" "any,a,t,32,t1,t2,v6,nov6,v6t2,neon_for_64bits,avoid_neon_for_64bits,iwmmxt,iwmmxt2" (const_string "any")) (define_attr "arch_enabled" "no,yes" @@ -164,6 +165,10 @@ (match_test "TARGET_32BIT && !arm_arch6")) (const_string "yes") + (and (eq_attr "arch" "v6t2") + (match_test "TARGET_32BIT && arm_arch6 && arm_arch_thumb2")) + (const_string "yes") + (and (eq_attr "arch" "avoid_neon_for_64bits") (match_test "TARGET_NEON") (not (match_test "TARGET_PREFER_NEON_64BITS"))) @@ -3631,7 +3636,7 @@ [(match_operand:SI 1 "s_register_operand" "r") (match_operand:SI 2 "s_register_operand" "r")])) (clobber (reg:CC CC_REGNUM))] - "TARGET_32BIT && optimize_function_for_size_p (cfun)" + "TARGET_32BIT && optimize_function_for_size_p (cfun) && !arm_restrict_it" "* operands[3] = gen_rtx_fmt_ee (minmax_code (operands[3]), SImode, operands[1], operands[2]); @@ -4374,7 +4379,7 @@ (define_insn "unaligned_loadhis" [(set (match_operand:SI 0 "s_register_operand" "=l,r") (sign_extend:SI - (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,m")] + (unspec:HI [(match_operand:HI 1 "memory_operand" "Uw,Uh")] UNSPEC_UNALIGNED_LOAD)))] "unaligned_access && TARGET_32BIT" "ldr%(sh%)\t%0, %1\t@ unaligned" @@ -5287,7 +5292,7 @@ (define_insn "*arm_zero_extendhisi2_v6" [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))] "TARGET_ARM && arm_arch6" "@ uxth%?\\t%0, %1 @@ -5381,7 +5386,7 @@ (define_insn "*arm_zero_extendqisi2_v6" [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))] + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,Uh")))] "TARGET_ARM && arm_arch6" "@ uxtb%(%)\\t%0, %1 @@ -5615,31 +5620,27 @@ (define_insn "*arm_extendhisi2" [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))] "TARGET_ARM && arm_arch4 && !arm_arch6" "@ # ldr%(sh%)\\t%0, %1" [(set_attr "length" "8,4") (set_attr "type" "alu_shift_reg,load_byte") - (set_attr "predicable" "yes") - (set_attr "pool_range" "*,256") - (set_attr "neg_pool_range" "*,244")] + (set_attr "predicable" "yes")] ) ;; ??? Check Thumb-2 pool range (define_insn "*arm_extendhisi2_v6" [(set (match_operand:SI 0 "s_register_operand" "=r,r") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,Uh")))] "TARGET_32BIT && arm_arch6" "@ sxth%?\\t%0, %1 ldr%(sh%)\\t%0, %1" [(set_attr "type" "extend,load_byte") (set_attr "predicable" "yes") - (set_attr "predicable_short_it" "no") - (set_attr "pool_range" "*,256") - (set_attr "neg_pool_range" "*,244")] + (set_attr "predicable_short_it" "no")] ) (define_insn "*arm_extendhisi2addsi" @@ -5682,9 +5683,7 @@ "TARGET_ARM && arm_arch4" "ldr%(sb%)\\t%0, %1" [(set_attr "type" "load_byte") - (set_attr "predicable" "yes") - (set_attr "pool_range" "256") - (set_attr "neg_pool_range" "244")] + (set_attr "predicable" "yes")] ) (define_expand "extendqisi2" @@ -5724,9 +5723,7 @@ ldr%(sb%)\\t%0, %1" [(set_attr "length" "8,4") (set_attr "type" "alu_shift_reg,load_byte") - (set_attr "predicable" "yes") - (set_attr "pool_range" "*,256") - (set_attr "neg_pool_range" "*,244")] + (set_attr "predicable" "yes")] ) (define_insn "*arm_extendqisi_v6" @@ -5738,9 +5735,7 @@ sxtb%?\\t%0, %1 ldr%(sb%)\\t%0, %1" [(set_attr "type" "extend,load_byte") - (set_attr "predicable" "yes") - (set_attr "pool_range" "*,256") - (set_attr "neg_pool_range" "*,244")] + (set_attr "predicable" "yes")] ) (define_insn "*arm_extendqisi2addsi" @@ -6973,8 +6968,8 @@ ;; Pattern to recognize insn generated default case above (define_insn "*movhi_insn_arch4" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r") - (match_operand:HI 1 "general_operand" "rI,K,r,mi"))] + [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,r,m,r") + (match_operand:HI 1 "general_operand" "rI,K,n,r,mi"))] "TARGET_ARM && arm_arch4 && (register_operand (operands[0], HImode) @@ -6982,16 +6977,19 @@ "@ mov%?\\t%0, %1\\t%@ movhi mvn%?\\t%0, #%B1\\t%@ movhi + movw%?\\t%0, %L1\\t%@ movhi str%(h%)\\t%1, %0\\t%@ movhi ldr%(h%)\\t%0, %1\\t%@ movhi" [(set_attr "predicable" "yes") - (set_attr "pool_range" "*,*,*,256") - (set_attr "neg_pool_range" "*,*,*,244") + (set_attr "pool_range" "*,*,*,*,256") + (set_attr "neg_pool_range" "*,*,*,*,244") + (set_attr "arch" "*,*,v6t2,*,*") (set_attr_alternative "type" [(if_then_else (match_operand 1 "const_int_operand" "") (const_string "mov_imm" ) (const_string "mov_reg")) (const_string "mvn_imm") + (const_string "mov_imm") (const_string "store1") (const_string "load1")])] ) @@ -10944,10 +10942,16 @@ enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[5]), operands[3], operands[4]); enum rtx_code rc = GET_CODE (operands[5]); - operands[6] = gen_rtx_REG (mode, CC_REGNUM); gcc_assert (!(mode == CCFPmode || mode == CCFPEmode)); - rc = reverse_condition (rc); + if (REGNO (operands[2]) != REGNO (operands[0])) + rc = reverse_condition (rc); + else + { + rtx tmp = operands[1]; + operands[1] = operands[2]; + operands[2] = tmp; + } operands[6] = gen_rtx_fmt_ee (rc, VOIDmode, operands[6], const0_rtx); } diff --git a/gcc-4.9/gcc/config/arm/constraints.md b/gcc-4.9/gcc/config/arm/constraints.md index 85dd116ce..f848664d5 100644 --- a/gcc-4.9/gcc/config/arm/constraints.md +++ b/gcc-4.9/gcc/config/arm/constraints.md @@ -36,7 +36,7 @@ ;; in Thumb-2 state: Pj, PJ, Ps, Pt, Pu, Pv, Pw, Px, Py ;; The following memory constraints have been used: -;; in ARM/Thumb-2 state: Q, Ut, Uv, Uy, Un, Um, Us +;; in ARM/Thumb-2 state: Q, Uh, Ut, Uv, Uy, Un, Um, Us ;; in ARM state: Uq ;; in Thumb state: Uu, Uw @@ -348,6 +348,12 @@ An address valid for loading/storing register exclusive" (match_operand 0 "mem_noofs_operand")) +(define_memory_constraint "Uh" + "@internal + An address suitable for byte and half-word loads which does not point inside a constant pool" + (and (match_code "mem") + (match_test "arm_legitimate_address_p (GET_MODE (op), XEXP (op, 0), false) && !arm_is_constant_pool_ref (op)"))) + (define_memory_constraint "Ut" "@internal In ARM/Thumb-2 state an address valid for loading/storing opaque structure @@ -394,7 +400,8 @@ (and (match_code "mem") (match_test "TARGET_ARM && arm_legitimate_address_outer_p (GET_MODE (op), XEXP (op, 0), - SIGN_EXTEND, 0)"))) + SIGN_EXTEND, 0) + && !arm_is_constant_pool_ref (op)"))) (define_memory_constraint "Q" "@internal diff --git a/gcc-4.9/gcc/config/arm/linux-grte.h b/gcc-4.9/gcc/config/arm/linux-grte.h index 7ee5806b7..e69de29bb 100644 --- a/gcc-4.9/gcc/config/arm/linux-grte.h +++ b/gcc-4.9/gcc/config/arm/linux-grte.h @@ -1,27 +0,0 @@ -/* Definitions for ARM Linux-based GRTE (Google RunTime Environment). - Copyright (C) 2011 Free Software Foundation, Inc. - Contributed by Chris Demetriou. - -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. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -. */ - -#undef SUBSUBTARGET_EXTRA_SPECS -#define SUBSUBTARGET_EXTRA_SPECS LINUX_GRTE_EXTRA_SPECS diff --git a/gcc-4.9/gcc/config/arm/t-aprofile b/gcc-4.9/gcc/config/arm/t-aprofile index ff9e2e1b3..86741e6b0 100644 --- a/gcc-4.9/gcc/config/arm/t-aprofile +++ b/gcc-4.9/gcc/config/arm/t-aprofile @@ -88,6 +88,9 @@ MULTILIB_MATCHES += march?armv8-a=mcpu?cortex-a53 MULTILIB_MATCHES += march?armv8-a=mcpu?cortex-a57 MULTILIB_MATCHES += march?armv8-a=mcpu?cortex-a57.cortex-a53 +# Arch Matches +MULTILIB_MATCHES += march?armv8-a=march?armv8-a+crc + # FPU matches MULTILIB_MATCHES += mfpu?vfpv3-d16=mfpu?vfpv3 MULTILIB_MATCHES += mfpu?vfpv3-d16=mfpu?vfpv3-fp16 diff --git a/gcc-4.9/gcc/config/avr/avr-dimode.md b/gcc-4.9/gcc/config/avr/avr-dimode.md index 639810518..56cd30458 100644 --- a/gcc-4.9/gcc/config/avr/avr-dimode.md +++ b/gcc-4.9/gcc/config/avr/avr-dimode.md @@ -68,6 +68,7 @@ { rtx acc_a = gen_rtx_REG (mode, ACC_A); + avr_fix_inputs (operands, 1 << 2, regmask (mode, ACC_A)); emit_move_insn (acc_a, operands[1]); if (DImode == mode @@ -145,6 +146,7 @@ { rtx acc_a = gen_rtx_REG (mode, ACC_A); + avr_fix_inputs (operands, 1 << 2, regmask (mode, ACC_A)); emit_move_insn (acc_a, operands[1]); if (const_operand (operands[2], GET_MODE (operands[2]))) @@ -201,6 +203,7 @@ { rtx acc_a = gen_rtx_REG (mode, ACC_A); + avr_fix_inputs (operands, 1 << 2, regmask (mode, ACC_A)); emit_move_insn (acc_a, operands[1]); if (const_operand (operands[2], GET_MODE (operands[2]))) @@ -249,6 +252,7 @@ { rtx acc_a = gen_rtx_REG (mode, ACC_A); + avr_fix_inputs (operands, 1 << 2, regmask (mode, ACC_A)); emit_move_insn (acc_a, operands[1]); if (const_operand (operands[2], GET_MODE (operands[2]))) @@ -338,6 +342,7 @@ { rtx acc_a = gen_rtx_REG (mode, ACC_A); + avr_fix_inputs (operands, 1 << 2, regmask (mode, ACC_A)); emit_move_insn (acc_a, operands[1]); if (s8_operand (operands[2], VOIDmode)) @@ -424,6 +429,7 @@ { rtx acc_a = gen_rtx_REG (mode, ACC_A); + avr_fix_inputs (operands, 1 << 2, regmask (mode, ACC_A)); emit_move_insn (acc_a, operands[1]); emit_move_insn (gen_rtx_REG (QImode, 16), operands[2]); emit_insn (gen_3_insn ()); @@ -457,6 +463,7 @@ (clobber (any_extend:SI (match_dup 1)))])] "avr_have_dimode" { + avr_fix_inputs (operands, 1 << 2, regmask (SImode, 22)); emit_move_insn (gen_rtx_REG (SImode, 22), operands[1]); emit_move_insn (gen_rtx_REG (SImode, 18), operands[2]); emit_insn (gen_mulsidi3_insn()); diff --git a/gcc-4.9/gcc/config/avr/avr-fixed.md b/gcc-4.9/gcc/config/avr/avr-fixed.md index 9c8489edd..6763f596e 100644 --- a/gcc-4.9/gcc/config/avr/avr-fixed.md +++ b/gcc-4.9/gcc/config/avr/avr-fixed.md @@ -231,7 +231,11 @@ (clobber (reg:HI 24))]) (set (match_operand:QQ 0 "register_operand" "") (reg:QQ 23))] - "!AVR_HAVE_MUL") + "!AVR_HAVE_MUL" + { + avr_fix_inputs (operands, 1 << 2, regmask (QQmode, 24)); + }) + (define_expand "muluqq3_nomul" [(set (reg:UQQ 22) @@ -246,7 +250,10 @@ (clobber (reg:HI 22))]) (set (match_operand:UQQ 0 "register_operand" "") (reg:UQQ 25))] - "!AVR_HAVE_MUL") + "!AVR_HAVE_MUL" + { + avr_fix_inputs (operands, 1 << 2, regmask (UQQmode, 22)); + }) (define_insn "*mulqq3.call" [(set (reg:QQ 23) @@ -274,7 +281,10 @@ (clobber (reg:HI 22))]) (set (match_operand:ALL2QA 0 "register_operand" "") (reg:ALL2QA 24))] - "AVR_HAVE_MUL") + "AVR_HAVE_MUL" + { + avr_fix_inputs (operands, 1 << 2, regmask (mode, 18)); + }) ;; "*mulhq3.call" "*muluhq3.call" ;; "*mulha3.call" "*muluha3.call" @@ -302,7 +312,10 @@ (reg:ALL4A 20))) (set (match_operand:ALL4A 0 "register_operand" "") (reg:ALL4A 24))] - "AVR_HAVE_MUL") + "AVR_HAVE_MUL" + { + avr_fix_inputs (operands, 1 << 2, regmask (mode, 16)); + }) ;; "*mulsa3.call" "*mulusa3.call" (define_insn "*mul3.call" @@ -330,7 +343,12 @@ (reg:ALL1Q 22))) (clobber (reg:QI 25))]) (set (match_operand:ALL1Q 0 "register_operand" "") - (reg:ALL1Q 24))]) + (reg:ALL1Q 24))] + "" + { + avr_fix_inputs (operands, 1 << 2, regmask (mode, 25)); + }) + ;; "*divqq3.call" "*udivuqq3.call" (define_insn "*3.call" @@ -356,7 +374,11 @@ (clobber (reg:HI 26)) (clobber (reg:QI 21))]) (set (match_operand:ALL2QA 0 "register_operand" "") - (reg:ALL2QA 24))]) + (reg:ALL2QA 24))] + "" + { + avr_fix_inputs (operands, 1 << 2, regmask (mode, 26)); + }) ;; "*divhq3.call" "*udivuhq3.call" ;; "*divha3.call" "*udivuha3.call" @@ -385,7 +407,11 @@ (clobber (reg:HI 26)) (clobber (reg:HI 30))]) (set (match_operand:ALL4A 0 "register_operand" "") - (reg:ALL4A 22))]) + (reg:ALL4A 22))] + "" + { + avr_fix_inputs (operands, 1 << 2, regmask (mode, 24)); + }) ;; "*divsa3.call" "*udivusa3.call" (define_insn "*3.call" @@ -435,6 +461,7 @@ operands[3] = gen_rtx_REG (mode, regno_out[(size_t) GET_MODE_SIZE (mode)]); operands[4] = gen_rtx_REG (mode, regno_in[(size_t) GET_MODE_SIZE (mode)]); + avr_fix_inputs (operands, 1 << 2, regmask (mode, REGNO (operands[4]))); operands[5] = simplify_gen_subreg (QImode, force_reg (HImode, operands[2]), HImode, 0); // $2 is no more needed, but is referenced for expand. operands[2] = const0_rtx; diff --git a/gcc-4.9/gcc/config/avr/avr-protos.h b/gcc-4.9/gcc/config/avr/avr-protos.h index c5ce78429..4a899a27c 100644 --- a/gcc-4.9/gcc/config/avr/avr-protos.h +++ b/gcc-4.9/gcc/config/avr/avr-protos.h @@ -124,6 +124,15 @@ extern bool avr_mem_memx_p (rtx); extern bool avr_load_libgcc_p (rtx); extern bool avr_xload_libgcc_p (enum machine_mode); +static inline unsigned +regmask (enum machine_mode mode, unsigned regno) +{ + return ((1u << GET_MODE_SIZE (mode)) - 1) << regno; +} + +extern void avr_fix_inputs (rtx*, unsigned, unsigned); +extern bool avr_emit3_fix_outputs (rtx (*)(rtx,rtx,rtx), rtx*, unsigned, unsigned); + extern rtx lpm_reg_rtx; extern rtx lpm_addr_reg_rtx; extern rtx tmp_reg_rtx; diff --git a/gcc-4.9/gcc/config/avr/avr.c b/gcc-4.9/gcc/config/avr/avr.c index fa979df46..4c65f5efa 100644 --- a/gcc-4.9/gcc/config/avr/avr.c +++ b/gcc-4.9/gcc/config/avr/avr.c @@ -11118,6 +11118,115 @@ avr_convert_to_type (tree type, tree expr) } +/* PR63633: The middle-end might come up with hard regs as input operands. + + RMASK is a bit mask representing a subset of hard registers R0...R31: + Rn is an element of that set iff bit n of RMASK is set. + OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then + OP[n] has to be fixed; otherwise OP[n] is left alone. + + For each element of OPMASK which is a hard register overlapping RMASK, + replace OP[n] with a newly created pseudo register + + HREG == 0: Also emit a move insn that copies the contents of that + hard register into the new pseudo. + + HREG != 0: Also set HREG[n] to the hard register. */ + +static void +avr_fix_operands (rtx *op, rtx *hreg, unsigned opmask, unsigned rmask) +{ + for (; opmask; opmask >>= 1, op++) + { + rtx reg = *op; + + if (hreg) + *hreg = NULL_RTX; + + if ((opmask & 1) + && REG_P (reg) + && REGNO (reg) < FIRST_PSEUDO_REGISTER + // This hard-reg overlaps other prohibited hard regs? + && (rmask & regmask (GET_MODE (reg), REGNO (reg)))) + { + *op = gen_reg_rtx (GET_MODE (reg)); + if (hreg == NULL) + emit_move_insn (*op, reg); + else + *hreg = reg; + } + + if (hreg) + hreg++; + } +} + + +void +avr_fix_inputs (rtx *op, unsigned opmask, unsigned rmask) +{ + avr_fix_operands (op, NULL, opmask, rmask); +} + + +/* Helper for the function below: If bit n of MASK is set and + HREG[n] != NULL, then emit a move insn to copy OP[n] to HREG[n]. + Otherwise do nothing for that n. Return TRUE. */ + +static bool +avr_move_fixed_operands (rtx *op, rtx *hreg, unsigned mask) +{ + for (; mask; mask >>= 1, op++, hreg++) + if ((mask & 1) + && *hreg) + emit_move_insn (*hreg, *op); + + return true; +} + + +/* PR63633: The middle-end might come up with hard regs as output operands. + + GEN is a sequence generating function like gen_mulsi3 with 3 operands OP[]. + RMASK is a bit mask representing a subset of hard registers R0...R31: + Rn is an element of that set iff bit n of RMASK is set. + OPMASK describes a subset of OP[]: If bit n of OPMASK is 1 then + OP[n] has to be fixed; otherwise OP[n] is left alone. + + Emit the insn sequence as generated by GEN() with all elements of OPMASK + which are hard registers overlapping RMASK replaced by newly created + pseudo registers. After the sequence has been emitted, emit insns that + move the contents of respective pseudos to their hard regs. */ + +bool +avr_emit3_fix_outputs (rtx (*gen)(rtx,rtx,rtx), rtx *op, + unsigned opmask, unsigned rmask) +{ + const int n = 3; + rtx hreg[n]; + + /* It is legitimate for GEN to call this function, and in order not to + get self-recursive we use the following static kludge. This is the + only way not to duplicate all expanders and to avoid ugly and + hard-to-maintain C-code instead of the much more appreciated RTL + representation as supplied by define_expand. */ + static bool lock = false; + + gcc_assert (opmask < (1u << n)); + + if (lock) + return false; + + avr_fix_operands (op, hreg, opmask, rmask); + + lock = true; + emit_insn (gen (op[0], op[1], op[2])); + lock = false; + + return avr_move_fixed_operands (op, hreg, opmask); +} + + /* Worker function for movmemhi expander. XOP[0] Destination as MEM:BLK XOP[1] Source " " diff --git a/gcc-4.9/gcc/config/avr/avr.md b/gcc-4.9/gcc/config/avr/avr.md index 3bb2a914a..3f4181dab 100644 --- a/gcc-4.9/gcc/config/avr/avr.md +++ b/gcc-4.9/gcc/config/avr/avr.md @@ -1482,7 +1482,11 @@ (set (reg:QI 22) (match_operand:QI 2 "register_operand" "")) (parallel [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22))) (clobber (reg:QI 22))]) - (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))]) + (set (match_operand:QI 0 "register_operand" "") (reg:QI 24))] + "" + { + avr_fix_inputs (operands, 1 << 2, regmask (QImode, 24)); + }) (define_insn "*mulqi3_call" [(set (reg:QI 24) (mult:QI (reg:QI 24) (reg:QI 22))) @@ -2210,7 +2214,13 @@ (parallel [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22))) (clobber (reg:HI 22)) (clobber (reg:QI 21))]) - (set (match_operand:HI 0 "register_operand" "") (reg:HI 24))]) + (set (match_operand:HI 0 "register_operand" "") + (reg:HI 24))] + "" + { + avr_fix_inputs (operands, (1 << 2), regmask (HImode, 24)); + }) + (define_insn "*mulhi3_call" [(set (reg:HI 24) (mult:HI (reg:HI 24) (reg:HI 22))) @@ -2248,6 +2258,10 @@ emit_insn (gen_mulohisi3 (operands[0], operands[2], operands[1])); DONE; } + + if (avr_emit3_fix_outputs (gen_mulsi3, operands, 1 << 0, + regmask (DImode, 18) | regmask (HImode, 26))) + DONE; }) (define_insn_and_split "*mulsi3" @@ -2287,7 +2301,23 @@ ;; "muluqisi3" ;; "muluhisi3" -(define_insn_and_split "mulusi3" +(define_expand "mulusi3" + [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") + (mult:SI (zero_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "")) + (match_operand:SI 2 "pseudo_register_or_const_int_operand" ""))) + (clobber (reg:HI 26)) + (clobber (reg:DI 18))])] + "AVR_HAVE_MUL" + { + avr_fix_inputs (operands, (1 << 1) | (1 << 2), -1u); + if (avr_emit3_fix_outputs (gen_mulusi3, operands, 1 << 0, + regmask (DImode, 18) | regmask (HImode, 26))) + DONE; + }) + +;; "*muluqisi3" +;; "*muluhisi3" +(define_insn_and_split "*mulusi3" [(set (match_operand:SI 0 "pseudo_register_operand" "=r") (mult:SI (zero_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r")) (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn"))) @@ -2323,7 +2353,23 @@ ;; "mulsqisi3" ;; "mulshisi3" -(define_insn_and_split "mulssi3" +(define_expand "mulssi3" + [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") + (mult:SI (sign_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "")) + (match_operand:SI 2 "pseudo_register_or_const_int_operand" ""))) + (clobber (reg:HI 26)) + (clobber (reg:DI 18))])] + "AVR_HAVE_MUL" + { + avr_fix_inputs (operands, (1 << 1) | (1 << 2), -1u); + if (avr_emit3_fix_outputs (gen_mulssi3, operands, 1 << 0, + regmask (DImode, 18) | regmask (HImode, 26))) + DONE; + }) + +;; "*mulsqisi3" +;; "*mulshisi3" +(define_insn_and_split "*mulssi3" [(set (match_operand:SI 0 "pseudo_register_operand" "=r") (mult:SI (sign_extend:SI (match_operand:QIHI 1 "pseudo_register_operand" "r")) (match_operand:SI 2 "pseudo_register_or_const_int_operand" "rn"))) @@ -2366,7 +2412,22 @@ ;; One-extend operand 1 -(define_insn_and_split "mulohisi3" +(define_expand "mulohisi3" + [(parallel [(set (match_operand:SI 0 "pseudo_register_operand" "") + (mult:SI (not:SI (zero_extend:SI + (not:HI (match_operand:HI 1 "pseudo_register_operand" "")))) + (match_operand:SI 2 "pseudo_register_or_const_int_operand" ""))) + (clobber (reg:HI 26)) + (clobber (reg:DI 18))])] + "AVR_HAVE_MUL" + { + avr_fix_inputs (operands, (1 << 1) | (1 << 2), -1u); + if (avr_emit3_fix_outputs (gen_mulohisi3, operands, 1 << 0, + regmask (DImode, 18) | regmask (HImode, 26))) + DONE; + }) + +(define_insn_and_split "*mulohisi3" [(set (match_operand:SI 0 "pseudo_register_operand" "=r") (mult:SI (not:SI (zero_extend:SI (not:HI (match_operand:HI 1 "pseudo_register_operand" "r")))) @@ -2394,7 +2455,12 @@ (any_extend:SI (match_operand:HI 2 "register_operand" "")))) (clobber (reg:HI 26)) (clobber (reg:DI 18))])] - "AVR_HAVE_MUL") + "AVR_HAVE_MUL" + { + if (avr_emit3_fix_outputs (gen_mulhisi3, operands, 1 << 0, + regmask (DImode, 18) | regmask (HImode, 26))) + DONE; + }) (define_expand "usmulhisi3" [(parallel [(set (match_operand:SI 0 "register_operand" "") @@ -2402,7 +2468,12 @@ (sign_extend:SI (match_operand:HI 2 "register_operand" "")))) (clobber (reg:HI 26)) (clobber (reg:DI 18))])] - "AVR_HAVE_MUL") + "AVR_HAVE_MUL" + { + if (avr_emit3_fix_outputs (gen_usmulhisi3, operands, 1 << 0, + regmask (DImode, 18) | regmask (HImode, 26))) + DONE; + }) ;; "*uumulqihisi3" "*uumulhiqisi3" "*uumulhihisi3" "*uumulqiqisi3" ;; "*usmulqihisi3" "*usmulhiqisi3" "*usmulhihisi3" "*usmulqiqisi3" @@ -2474,7 +2545,10 @@ (clobber (reg:HI 22))]) (set (match_operand:HI 0 "register_operand" "") (reg:HI 24))] - "AVR_HAVE_MUL") + "AVR_HAVE_MUL" + { + avr_fix_inputs (operands, 1 << 2, regmask (HImode, 18)); + }) (define_insn "*mulsi3_call" @@ -2697,6 +2771,10 @@ emit_insn (gen_mulsqipsi3 (operands[0], reg, operands[1])); DONE; } + + if (avr_emit3_fix_outputs (gen_mulpsi3, operands, 1u << 0, + regmask (DImode, 18) | regmask (HImode, 26))) + DONE; }) (define_insn "*umulqihipsi3" @@ -2729,7 +2807,21 @@ [(set_attr "length" "7") (set_attr "cc" "clobber")]) -(define_insn_and_split "mulsqipsi3" +(define_expand "mulsqipsi3" + [(parallel [(set (match_operand:PSI 0 "pseudo_register_operand" "") + (mult:PSI (sign_extend:PSI (match_operand:QI 1 "pseudo_register_operand" "")) + (match_operand:PSI 2 "pseudo_register_or_const_int_operand"""))) + (clobber (reg:HI 26)) + (clobber (reg:DI 18))])] + "AVR_HAVE_MUL" + { + avr_fix_inputs (operands, (1 << 1) | (1 << 2), -1u); + if (avr_emit3_fix_outputs (gen_mulsqipsi3, operands, 1 << 0, + regmask (DImode, 18) | regmask (HImode, 26))) + DONE; + }) + +(define_insn_and_split "*mulsqipsi3" [(set (match_operand:PSI 0 "pseudo_register_operand" "=r") (mult:PSI (sign_extend:PSI (match_operand:QI 1 "pseudo_register_operand" "r")) (match_operand:PSI 2 "pseudo_register_or_const_int_operand" "rn"))) @@ -4931,8 +5023,9 @@ (unspec:HI [(match_operand:HI 0 "register_operand" "!z,*r,z")] UNSPEC_INDEX_JMP)) (use (label_ref (match_operand 1 "" ""))) - (clobber (match_dup 0))] - "" + (clobber (match_dup 0)) + (clobber (const_int 0))] + "!AVR_HAVE_EIJMP_EICALL" "@ ijmp push %A0\;push %B0\;ret @@ -4941,6 +5034,19 @@ (set_attr "isa" "rjmp,rjmp,jmp") (set_attr "cc" "none,none,clobber")]) +(define_insn "*tablejump.3byte-pc" + [(set (pc) + (unspec:HI [(reg:HI REG_Z)] + UNSPEC_INDEX_JMP)) + (use (label_ref (match_operand 0 "" ""))) + (clobber (reg:HI REG_Z)) + (clobber (reg:QI 24))] + "AVR_HAVE_EIJMP_EICALL" + "clr r24\;subi r30,pm_lo8(-(%0))\;sbci r31,pm_hi8(-(%0))\;sbci r24,pm_hh8(-(%0))\;jmp __tablejump2__" + [(set_attr "length" "6") + (set_attr "isa" "eijmp") + (set_attr "cc" "clobber")]) + (define_expand "casesi" [(parallel [(set (match_dup 6) @@ -4958,15 +5064,31 @@ (label_ref (match_operand 4 "" "")) (pc))) - (set (match_dup 6) - (plus:HI (match_dup 6) (label_ref (match_operand:HI 3 "" "")))) + (set (match_dup 10) + (match_dup 7)) - (parallel [(set (pc) (unspec:HI [(match_dup 6)] UNSPEC_INDEX_JMP)) + (parallel [(set (pc) + (unspec:HI [(match_dup 10)] UNSPEC_INDEX_JMP)) (use (label_ref (match_dup 3))) - (clobber (match_dup 6))])] + (clobber (match_dup 10)) + (clobber (match_dup 8))])] "" { operands[6] = gen_reg_rtx (HImode); + + if (AVR_HAVE_EIJMP_EICALL) + { + operands[7] = operands[6]; + operands[8] = all_regs_rtx[24]; + operands[10] = gen_rtx_REG (HImode, REG_Z); + } + else + { + operands[7] = gen_rtx_PLUS (HImode, operands[6], + gen_rtx_LABEL_REF (VOIDmode, operands[3])); + operands[8] = const0_rtx; + operands[10] = operands[6]; + } }) @@ -6034,6 +6156,7 @@ emit_insn (gen_fmul_insn (operand0, operand1, operand2)); DONE; } + avr_fix_inputs (operands, 1 << 2, regmask (QImode, 24)); }) (define_insn "fmul_insn" @@ -6077,6 +6200,7 @@ emit_insn (gen_fmuls_insn (operand0, operand1, operand2)); DONE; } + avr_fix_inputs (operands, 1 << 2, regmask (QImode, 24)); }) (define_insn "fmuls_insn" @@ -6120,6 +6244,7 @@ emit_insn (gen_fmulsu_insn (operand0, operand1, operand2)); DONE; } + avr_fix_inputs (operands, 1 << 2, regmask (QImode, 24)); }) (define_insn "fmulsu_insn" diff --git a/gcc-4.9/gcc/config/darwin-c.c b/gcc-4.9/gcc/config/darwin-c.c index 892ba3547..7fe4b1f2e 100644 --- a/gcc-4.9/gcc/config/darwin-c.c +++ b/gcc-4.9/gcc/config/darwin-c.c @@ -571,21 +571,34 @@ find_subframework_header (cpp_reader *pfile, const char *header, cpp_dir **dirp) } /* Return the value of darwin_macosx_version_min suitable for the - __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro, - so '10.4.2' becomes 1040. The lowest digit is always zero. + __ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__ macro, so '10.4.2' + becomes 1040 and '10.10.0' becomes 101000. The lowest digit is + always zero, as is the second lowest for '10.10.x' and above. Print a warning if the version number can't be understood. */ static const char * version_as_macro (void) { - static char result[] = "1000"; + static char result[7] = "1000"; + int minorDigitIdx; if (strncmp (darwin_macosx_version_min, "10.", 3) != 0) goto fail; if (! ISDIGIT (darwin_macosx_version_min[3])) goto fail; - result[2] = darwin_macosx_version_min[3]; - if (darwin_macosx_version_min[4] != '\0' - && darwin_macosx_version_min[4] != '.') + + minorDigitIdx = 3; + result[2] = darwin_macosx_version_min[minorDigitIdx++]; + if (ISDIGIT (darwin_macosx_version_min[minorDigitIdx])) + { + /* Starting with OS X 10.10, the macro ends '00' rather than '0', + i.e. 10.10.x becomes 101000 rather than 10100. */ + result[3] = darwin_macosx_version_min[minorDigitIdx++]; + result[4] = '0'; + result[5] = '0'; + result[6] = '\0'; + } + if (darwin_macosx_version_min[minorDigitIdx] != '\0' + && darwin_macosx_version_min[minorDigitIdx] != '.') goto fail; return result; diff --git a/gcc-4.9/gcc/config/darwin-driver.c b/gcc-4.9/gcc/config/darwin-driver.c index 8b6ae9391..541e10bc0 100644 --- a/gcc-4.9/gcc/config/darwin-driver.c +++ b/gcc-4.9/gcc/config/darwin-driver.c @@ -29,8 +29,8 @@ along with GCC; see the file COPYING3. If not see #include #include "xregex.h" -static bool -darwin_find_version_from_kernel (char *new_flag) +static char * +darwin_find_version_from_kernel (void) { char osversion[32]; size_t osversion_len = sizeof (osversion) - 1; @@ -39,6 +39,7 @@ darwin_find_version_from_kernel (char *new_flag) char minor_vers[6]; char * version_p; char * version_pend; + char * new_flag; /* Determine the version of the running OS. If we can't, warn user, and do nothing. */ @@ -46,7 +47,7 @@ darwin_find_version_from_kernel (char *new_flag) &osversion_len, NULL, 0) == -1) { warning (0, "sysctl for kern.osversion failed: %m"); - return false; + return NULL; } /* Try to parse the first two parts of the OS version number. Warn @@ -57,8 +58,6 @@ darwin_find_version_from_kernel (char *new_flag) version_p = osversion + 1; if (ISDIGIT (*version_p)) major_vers = major_vers * 10 + (*version_p++ - '0'); - if (major_vers > 4 + 9) - goto parse_failed; if (*version_p++ != '.') goto parse_failed; version_pend = strchr(version_p, '.'); @@ -74,17 +73,16 @@ darwin_find_version_from_kernel (char *new_flag) if (major_vers - 4 <= 4) /* On 10.4 and earlier, the old linker is used which does not support three-component system versions. */ - sprintf (new_flag, "10.%d", major_vers - 4); + asprintf (&new_flag, "10.%d", major_vers - 4); else - sprintf (new_flag, "10.%d.%s", major_vers - 4, - minor_vers); + asprintf (&new_flag, "10.%d.%s", major_vers - 4, minor_vers); - return true; + return new_flag; parse_failed: warning (0, "couldn%'t understand kern.osversion %q.*s", (int) osversion_len, osversion); - return false; + return NULL; } #endif @@ -105,7 +103,7 @@ darwin_default_min_version (unsigned int *decoded_options_count, const unsigned int argc = *decoded_options_count; struct cl_decoded_option *const argv = *decoded_options; unsigned int i; - static char new_flag[sizeof ("10.0.0") + 6]; + const char *new_flag; /* If the command-line is empty, just return. */ if (argc <= 1) @@ -142,16 +140,16 @@ darwin_default_min_version (unsigned int *decoded_options_count, #ifndef CROSS_DIRECTORY_STRUCTURE - /* Try to find the version from the kernel, if we fail - we print a message - and give up. */ - if (!darwin_find_version_from_kernel (new_flag)) - return; + /* Try to find the version from the kernel, if we fail - we print a message + and give up. */ + new_flag = darwin_find_version_from_kernel (); + if (!new_flag) + return; #else - /* For cross-compilers, default to the target OS version. */ - - strncpy (new_flag, DEF_MIN_OSX_VERSION, sizeof (new_flag)); + /* For cross-compilers, default to the target OS version. */ + new_flag = DEF_MIN_OSX_VERSION; #endif /* CROSS_DIRECTORY_STRUCTURE */ @@ -165,7 +163,6 @@ darwin_default_min_version (unsigned int *decoded_options_count, memcpy (*decoded_options + 2, argv + 1, (argc - 1) * sizeof (struct cl_decoded_option)); return; - } /* Translate -filelist and -framework options in *DECODED_OPTIONS diff --git a/gcc-4.9/gcc/config/gnu-user.h b/gcc-4.9/gcc/config/gnu-user.h index 2af0a54ed..1a9a487a8 100644 --- a/gcc-4.9/gcc/config/gnu-user.h +++ b/gcc-4.9/gcc/config/gnu-user.h @@ -118,7 +118,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see /* Link -lasan early on the command line. For -static-libasan, don't link it for -shared link, the executable should be compiled with -static-libasan in that case, and for executable link link with --{,no-}whole-archive around - it to force everything into the executable. And similarly for -ltsan. */ + it to force everything into the executable. And similarly for -ltsan + and -llsan. */ #if defined(HAVE_LD_STATIC_DYNAMIC) #undef LIBASAN_EARLY_SPEC #define LIBASAN_EARLY_SPEC "%{!shared:libasan_preinit%O%s} " \ @@ -129,4 +130,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define LIBTSAN_EARLY_SPEC "%{static-libtsan:%{!shared:" \ LD_STATIC_OPTION " --whole-archive -ltsan --no-whole-archive " \ LD_DYNAMIC_OPTION "}}%{!static-libtsan:-ltsan}" +#undef LIBLSAN_EARLY_SPEC +#define LIBLSAN_EARLY_SPEC "%{static-liblsan:%{!shared:" \ + LD_STATIC_OPTION " --whole-archive -llsan --no-whole-archive " \ + LD_DYNAMIC_OPTION "}}%{!static-liblsan:-llsan}" #endif diff --git a/gcc-4.9/gcc/config/i386/i386.c b/gcc-4.9/gcc/config/i386/i386.c index a598b8eef..54942d520 100644 --- a/gcc-4.9/gcc/config/i386/i386.c +++ b/gcc-4.9/gcc/config/i386/i386.c @@ -2465,7 +2465,7 @@ struct ptt const int align_func; }; -/* This table must be in sync with enum processor_type in i386.h. */ +/* This table must be in sync with enum processor_type in i386.h. */ static const struct ptt processor_target_table[PROCESSOR_max] = { {"generic", &generic_cost, 16, 10, 16, 10, 16}, @@ -3257,14 +3257,14 @@ ix86_option_override_internal (bool main_args_p, | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_FMA4 | PTA_XOP | PTA_LWP | PTA_BMI | PTA_TBM | PTA_F16C - | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE + | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE}, {"bdver4", PROCESSOR_BDVER4, CPU_BDVER4, PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3 | PTA_SSE4A | PTA_CX16 | PTA_ABM | PTA_SSSE3 | PTA_SSE4_1 - | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2 - | PTA_FMA4 | PTA_XOP | PTA_LWP | PTA_BMI | PTA_BMI2 - | PTA_TBM | PTA_F16C | PTA_FMA | PTA_PRFCHW | PTA_FXSR + | PTA_SSE4_2 | PTA_AES | PTA_PCLMUL | PTA_AVX | PTA_AVX2 + | PTA_FMA4 | PTA_XOP | PTA_LWP | PTA_BMI | PTA_BMI2 + | PTA_TBM | PTA_F16C | PTA_FMA | PTA_PRFCHW | PTA_FXSR | PTA_XSAVE | PTA_XSAVEOPT | PTA_FSGSBASE | PTA_RDRND | PTA_MOVBE}, {"btver1", PROCESSOR_BTVER1, CPU_GENERIC, @@ -3334,8 +3334,9 @@ ix86_option_override_internal (bool main_args_p, /* When TARGET_BI_ARCH == 2, by default, OPTION_MASK_ABI_X32 is on and OPTION_MASK_ABI_64 is off. We turn off OPTION_MASK_ABI_X32 if OPTION_MASK_ABI_64 is turned on by - -m64. */ - if (TARGET_LP64_P (opts->x_ix86_isa_flags)) + -m64 or OPTION_MASK_CODE16 is turned on by -m16. */ + if (TARGET_LP64_P (opts->x_ix86_isa_flags) + || TARGET_16BIT_P (opts->x_ix86_isa_flags)) opts->x_ix86_isa_flags &= ~OPTION_MASK_ABI_X32; #endif } @@ -3846,11 +3847,30 @@ ix86_option_override_internal (bool main_args_p, opts->x_target_flags |= MASK_NO_RED_ZONE; } + if (!global_options_set.x_flag_shrink_wrap_frame_pointer) + flag_shrink_wrap_frame_pointer = 1; + + /* -fshrink-wrap-frame-pointer is an optimization based on + -fno-omit-frame-pointer mode, so it is only effective when + flag_omit_frame_pointer is false. + Frame pointer shrinkwrap may increase code size, so disable + it when optimize_size is true. */ + if (flag_omit_frame_pointer + || optimize == 0 + || optimize_size) + flag_shrink_wrap_frame_pointer = 0; + + /* If only no -mno-omit-leaf-frame-pointer is explicitly specified, + -fshrink_wrap_frame_pointer will enable omitting leaf frame + pointer by default. */ + if (flag_shrink_wrap_frame_pointer + && !(TARGET_OMIT_LEAF_FRAME_POINTER_P (opts_set->x_target_flags) + && !TARGET_OMIT_LEAF_FRAME_POINTER_P (opts->x_target_flags))) + opts->x_target_flags |= MASK_OMIT_LEAF_FRAME_POINTER; + /* Keep nonleaf frame pointers. */ if (opts->x_flag_omit_frame_pointer) opts->x_target_flags &= ~MASK_OMIT_LEAF_FRAME_POINTER; - else if (TARGET_OMIT_LEAF_FRAME_POINTER_P (opts->x_target_flags)) - opts->x_flag_omit_frame_pointer = 1; /* If we're doing fast math, we don't care about comparison order wrt NaNs. This lets us use a shorter comparison sequence. */ @@ -3969,7 +3989,7 @@ ix86_option_override_internal (bool main_args_p, /* For all chips supporting SSE2, -mfpmath=sse performs better than fpmath=387. The second is however default at many targets since the extra 80bit precision of temporaries is considered to be part of ABI. - Overwrite the default at least for -ffast-math. + Overwrite the default at least for -ffast-math. TODO: -mfpmath=both seems to produce same performing code with bit smaller binaries. It is however not clear if register allocation is ready for this setting. @@ -4291,7 +4311,7 @@ ix86_conditional_register_usage (void) c_mask = (TARGET_64BIT_MS_ABI ? (1 << 3) : TARGET_64BIT ? (1 << 2) : (1 << 1)); - + CLEAR_HARD_REG_SET (reg_class_contents[(int)CLOBBERED_REGS]); for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) @@ -4840,9 +4860,9 @@ ix86_valid_target_attribute_p (tree fndecl, tree old_optimize = build_optimization_node (&global_options); - /* Get the optimization options of the current function. */ + /* Get the optimization options of the current function. */ tree func_optimize = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (fndecl); - + if (!func_optimize) func_optimize = old_optimize; @@ -4850,7 +4870,7 @@ ix86_valid_target_attribute_p (tree fndecl, memset (&func_options, 0, sizeof (func_options)); init_options_struct (&func_options, NULL); lang_hooks.init_options_struct (&func_options); - + cl_optimization_restore (&func_options, TREE_OPTIMIZATION (func_optimize)); @@ -5007,6 +5027,10 @@ ix86_in_large_data_p (tree exp) if (TREE_CODE (exp) == FUNCTION_DECL) return false; + /* Automatic variables are never large data. */ + if (TREE_CODE (exp) == VAR_DECL && !is_global_var (exp)) + return false; + if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp)) { const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp)); @@ -5040,8 +5064,7 @@ ATTRIBUTE_UNUSED static section * x86_64_elf_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align) { - if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC) - && ix86_in_large_data_p (decl)) + if (ix86_in_large_data_p (decl)) { const char *sname = NULL; unsigned int flags = SECTION_WRITE; @@ -5127,8 +5150,7 @@ x86_64_elf_section_type_flags (tree decl, const char *name, int reloc) static void ATTRIBUTE_UNUSED x86_64_elf_unique_section (tree decl, int reloc) { - if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC) - && ix86_in_large_data_p (decl)) + if (ix86_in_large_data_p (decl)) { const char *prefix = NULL; /* We only need to use .gnu.linkonce if we don't have COMDAT groups. */ @@ -5197,7 +5219,7 @@ x86_elf_aligned_common (FILE *file, { if ((ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_MEDIUM_PIC) && size > (unsigned int)ix86_section_threshold) - fputs (".largecomm\t", file); + fputs ("\t.largecomm\t", file); else fputs (COMMON_ASM_OP, file); assemble_name (file, name); @@ -5976,7 +5998,18 @@ ix86_function_type_abi (const_tree fntype) if (abi == SYSV_ABI) { if (lookup_attribute ("ms_abi", TYPE_ATTRIBUTES (fntype))) - abi = MS_ABI; + { + if (TARGET_X32) + { + static bool warned = false; + if (!warned) + { + error ("X32 does not support ms_abi attribute"); + warned = true; + } + } + abi = MS_ABI; + } } else if (lookup_attribute ("sysv_abi", TYPE_ATTRIBUTES (fntype))) abi = SYSV_ABI; @@ -6212,7 +6245,7 @@ init_cumulative_args (CUMULATIVE_ARGS *cum, /* Argument info to initialize */ The midde-end can't deal with the vector types > 16 bytes. In this case, we return the original mode and warn ABI change if CUM isn't - NULL. + NULL. If INT_RETURN is true, warn ABI change if the vector mode isn't available for function return value. */ @@ -9083,20 +9116,22 @@ ix86_frame_pointer_required (void) if (TARGET_64BIT_MS_ABI && get_frame_size () > SEH_MAX_FRAME_SIZE) return true; - /* In ix86_option_override_internal, TARGET_OMIT_LEAF_FRAME_POINTER - turns off the frame pointer by default. Turn it back on now if - we've not got a leaf function. */ - if (TARGET_OMIT_LEAF_FRAME_POINTER - && (!crtl->is_leaf - || ix86_current_function_calls_tls_descriptor)) - return true; - if (crtl->profile && !flag_fentry) return true; return false; } +/* Return true if the frame pointer of the function could be omitted. */ + +static bool +ix86_can_omit_leaf_frame_pointer (void) +{ + return TARGET_OMIT_LEAF_FRAME_POINTER + && (crtl->is_leaf + && !ix86_current_function_calls_tls_descriptor); +} + /* Record that the current function accesses previous call frames. */ void @@ -9569,7 +9604,7 @@ ix86_compute_frame_layout (struct ix86_frame *frame) offset += UNITS_PER_WORD; /* Skip saved base pointer. */ - if (frame_pointer_needed) + if (frame_pointer_needed || frame_pointer_partially_needed) offset += UNITS_PER_WORD; frame->hfp_save_offset = offset; @@ -10890,6 +10925,26 @@ ix86_expand_prologue (void) m->fs.fp_valid = true; } } + else if (frame_pointer_partially_needed) + { + insn = emit_insn (gen_push (hard_frame_pointer_rtx)); + RTX_FRAME_RELATED_P (insn) = 1; + if (fpset_needed_in_prologue) + { + insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); + /* Using sp as cfa_reg will involve more .cfi_def_cfa_offset for + pushes in prologue, so use fp as cfa_reg to reduce .eh_frame + size when possible. */ + if (!any_fp_def) + { + RTX_FRAME_RELATED_P (insn) = 1; + if (m->fs.cfa_reg == stack_pointer_rtx) + m->fs.cfa_reg = hard_frame_pointer_rtx; + m->fs.fp_offset = m->fs.sp_offset; + m->fs.fp_valid = true; + } + } + } if (!int_registers_saved) { @@ -11067,6 +11122,10 @@ ix86_expand_prologue (void) if (sp_is_cfa_reg) m->fs.cfa_offset += UNITS_PER_WORD; RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_FRAME_RELATED_EXPR, + gen_rtx_SET (VOIDmode, stack_pointer_rtx, + plus_constant (Pmode, stack_pointer_rtx, + -UNITS_PER_WORD))); } } @@ -11080,6 +11139,10 @@ ix86_expand_prologue (void) if (sp_is_cfa_reg) m->fs.cfa_offset += UNITS_PER_WORD; RTX_FRAME_RELATED_P (insn) = 1; + add_reg_note (insn, REG_FRAME_RELATED_EXPR, + gen_rtx_SET (VOIDmode, stack_pointer_rtx, + plus_constant (Pmode, stack_pointer_rtx, + -UNITS_PER_WORD))); } } @@ -11231,6 +11294,34 @@ ix86_expand_prologue (void) emit_insn (gen_prologue_use (stack_pointer_rtx)); } +/* Get frame pointer setting insn based on frame state. */ +static rtx +ix86_set_fp_insn () +{ + rtx r, seq; + struct ix86_frame frame; + HOST_WIDE_INT offset; + + ix86_compute_frame_layout (&frame); + gcc_assert (frame_pointer_partially_needed); + offset = frame.stack_pointer_offset - frame.hard_frame_pointer_offset; + + if (TARGET_64BIT && (offset > 0x7fffffff)) + { + r = gen_rtx_SET (DImode, hard_frame_pointer_rtx, GEN_INT (offset)); + emit_insn (r); + r = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, stack_pointer_rtx); + r = gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx, r); + } + else + { + r = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (offset)); + r = gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx, r); + } + emit_insn (r); + return r; +} + /* Emit code to restore REG using a POP insn. */ static void @@ -11415,7 +11506,11 @@ ix86_expand_epilogue (int style) || m->fs.sp_offset == frame.stack_pointer_offset); /* The FP must be valid if the frame pointer is present. */ - gcc_assert (frame_pointer_needed == m->fs.fp_valid); + if (!frame_pointer_partially_needed) + gcc_assert (frame_pointer_needed == m->fs.fp_valid); + else + gcc_assert (!(any_fp_def && m->fs.fp_valid)); + gcc_assert (!m->fs.fp_valid || m->fs.fp_offset == frame.hard_frame_pointer_offset); @@ -11619,7 +11714,7 @@ ix86_expand_epilogue (int style) /* If we used a stack pointer and haven't already got rid of it, then do so now. */ - if (m->fs.fp_valid) + if (m->fs.fp_valid || frame_pointer_partially_needed) { /* If the stack pointer is valid and pointing at the frame pointer store address, then we only need a pop. */ @@ -11627,15 +11722,20 @@ ix86_expand_epilogue (int style) ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx); /* Leave results in shorter dependency chains on CPUs that are able to grok it fast. */ - else if (TARGET_USE_LEAVE - || optimize_bb_for_size_p (EXIT_BLOCK_PTR_FOR_FN (cfun)) - || !cfun->machine->use_fast_prologue_epilogue) + else if (m->fs.fp_valid + && (TARGET_USE_LEAVE + || optimize_function_for_size_p (cfun) + || !cfun->machine->use_fast_prologue_epilogue)) ix86_emit_leave (); else { + rtx dest, offset; + dest = (m->fs.fp_valid) ? hard_frame_pointer_rtx : stack_pointer_rtx; + offset = (m->fs.fp_valid) ? const0_rtx : + GEN_INT (m->fs.sp_offset - frame.hfp_save_offset); pro_epilogue_adjust_stack (stack_pointer_rtx, - hard_frame_pointer_rtx, - const0_rtx, style, !using_drap); + dest, + offset, style, !using_drap); ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx); } } @@ -11947,7 +12047,7 @@ ix86_output_function_nops_prologue_epilogue (FILE *file, fprintf (file, "\n"); /* Switching back to text section. */ - switch_to_section (function_section (current_function_decl)); + switch_to_section (current_function_section ()); return true; } @@ -12379,7 +12479,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out) addr = XEXP (addr, 0); if (CONST_INT_P (addr)) return 0; - } + } else if (GET_CODE (addr) == AND && const_32bit_mask (XEXP (addr, 1), DImode)) { @@ -12905,8 +13005,16 @@ legitimate_pic_address_disp_p (rtx disp) return true; } else if (!SYMBOL_REF_FAR_ADDR_P (op0) - && (SYMBOL_REF_LOCAL_P (op0) - || (TARGET_64BIT && ix86_pie_copyrelocs && flag_pie + && (SYMBOL_REF_LOCAL_P (op0) + || (HAVE_LD_PIE_COPYRELOC + && flag_pie + && !(SYMBOL_REF_WEAK (op0) + /* TODO:Temporary fix for weak defined symbols. Weak defined + symbols in an executable cannot be overridden even with + a non-weak symbol in a shared library. + Revert after fix is checked in here: + http://gcc.gnu.org/ml/gcc-patches/2015-02/msg00366.html*/ + && SYMBOL_REF_EXTERNAL_P (op0)) && !SYMBOL_REF_FUNCTION_P (op0))) && ix86_cmodel != CM_LARGE_PIC) return true; @@ -13010,7 +13118,7 @@ ix86_legitimize_reload_address (rtx x, (reg:DI 2 cx)) This RTX is rejected from ix86_legitimate_address_p due to - non-strictness of base register 97. Following this rejection, + non-strictness of base register 97. Following this rejection, reload pushes all three components into separate registers, creating invalid memory address RTX. @@ -13025,7 +13133,7 @@ ix86_legitimize_reload_address (rtx x, rtx base, index; bool something_reloaded = false; - base = XEXP (XEXP (x, 0), 1); + base = XEXP (XEXP (x, 0), 1); if (!REG_OK_FOR_BASE_STRICT_P (base)) { push_reload (base, NULL_RTX, &XEXP (XEXP (x, 0), 1), NULL, @@ -13929,7 +14037,7 @@ get_dllimport_decl (tree decl, bool beimport) #ifdef SUB_TARGET_RECORD_STUB SUB_TARGET_RECORD_STUB (name); #endif - } + } rtl = gen_const_mem (Pmode, rtl); set_mem_alias_set (rtl, ix86_GOT_alias_set ()); @@ -13976,7 +14084,7 @@ legitimize_dllimport_symbol (rtx symbol, bool want_reg) return x; } -/* Expand SYMBOL into its corresponding dllimport or refptr symbol. WANT_REG +/* Expand SYMBOL into its corresponding dllimport or refptr symbol. WANT_REG is true if we require the result be a register. */ static rtx @@ -14749,7 +14857,7 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse, if (mode == CCmode) suffix = "b"; else if (mode == CCCmode) - suffix = "c"; + suffix = fp ? "b" : "c"; else gcc_unreachable (); break; @@ -14772,9 +14880,9 @@ put_condition_code (enum rtx_code code, enum machine_mode mode, bool reverse, break; case GEU: if (mode == CCmode) - suffix = fp ? "nb" : "ae"; + suffix = "nb"; else if (mode == CCCmode) - suffix = "nc"; + suffix = fp ? "nb" : "nc"; else gcc_unreachable (); break; @@ -15109,7 +15217,7 @@ ix86_print_operand (FILE *file, rtx x, int code) case 2: putc ('w', file); break; - + case 4: putc ('l', file); break; @@ -16408,7 +16516,7 @@ ix86_mode_needed (int entity, rtx insn) } /* Check if a 256bit AVX register is referenced in stores. */ - + static void ix86_check_avx256_stores (rtx dest, const_rtx set ATTRIBUTE_UNUSED, void *data) { @@ -16417,7 +16525,7 @@ ix86_check_avx256_stores (rtx dest, const_rtx set ATTRIBUTE_UNUSED, void *data) bool *used = (bool *) data; *used = true; } - } + } /* Calculate mode of upper 128bit AVX registers after the insn. */ @@ -17463,7 +17571,7 @@ ix86_expand_vector_move_misalign (enum machine_mode mode, rtx operands[]) t = gen_reg_rtx (V4SFmode); else t = op0; - + if (TARGET_SSE_PARTIAL_REG_DEPENDENCY) emit_move_insn (t, CONST0_RTX (V4SFmode)); else @@ -18527,7 +18635,7 @@ ix86_emit_binop (enum rtx_code code, enum machine_mode mode, op = gen_rtx_SET (VOIDmode, dst, gen_rtx_fmt_ee (code, mode, dst, src)); clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, FLAGS_REG)); - + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob))); } @@ -21852,7 +21960,7 @@ ix86_expand_vec_perm (rtx operands[]) if (TARGET_XOP) { - /* The XOP VPPERM insn supports three inputs. By ignoring the + /* The XOP VPPERM insn supports three inputs. By ignoring the one_operand_shuffle special case, we avoid creating another set of constant vectors in memory. */ one_operand_shuffle = false; @@ -23708,7 +23816,7 @@ expand_small_movmem_or_setmem (rtx destmem, rtx srcmem, DONE_LABEL is a label after the whole copying sequence. The label is created on demand if *DONE_LABEL is NULL. MIN_SIZE is minimal size of block copied. This value gets adjusted for new - bounds after the initial copies. + bounds after the initial copies. DESTMEM/SRCMEM are memory expressions pointing to the copies block, DESTPTR/SRCPTR are pointers to the block. DYNAMIC_CHECK indicate whether @@ -24013,7 +24121,7 @@ expand_set_or_movmem_constant_prologue (rtx dst, rtx *srcp, rtx destreg, return dst; } -/* Return true if ALG can be used in current context. +/* Return true if ALG can be used in current context. Assume we expand memset if MEMSET is true. */ static bool alg_usable_p (enum stringop_alg alg, bool memset) @@ -24136,7 +24244,8 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, *noalign = alg_noalign; return alg; } - break; + else if (!any_alg_usable_p) + break; } else if (alg_usable_p (candidate, memset)) { @@ -24174,9 +24283,10 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, alg = decide_alg (count, max / 2, min_size, max_size, memset, zero_memset, dynamic_check, noalign); gcc_assert (*dynamic_check == -1); - gcc_assert (alg != libcall); if (TARGET_INLINE_STRINGOPS_DYNAMICALLY) *dynamic_check = max; + else + gcc_assert (alg != libcall); return alg; } return (alg_usable_p (algs->unknown_size, memset) @@ -24336,7 +24446,7 @@ promote_duplicated_reg_to_size (rtx val, int size_needed, int desired_align, with specified algorithm. 4) Epilogue: code copying tail of the block that is too small to be - handled by main body (or up to size guarded by prologue guard). + handled by main body (or up to size guarded by prologue guard). Misaligned move sequence @@ -24531,7 +24641,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, /* Do the cheap promotion to allow better CSE across the main loop and epilogue (ie one load of the big constant in the - front of all code. + front of all code. For now the misaligned move sequences do not have fast path without broadcasting. */ if (issetmem && ((CONST_INT_P (val_exp) || misaligned_prologue_used))) @@ -25103,13 +25213,19 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, } else { - /* Static functions and indirect calls don't need the pic register. */ + /* Static functions and indirect calls don't need the pic register. Also, + check if PLT was explicitly avoided via no-plt or "noplt" attribute, making + it an indirect call. */ if (flag_pic && (!TARGET_64BIT || (ix86_cmodel == CM_LARGE_PIC && DEFAULT_ABI != MS_ABI)) && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF - && ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0))) + && !SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0)) + && flag_plt + && (SYMBOL_REF_DECL ((XEXP (fnaddr, 0))) == NULL_TREE + || !lookup_attribute ("noplt", + DECL_ATTRIBUTES (SYMBOL_REF_DECL (XEXP (fnaddr, 0)))))) use_reg (&use, pic_offset_table_rtx); } @@ -25173,6 +25289,31 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1, return call; } +/* Return true if the function being called was marked with attribute "noplt" + or using -fno-plt and we are compiling for non-PIC and x86_64. We need to + handle the non-PIC case in the backend because there is no easy interface + for the front-end to force non-PLT calls to use the GOT. This is currently + used only with 64-bit ELF targets to call the function marked "noplt" + indirectly. */ + +static bool +ix86_nopic_noplt_attribute_p (rtx call_op) +{ + if (flag_pic || ix86_cmodel == CM_LARGE + || !TARGET_64BIT || TARGET_MACHO || TARGET_SEH || TARGET_PECOFF + || SYMBOL_REF_LOCAL_P (call_op)) + return false; + + tree symbol_decl = SYMBOL_REF_DECL (call_op); + + if (!flag_plt + || (symbol_decl != NULL_TREE + && lookup_attribute ("noplt", DECL_ATTRIBUTES (symbol_decl)))) + return true; + + return false; +} + /* Output the assembly for a call instruction. */ const char * @@ -25184,7 +25325,9 @@ ix86_output_call_insn (rtx insn, rtx call_op) if (SIBLING_CALL_P (insn)) { - if (direct_p) + if (direct_p && ix86_nopic_noplt_attribute_p (call_op)) + xasm = "jmp\t*%p0@GOTPCREL(%%rip)"; + else if (direct_p) xasm = "jmp\t%P0"; /* SEH epilogue detection requires the indirect branch case to include REX.W. */ @@ -25236,7 +25379,9 @@ ix86_output_call_insn (rtx insn, rtx call_op) seh_nop_p = true; } - if (direct_p) + if (direct_p && ix86_nopic_noplt_attribute_p (call_op)) + xasm = "call\t*%p0@GOTPCREL(%%rip)"; + else if (direct_p) xasm = "call\t%P0"; else xasm = "call\t%A0"; @@ -26506,7 +26651,7 @@ ix86_dependencies_evaluation_hook (rtx head, rtx tail) using topological ordering in the region. */ if (rgn == CONTAINING_RGN (e->src->index) && BLOCK_TO_BB (bb->index) > BLOCK_TO_BB (e->src->index)) - add_dependee_for_func_arg (first_arg, e->src); + add_dependee_for_func_arg (first_arg, e->src); } } insn = first_arg; @@ -26974,7 +27119,7 @@ ix86_local_alignment (tree exp, enum machine_mode mode, other unit can not rely on the alignment. Exclude va_list type. It is the common case of local array where - we can not benefit from the alignment. + we can not benefit from the alignment. TODO: Probably one should optimize for size only when var is not escaping. */ if (TARGET_64BIT && optimize_function_for_speed_p (cfun) @@ -31443,7 +31588,7 @@ add_condition_to_bb (tree function_decl, tree version_decl, convert_expr = build1 (CONVERT_EXPR, ptr_type_node, build_fold_addr_expr (version_decl)); result_var = create_tmp_var (ptr_type_node, NULL); - convert_stmt = gimple_build_assign (result_var, convert_expr); + convert_stmt = gimple_build_assign (result_var, convert_expr); return_stmt = gimple_build_return (result_var); if (predicate_chain == NULL_TREE) @@ -31470,7 +31615,7 @@ add_condition_to_bb (tree function_decl, tree version_decl, gimple_seq_add_stmt (&gseq, call_cond_stmt); predicate_chain = TREE_CHAIN (predicate_chain); - + if (and_expr_var == NULL) and_expr_var = cond_var; else @@ -31511,7 +31656,7 @@ add_condition_to_bb (tree function_decl, tree version_decl, gimple_set_bb (return_stmt, bb2); bb3 = e23->dest; - make_edge (bb1, bb3, EDGE_FALSE_VALUE); + make_edge (bb1, bb3, EDGE_FALSE_VALUE); remove_edge (e23); make_edge (bb2, EXIT_BLOCK_PTR_FOR_FN (cfun), 0); @@ -31563,7 +31708,7 @@ get_builtin_code_for_version (tree decl, tree *predicate_list) P_FMA4, P_XOP, P_PROC_XOP, - P_FMA, + P_FMA, P_PROC_FMA, P_AVX2, P_PROC_AVX2 @@ -31628,11 +31773,11 @@ get_builtin_code_for_version (tree decl, tree *predicate_list) cl_target_option_save (&cur_target, &global_options); target_node = ix86_valid_target_attribute_tree (attrs, &global_options, &global_options_set); - + gcc_assert (target_node); new_target = TREE_TARGET_OPTION (target_node); gcc_assert (new_target); - + if (new_target->arch_specified && new_target->arch > 0) { switch (new_target->arch) @@ -31701,18 +31846,18 @@ get_builtin_code_for_version (tree decl, tree *predicate_list) arg_str = "bdver4"; priority = P_PROC_AVX2; break; - } - } - + } + } + cl_target_option_restore (&global_options, &cur_target); - + if (predicate_list && arg_str == NULL) { error_at (DECL_SOURCE_LOCATION (decl), "No dispatcher found for the versioning attributes"); return 0; } - + if (predicate_list) { predicate_decl = ix86_builtins [(int) IX86_BUILTIN_CPU_IS]; @@ -31779,7 +31924,7 @@ get_builtin_code_for_version (tree decl, tree *predicate_list) *predicate_list = predicate_chain; } - return priority; + return priority; } /* This compares the priority of target features in function DECL1 @@ -31798,7 +31943,7 @@ ix86_compare_version_priority (tree decl1, tree decl2) /* V1 and V2 point to function versions with different priorities based on the target ISA. This function compares their priorities. */ - + static int feature_compare (const void *v1, const void *v2) { @@ -32111,12 +32256,12 @@ ix86_function_versions (tree fn1, tree fn2) result = true; XDELETEVEC (target1); - XDELETEVEC (target2); - + XDELETEVEC (target2); + return result; } -static tree +static tree ix86_mangle_decl_assembler_name (tree decl, tree id) { /* For function version, add the target suffix to the assembler name. */ @@ -32186,7 +32331,7 @@ make_dispatcher_decl (const tree decl) fn_type = TREE_TYPE (decl); func_type = build_function_type (TREE_TYPE (fn_type), TYPE_ARG_TYPES (fn_type)); - + func_decl = build_fn_decl (func_name, func_type); XDELETEVEC (func_name); TREE_USED (func_decl) = 1; @@ -32199,7 +32344,7 @@ make_dispatcher_decl (const tree decl) /* This will be of type IFUNCs have to be externally visible. */ TREE_PUBLIC (func_decl) = 1; - return func_decl; + return func_decl; } #endif @@ -32236,7 +32381,7 @@ ix86_get_function_versions_dispatcher (void *decl) tree dispatch_decl = NULL; struct cgraph_function_version_info *default_version_info = NULL; - + gcc_assert (fn != NULL && DECL_FUNCTION_VERSIONED (fn)); node = cgraph_get_node (fn); @@ -32244,7 +32389,7 @@ ix86_get_function_versions_dispatcher (void *decl) node_v = get_cgraph_node_version (node); gcc_assert (node_v != NULL); - + if (node_v->dispatcher_resolver != NULL) return node_v->dispatcher_resolver; @@ -32409,7 +32554,7 @@ make_resolver_func (const tree default_decl, gcc_assert (dispatch_decl != NULL); /* Mark dispatch_decl as "ifunc" with resolver as resolver_name. */ - DECL_ATTRIBUTES (dispatch_decl) + DECL_ATTRIBUTES (dispatch_decl) = make_attribute ("ifunc", resolver_name, DECL_ATTRIBUTES (dispatch_decl)); /* Create the alias for dispatch to resolver here. */ @@ -32424,7 +32569,7 @@ make_resolver_func (const tree default_decl, provide the code to dispatch the right function at run-time. NODE points to the dispatcher decl whose body will be created. */ -static tree +static tree ix86_generate_version_dispatcher_body (void *node_p) { tree resolver_decl; @@ -32476,7 +32621,7 @@ ix86_generate_version_dispatcher_body (void *node_p) } dispatch_function_versions (resolver_decl, &fn_ver_vec, &empty_bb); - rebuild_cgraph_edges (); + rebuild_cgraph_edges (); pop_cfun (); return resolver_decl; } @@ -32587,7 +32732,7 @@ fold_builtin_cpu (tree fndecl, tree *args) M_AMDFAM15H, M_INTEL_SILVERMONT, M_AMD_BTVER1, - M_AMD_BTVER2, + M_AMD_BTVER2, M_CPU_SUBTYPE_START, M_INTEL_COREI7_NEHALEM, M_INTEL_COREI7_WESTMERE, @@ -32627,13 +32772,13 @@ fold_builtin_cpu (tree fndecl, tree *args) {"barcelona", M_AMDFAM10H_BARCELONA}, {"shanghai", M_AMDFAM10H_SHANGHAI}, {"istanbul", M_AMDFAM10H_ISTANBUL}, - {"btver1", M_AMD_BTVER1}, + {"btver1", M_AMD_BTVER1}, {"amdfam15h", M_AMDFAM15H}, {"bdver1", M_AMDFAM15H_BDVER1}, {"bdver2", M_AMDFAM15H_BDVER2}, {"bdver3", M_AMDFAM15H_BDVER3}, {"bdver4", M_AMDFAM15H_BDVER4}, - {"btver2", M_AMD_BTVER2}, + {"btver2", M_AMD_BTVER2}, }; static struct _isa_names_table @@ -35238,9 +35383,9 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget, { /* Make it call __cpu_indicator_init in libgcc. */ tree call_expr, fndecl, type; - type = build_function_type_list (integer_type_node, NULL_TREE); + type = build_function_type_list (integer_type_node, NULL_TREE); fndecl = build_fn_decl ("__cpu_indicator_init", type); - call_expr = build_call_expr (fndecl, 0); + call_expr = build_call_expr (fndecl, 0); return expand_expr (call_expr, target, mode, EXPAND_NORMAL); } case IX86_BUILTIN_CPU_IS: @@ -41332,8 +41477,8 @@ ix86_encode_section_info (tree decl, rtx rtl, int first) { default_encode_section_info (decl, rtl, first); - if (TREE_CODE (decl) == VAR_DECL - && (TREE_STATIC (decl) || DECL_EXTERNAL (decl)) + if (((TREE_CODE (decl) == VAR_DECL && is_global_var (decl)) + || TREE_CODE(decl) == STRING_CST) && ix86_in_large_data_p (decl)) SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_FAR_ADDR; } @@ -42957,8 +43102,8 @@ expand_vec_perm_pshufb (struct expand_vec_perm_d *d) op0 = gen_lowpart (V4DImode, d->op0); op1 = gen_lowpart (V4DImode, d->op1); rperm[0] - = GEN_INT (((d->perm[0] & (nelt / 2)) ? 1 : 0) - || ((d->perm[nelt / 2] & (nelt / 2)) ? 2 : 0)); + = GEN_INT ((d->perm[0] / (nelt / 2)) + | ((d->perm[nelt / 2] / (nelt / 2)) * 16)); emit_insn (gen_avx2_permv2ti (target, op0, op1, rperm[0])); if (target != d->target) emit_move_insn (d->target, gen_lowpart (d->vmode, target)); @@ -47277,6 +47422,9 @@ adjacent_mem_locations (rtx mem1, rtx mem2) #undef TARGET_PROFILE_BEFORE_PROLOGUE #define TARGET_PROFILE_BEFORE_PROLOGUE ix86_profile_before_prologue +#undef TARGET_SET_FP_INSN +#define TARGET_SET_FP_INSN ix86_set_fp_insn + #undef TARGET_MANGLE_DECL_ASSEMBLER_NAME #define TARGET_MANGLE_DECL_ASSEMBLER_NAME ix86_mangle_decl_assembler_name @@ -47562,6 +47710,9 @@ adjacent_mem_locations (rtx mem1, rtx mem2) #undef TARGET_FRAME_POINTER_REQUIRED #define TARGET_FRAME_POINTER_REQUIRED ix86_frame_pointer_required +#undef TARGET_CAN_OMIT_LEAF_FRAME_POINTER +#define TARGET_CAN_OMIT_LEAF_FRAME_POINTER ix86_can_omit_leaf_frame_pointer + #undef TARGET_CAN_ELIMINATE #define TARGET_CAN_ELIMINATE ix86_can_eliminate @@ -47601,6 +47752,8 @@ adjacent_mem_locations (rtx mem1, rtx mem2) #define TARGET_FLOAT_EXCEPTIONS_ROUNDING_SUPPORTED_P \ ix86_float_exceptions_rounding_supported_p +#undef TARGET_STRICT_ALIGN +#define TARGET_STRICT_ALIGN true struct gcc_target targetm = TARGET_INITIALIZER; #include "gt-i386.h" diff --git a/gcc-4.9/gcc/config/i386/i386.md b/gcc-4.9/gcc/config/i386/i386.md index 39d395875..2369e4b40 100644 --- a/gcc-4.9/gcc/config/i386/i386.md +++ b/gcc-4.9/gcc/config/i386/i386.md @@ -12159,18 +12159,52 @@ (set_attr "mode" "")]) ;; BMI2 instructions. -(define_insn "bmi2_bzhi_3" +(define_expand "bmi2_bzhi_3" + [(parallel + [(set (match_operand:SWI48 0 "register_operand") + (zero_extract:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand") + (umin:SWI48 + (and:SWI48 (match_operand:SWI48 2 "register_operand") + (const_int 255)) + (match_dup 3)) + (const_int 0))) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_BMI2" + "operands[3] = GEN_INT ( * BITS_PER_UNIT);") + +(define_insn "*bmi2_bzhi_3" [(set (match_operand:SWI48 0 "register_operand" "=r") - (and:SWI48 (lshiftrt:SWI48 (const_int -1) - (match_operand:SWI48 2 "register_operand" "r")) - (match_operand:SWI48 1 "nonimmediate_operand" "rm"))) + (zero_extract:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "rm") + (umin:SWI48 + (and:SWI48 (match_operand:SWI48 2 "register_operand" "r") + (const_int 255)) + (match_operand:SWI48 3 "const_int_operand" "n")) + (const_int 0))) (clobber (reg:CC FLAGS_REG))] - "TARGET_BMI2" + "TARGET_BMI2 && INTVAL (operands[3]) == * BITS_PER_UNIT" "bzhi\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "bitmanip") (set_attr "prefix" "vex") (set_attr "mode" "")]) +(define_mode_attr k [(SI "k") (DI "q")]) +(define_insn "*bmi2_bzhi_3_1" + [(set (match_operand:SWI48 0 "register_operand" "=r") + (zero_extract:SWI48 + (match_operand:SWI48 1 "nonimmediate_operand" "rm") + (umin:SWI48 + (zero_extend:SWI48 (match_operand:QI 2 "register_operand" "r")) + (match_operand:SWI48 3 "const_int_operand" "n")) + (const_int 0))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_BMI2 && INTVAL (operands[3]) == * BITS_PER_UNIT" + "bzhi\t{%2, %1, %0|%0, %1, %2}" + [(set_attr "type" "bitmanip") + (set_attr "prefix" "vex") + (set_attr "mode" "")]) + (define_insn "bmi2_pdep_3" [(set (match_operand:SWI48 0 "register_operand" "=r") (unspec:SWI48 [(match_operand:SWI48 1 "register_operand" "r") @@ -13518,7 +13552,8 @@ (set (reg:CCFP FPSR_REG) (unspec:CCFP [(match_dup 2) (match_dup 3)] UNSPEC_C2_FLAG))] - "TARGET_USE_FANCY_MATH_387" + "TARGET_USE_FANCY_MATH_387 + && flag_finite_math_only" "fprem" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) @@ -13527,7 +13562,8 @@ [(use (match_operand:XF 0 "register_operand")) (use (match_operand:XF 1 "general_operand")) (use (match_operand:XF 2 "general_operand"))] - "TARGET_USE_FANCY_MATH_387" + "TARGET_USE_FANCY_MATH_387 + && flag_finite_math_only" { rtx label = gen_label_rtx (); @@ -13550,7 +13586,8 @@ [(use (match_operand:MODEF 0 "register_operand")) (use (match_operand:MODEF 1 "general_operand")) (use (match_operand:MODEF 2 "general_operand"))] - "TARGET_USE_FANCY_MATH_387" + "TARGET_USE_FANCY_MATH_387 + && flag_finite_math_only" { rtx (*gen_truncxf) (rtx, rtx); @@ -13589,7 +13626,8 @@ (set (reg:CCFP FPSR_REG) (unspec:CCFP [(match_dup 2) (match_dup 3)] UNSPEC_C2_FLAG))] - "TARGET_USE_FANCY_MATH_387" + "TARGET_USE_FANCY_MATH_387 + && flag_finite_math_only" "fprem1" [(set_attr "type" "fpspc") (set_attr "mode" "XF")]) @@ -13598,7 +13636,8 @@ [(use (match_operand:XF 0 "register_operand")) (use (match_operand:XF 1 "general_operand")) (use (match_operand:XF 2 "general_operand"))] - "TARGET_USE_FANCY_MATH_387" + "TARGET_USE_FANCY_MATH_387 + && flag_finite_math_only" { rtx label = gen_label_rtx (); @@ -13621,7 +13660,8 @@ [(use (match_operand:MODEF 0 "register_operand")) (use (match_operand:MODEF 1 "general_operand")) (use (match_operand:MODEF 2 "general_operand"))] - "TARGET_USE_FANCY_MATH_387" + "TARGET_USE_FANCY_MATH_387 + && flag_finite_math_only" { rtx (*gen_truncxf) (rtx, rtx); diff --git a/gcc-4.9/gcc/config/i386/i386.opt b/gcc-4.9/gcc/config/i386/i386.opt index 1e00b660e..f64a9e1eb 100644 --- a/gcc-4.9/gcc/config/i386/i386.opt +++ b/gcc-4.9/gcc/config/i386/i386.opt @@ -108,10 +108,6 @@ int x_ix86_dump_tunes TargetSave int x_ix86_force_align_arg_pointer -;; -mcopyrelocs= -TargetSave -int x_ix86_copyrelocs - ;; -mforce-drap= TargetSave int x_ix86_force_drap @@ -295,10 +291,6 @@ mfancy-math-387 Target RejectNegative Report InverseMask(NO_FANCY_MATH_387, USE_FANCY_MATH_387) Save Generate sin, cos, sqrt for FPU -mcopyrelocs -Target Report Var(ix86_pie_copyrelocs) Init(0) -Assume copy relocations support for pie builds. - mforce-drap Target Report Var(ix86_force_drap) Always use Dynamic Realigned Argument Pointer (DRAP) to realign stack diff --git a/gcc-4.9/gcc/config/i386/linux.h b/gcc-4.9/gcc/config/i386/linux.h index 27d68b5db..bfc7746bc 100644 --- a/gcc-4.9/gcc/config/i386/linux.h +++ b/gcc-4.9/gcc/config/i386/linux.h @@ -24,18 +24,3 @@ along with GCC; see the file COPYING3. If not see #define RUNTIME_ROOT_PREFIX "" #endif #define GLIBC_DYNAMIC_LINKER RUNTIME_ROOT_PREFIX "/lib/ld-linux.so.2" - -/* These may be provided by config/linux-grtev*.h. */ -#ifndef LINUX_GRTE_EXTRA_SPECS -#define LINUX_GRTE_EXTRA_SPECS -#endif - -#undef SUBTARGET_EXTRA_SPECS -#ifndef SUBTARGET_EXTRA_SPECS_STR -#define SUBTARGET_EXTRA_SPECS \ - LINUX_GRTE_EXTRA_SPECS -#else -#define SUBTARGET_EXTRA_SPECS \ - LINUX_GRTE_EXTRA_SPECS \ - SUBTARGET_EXTRA_SPECS_STR -#endif diff --git a/gcc-4.9/gcc/config/i386/linux64.h b/gcc-4.9/gcc/config/i386/linux64.h index 5124a341b..b71616fea 100644 --- a/gcc-4.9/gcc/config/i386/linux64.h +++ b/gcc-4.9/gcc/config/i386/linux64.h @@ -34,12 +34,3 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #define GLIBC_DYNAMIC_LINKER64 RUNTIME_ROOT_PREFIX "/lib64/ld-linux-x86-64.so.2" #define GLIBC_DYNAMIC_LINKERX32 RUNTIME_ROOT_PREFIX "/libx32/ld-linux-x32.so.2" -/* These may be provided by config/linux-grtev*.h. */ -#ifndef LINUX_GRTE_EXTRA_SPECS -#define LINUX_GRTE_EXTRA_SPECS -#endif - -#undef SUBTARGET_EXTRA_SPECS -#define SUBTARGET_EXTRA_SPECS \ - LINUX_GRTE_EXTRA_SPECS - diff --git a/gcc-4.9/gcc/config/i386/mmx.md b/gcc-4.9/gcc/config/i386/mmx.md index 214acde23..a7d2a7eec 100644 --- a/gcc-4.9/gcc/config/i386/mmx.md +++ b/gcc-4.9/gcc/config/i386/mmx.md @@ -600,20 +600,25 @@ ;; Avoid combining registers from different units in a single alternative, ;; see comment above inline_secondary_memory_needed function in i386.c (define_insn "*vec_extractv2sf_1" - [(set (match_operand:SF 0 "nonimmediate_operand" "=y,x,y,x,f,r") + [(set (match_operand:SF 0 "nonimmediate_operand" "=y,x,x,y,x,f,r") (vec_select:SF - (match_operand:V2SF 1 "nonimmediate_operand" " 0,0,o,o,o,o") + (match_operand:V2SF 1 "nonimmediate_operand" " 0,x,x,o,o,o,o") (parallel [(const_int 1)])))] "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))" "@ punpckhdq\t%0, %0 - unpckhps\t%0, %0 + %vmovshdup\t{%1, %0|%0, %1} + shufps\t{$0xe5, %1, %0|%0, %1, 0xe5} # # # #" - [(set_attr "type" "mmxcvt,sselog1,mmxmov,ssemov,fmov,imov") - (set_attr "mode" "DI,V4SF,SF,SF,SF,SF")]) + [(set_attr "isa" "*,sse3,noavx,*,*,*,*") + (set_attr "type" "mmxcvt,sse,sseshuf1,mmxmov,ssemov,fmov,imov") + (set_attr "length_immediate" "*,*,1,*,*,*,*") + (set_attr "prefix_rep" "*,1,*,*,*,*,*") + (set_attr "prefix" "orig,maybe_vex,orig,orig,orig,orig,orig") + (set_attr "mode" "DI,V4SF,V4SF,SF,SF,SF,SF")]) (define_split [(set (match_operand:SF 0 "register_operand") @@ -1288,26 +1293,23 @@ ;; Avoid combining registers from different units in a single alternative, ;; see comment above inline_secondary_memory_needed function in i386.c (define_insn "*vec_extractv2si_1" - [(set (match_operand:SI 0 "nonimmediate_operand" "=y,x,x,x,y,x,r") + [(set (match_operand:SI 0 "nonimmediate_operand" "=y,x,x,y,x,r") (vec_select:SI - (match_operand:V2SI 1 "nonimmediate_operand" " 0,0,x,0,o,o,o") + (match_operand:V2SI 1 "nonimmediate_operand" " 0,x,x,o,o,o") (parallel [(const_int 1)])))] "TARGET_MMX && !(MEM_P (operands[0]) && MEM_P (operands[1]))" "@ punpckhdq\t%0, %0 - punpckhdq\t%0, %0 - pshufd\t{$85, %1, %0|%0, %1, 85} - unpckhps\t%0, %0 + %vpshufd\t{$0xe5, %1, %0|%0, %1, 0xe5} + shufps\t{$0xe5, %1, %0|%0, %1, 0xe5} # # #" - [(set (attr "isa") - (if_then_else (eq_attr "alternative" "1,2") - (const_string "sse2") - (const_string "*"))) - (set_attr "type" "mmxcvt,sselog1,sselog1,sselog1,mmxmov,ssemov,imov") - (set_attr "length_immediate" "*,*,1,*,*,*,*") - (set_attr "mode" "DI,TI,TI,V4SF,SI,SI,SI")]) + [(set_attr "isa" "*,sse2,noavx,*,*,*") + (set_attr "type" "mmxcvt,sseshuf1,sseshuf1,mmxmov,ssemov,imov") + (set_attr "length_immediate" "*,1,1,*,*,*") + (set_attr "prefix" "orig,maybe_vex,orig,orig,orig,orig") + (set_attr "mode" "DI,TI,V4SF,SI,SI,SI")]) (define_split [(set (match_operand:SI 0 "register_operand") diff --git a/gcc-4.9/gcc/config/i386/x86-tune.def b/gcc-4.9/gcc/config/i386/x86-tune.def index ddf1d21c9..215c71f4d 100644 --- a/gcc-4.9/gcc/config/i386/x86-tune.def +++ b/gcc-4.9/gcc/config/i386/x86-tune.def @@ -97,25 +97,25 @@ DEF_TUNE (X86_TUNE_MEMORY_MISMATCH_STALL, "memory_mismatch_stall", conditional jump instruction for 32 bit TARGET. FIXME: revisit for generic. */ DEF_TUNE (X86_TUNE_FUSE_CMP_AND_BRANCH_32, "fuse_cmp_and_branch_32", - m_CORE_ALL | m_BDVER) + m_GENERIC | m_CORE_ALL | m_BDVER) /* X86_TUNE_FUSE_CMP_AND_BRANCH_64: Fuse compare with a subsequent conditional jump instruction for TARGET_64BIT. FIXME: revisit for generic. */ DEF_TUNE (X86_TUNE_FUSE_CMP_AND_BRANCH_64, "fuse_cmp_and_branch_64", - m_NEHALEM | m_SANDYBRIDGE | m_HASWELL | m_BDVER) + m_GENERIC | m_NEHALEM | m_SANDYBRIDGE | m_HASWELL | m_BDVER) /* X86_TUNE_FUSE_CMP_AND_BRANCH_SOFLAGS: Fuse compare with a subsequent conditional jump instruction when the condition jump check sign flag (SF) or overflow flag (OF). */ DEF_TUNE (X86_TUNE_FUSE_CMP_AND_BRANCH_SOFLAGS, "fuse_cmp_and_branch_soflags", - m_NEHALEM | m_SANDYBRIDGE | m_HASWELL | m_BDVER) + m_GENERIC | m_NEHALEM | m_SANDYBRIDGE | m_HASWELL | m_BDVER) /* X86_TUNE_FUSE_ALU_AND_BRANCH: Fuse alu with a subsequent conditional jump instruction when the alu instruction produces the CCFLAG consumed by the conditional jump instruction. */ DEF_TUNE (X86_TUNE_FUSE_ALU_AND_BRANCH, "fuse_alu_and_branch", - m_SANDYBRIDGE | m_HASWELL) + m_GENERIC | m_SANDYBRIDGE | m_HASWELL) /* X86_TUNE_REASSOC_INT_TO_PARALLEL: Try to produce parallel computations during reassociation of integer computation. */ diff --git a/gcc-4.9/gcc/config/ia64/ia64.c b/gcc-4.9/gcc/config/ia64/ia64.c index 41adc4adc..4ec3e3abe 100644 --- a/gcc-4.9/gcc/config/ia64/ia64.c +++ b/gcc-4.9/gcc/config/ia64/ia64.c @@ -602,11 +602,6 @@ static const struct attribute_spec ia64_attribute_table[] = #undef TARGET_VECTOR_MODE_SUPPORTED_P #define TARGET_VECTOR_MODE_SUPPORTED_P ia64_vector_mode_supported_p -/* ia64 architecture manual 4.4.7: ... reads, writes, and flushes may occur - in an order different from the specified program order. */ -#undef TARGET_RELAXED_ORDERING -#define TARGET_RELAXED_ORDERING true - #undef TARGET_LEGITIMATE_CONSTANT_P #define TARGET_LEGITIMATE_CONSTANT_P ia64_legitimate_constant_p #undef TARGET_LEGITIMATE_ADDRESS_P diff --git a/gcc-4.9/gcc/config/linux-grte.h b/gcc-4.9/gcc/config/linux-grte.h index 31e8a94ce..e69de29bb 100644 --- a/gcc-4.9/gcc/config/linux-grte.h +++ b/gcc-4.9/gcc/config/linux-grte.h @@ -1,41 +0,0 @@ -/* Definitions for Linux-based GRTE (Google RunTime Environment). - Copyright (C) 2009,2010,2011,2012 Free Software Foundation, Inc. - Contributed by Chris Demetriou and Ollie Wild. - -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. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -. */ - -/* Overrides LIB_SPEC from gnu-user.h. */ -#undef LIB_SPEC -#define LIB_SPEC \ - "%{pthread:-lpthread} \ - %{shared:-lc} \ - %{!shared:%{mieee-fp:-lieee} %{profile:%(libc_p)}%{!profile:%(libc)}}" - -/* When GRTE links statically, it needs its NSS and resolver libraries - linked in as well. Note that when linking statically, these are - enclosed in a group by LINK_GCC_C_SEQUENCE_SPEC. */ -#undef LINUX_GRTE_EXTRA_SPECS -#define LINUX_GRTE_EXTRA_SPECS \ - { "libc", "%{static:%(libc_static);:-lc}" }, \ - { "libc_p", "%{static:%(libc_p_static);:-lc_p}" }, \ - { "libc_static", "-lc -lresolv" }, \ - { "libc_p_static", "-lc_p -lresolv_p" }, diff --git a/gcc-4.9/gcc/config/linux.c b/gcc-4.9/gcc/config/linux.c index 7c3c5a461..cdb2b5bdd 100644 --- a/gcc-4.9/gcc/config/linux.c +++ b/gcc-4.9/gcc/config/linux.c @@ -23,8 +23,6 @@ along with GCC; see the file COPYING3. If not see #include "tm.h" #include "linux-protos.h" -/* Android does not support GNU indirect functions. */ - bool linux_has_ifunc_p (void) { diff --git a/gcc-4.9/gcc/config/msp430/msp430.md b/gcc-4.9/gcc/config/msp430/msp430.md index 5e890eced..3f29d6d62 100644 --- a/gcc-4.9/gcc/config/msp430/msp430.md +++ b/gcc-4.9/gcc/config/msp430/msp430.md @@ -559,7 +559,7 @@ [(set (match_operand:PSI 0 "nonimmediate_operand" "=r") (subreg:PSI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) 0))] "TARGET_LARGE" - "RLAM #4, %0 { RRAM #4, %0" + "RLAM.A #4, %0 { RRAM.A #4, %0" ) ;; Look for cases where integer/pointer conversions are suboptimal due @@ -587,7 +587,7 @@ (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) (const_int 1)))] "TARGET_LARGE" - "RLAM #4, %0 { RRAM #3, %0" + "RLAM.A #4, %0 { RRAM.A #3, %0" ) (define_insn "extend_and_shift2_hipsi2" @@ -595,7 +595,7 @@ (ashift:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0")) (const_int 2)))] "TARGET_LARGE" - "RLAM #4, %0 { RRAM #2, %0" + "RLAM.A #4, %0 { RRAM.A #2, %0" ) ; Nasty - we are sign-extending a 20-bit PSI value in one register into diff --git a/gcc-4.9/gcc/config/nios2/nios2.c b/gcc-4.9/gcc/config/nios2/nios2.c index cdd2e6bc9..047b615ba 100644 --- a/gcc-4.9/gcc/config/nios2/nios2.c +++ b/gcc-4.9/gcc/config/nios2/nios2.c @@ -2135,6 +2135,18 @@ nios2_output_dwarf_dtprel (FILE *file, int size, rtx x) fprintf (file, ")"); } +/* Implemet TARGET_ASM_FILE_END. */ + +static void +nios2_asm_file_end (void) +{ + /* The Nios II Linux stack is mapped non-executable by default, so add a + .note.GNU-stack section for switching to executable stacks only when + trampolines are generated. */ + if (TARGET_LINUX_ABI && trampolines_created) + file_end_indicate_exec_stack (); +} + /* Implement TARGET_ASM_FUNCTION_PROLOGUE. */ static void nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) @@ -3313,6 +3325,9 @@ nios2_merge_decl_attributes (tree olddecl, tree newdecl) #undef TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA #define TARGET_ASM_OUTPUT_ADDR_CONST_EXTRA nios2_output_addr_const_extra +#undef TARGET_ASM_FILE_END +#define TARGET_ASM_FILE_END nios2_asm_file_end + #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE nios2_option_override diff --git a/gcc-4.9/gcc/config/pa/pa.c b/gcc-4.9/gcc/config/pa/pa.c index 5a7598ca7..801982068 100644 --- a/gcc-4.9/gcc/config/pa/pa.c +++ b/gcc-4.9/gcc/config/pa/pa.c @@ -3235,7 +3235,12 @@ pa_assemble_integer (rtx x, unsigned int size, int aligned_p) && aligned_p && function_label_operand (x, VOIDmode)) { - fputs (size == 8? "\t.dword\tP%" : "\t.word\tP%", asm_out_file); + fputs (size == 8? "\t.dword\t" : "\t.word\t", asm_out_file); + + /* We don't want an OPD when generating fast indirect calls. */ + if (!TARGET_FAST_INDIRECT_CALLS) + fputs ("P%", asm_out_file); + output_addr_const (asm_out_file, x); fputc ('\n', asm_out_file); return true; @@ -4203,9 +4208,12 @@ pa_output_function_epilogue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) { last_address = extra_nop ? 4 : 0; insn = get_last_nonnote_insn (); - last_address += INSN_ADDRESSES (INSN_UID (insn)); - if (INSN_P (insn)) - last_address += insn_default_length (insn); + if (insn) + { + last_address += INSN_ADDRESSES (INSN_UID (insn)); + if (INSN_P (insn)) + last_address += insn_default_length (insn); + } last_address = ((last_address + FUNCTION_BOUNDARY / BITS_PER_UNIT - 1) & ~(FUNCTION_BOUNDARY / BITS_PER_UNIT - 1)); } @@ -9308,6 +9316,12 @@ pa_function_value (const_tree valtype, || TREE_CODE (valtype) == COMPLEX_TYPE || TREE_CODE (valtype) == VECTOR_TYPE) { + HOST_WIDE_INT valsize = int_size_in_bytes (valtype); + + /* Handle aggregates that fit exactly in a word or double word. */ + if ((valsize & (UNITS_PER_WORD - 1)) == 0) + return gen_rtx_REG (TYPE_MODE (valtype), 28); + if (TARGET_64BIT) { /* Aggregates with a size less than or equal to 128 bits are @@ -9316,7 +9330,7 @@ pa_function_value (const_tree valtype, memory. */ rtx loc[2]; int i, offset = 0; - int ub = int_size_in_bytes (valtype) <= UNITS_PER_WORD ? 1 : 2; + int ub = valsize <= UNITS_PER_WORD ? 1 : 2; for (i = 0; i < ub; i++) { @@ -9328,7 +9342,7 @@ pa_function_value (const_tree valtype, return gen_rtx_PARALLEL (BLKmode, gen_rtvec_v (ub, loc)); } - else if (int_size_in_bytes (valtype) > UNITS_PER_WORD) + else if (valsize > UNITS_PER_WORD) { /* Aggregates 5 to 8 bytes in size are returned in general registers r28-r29 in the same manner as other non diff --git a/gcc-4.9/gcc/config/pa/pa.md b/gcc-4.9/gcc/config/pa/pa.md index a9421ac2e..43b909e35 100644 --- a/gcc-4.9/gcc/config/pa/pa.md +++ b/gcc-4.9/gcc/config/pa/pa.md @@ -123,7 +123,7 @@ ;; type "binary" insns have two input operands (1,2) and one output (0) (define_attr "type" - "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli,sh_func_adrs,parallel_branch,fpstore_load,store_fpload" + "move,unary,binary,shift,nullshift,compare,load,store,uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,fpload,fpstore,fpalu,fpcc,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,multi,milli,sh_func_adrs,parallel_branch,fpstore_load,store_fpload,trap" (const_string "binary")) (define_attr "pa_combine_type" @@ -166,7 +166,7 @@ ;; For conditional branches. Frame related instructions are not allowed ;; because they confuse the unwind support. (define_attr "in_branch_delay" "false,true" - (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch") + (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch,trap") (eq_attr "length" "4") (not (match_test "RTX_FRAME_RELATED_P (insn)"))) (const_string "true") @@ -175,7 +175,7 @@ ;; Disallow instructions which use the FPU since they will tie up the FPU ;; even if the instruction is nullified. (define_attr "in_nullified_branch_delay" "false,true" - (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,parallel_branch") + (if_then_else (and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,fpcc,fpalu,fpmulsgl,fpmuldbl,fpdivsgl,fpdivdbl,fpsqrtsgl,fpsqrtdbl,parallel_branch,trap") (eq_attr "length" "4") (not (match_test "RTX_FRAME_RELATED_P (insn)"))) (const_string "true") @@ -184,7 +184,7 @@ ;; For calls and millicode calls. Allow unconditional branches in the ;; delay slot. (define_attr "in_call_delay" "false,true" - (cond [(and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch") + (cond [(and (eq_attr "type" "!uncond_branch,branch,cbranch,fbranch,call,sibcall,dyncall,multi,milli,sh_func_adrs,parallel_branch,trap") (eq_attr "length" "4") (not (match_test "RTX_FRAME_RELATED_P (insn)"))) (const_string "true") @@ -5331,6 +5331,15 @@ [(set_attr "type" "binary,binary") (set_attr "length" "4,4")]) +;; Trap instructions. + +(define_insn "trap" + [(trap_if (const_int 1) (const_int 0))] + "" + "{addit|addi,tc},<> 1,%%r0,%%r0" + [(set_attr "type" "trap") + (set_attr "length" "4")]) + ;; Clobbering a "register_operand" instead of a match_scratch ;; in operand3 of millicode calls avoids spilling %r1 and ;; produces better code. @@ -8926,14 +8935,14 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" ;; strength reduction is used. It is actually created when the instruction ;; combination phase combines the special loop test. Since this insn ;; is both a jump insn and has an output, it must deal with its own -;; reloads, hence the `m' constraints. The `!' constraints direct reload +;; reloads, hence the `Q' constraints. The `!' constraints direct reload ;; to not choose the register alternatives in the event a reload is needed. (define_insn "decrement_and_branch_until_zero" [(set (pc) (if_then_else (match_operator 2 "comparison_operator" [(plus:SI - (match_operand:SI 0 "reg_before_reload_operand" "+!r,!*f,*m") + (match_operand:SI 0 "reg_before_reload_operand" "+!r,!*f,*Q") (match_operand:SI 1 "int5_operand" "L,L,L")) (const_int 0)]) (label_ref (match_operand 3 "" "")) @@ -9022,7 +9031,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)]) (label_ref (match_operand 3 "" "")) (pc))) - (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*m,!*q") + (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*Q,!*q") (match_dup 1))] "" "* return pa_output_movb (operands, insn, which_alternative, 0); " @@ -9094,7 +9103,7 @@ add,l %2,%3,%3\;bv,n %%r0(%3)" [(match_operand:SI 1 "register_operand" "r,r,r,r") (const_int 0)]) (pc) (label_ref (match_operand 3 "" "")))) - (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*m,!*q") + (set (match_operand:SI 0 "reg_before_reload_operand" "=!r,!*f,*Q,!*q") (match_dup 1))] "" "* return pa_output_movb (operands, insn, which_alternative, 1); " diff --git a/gcc-4.9/gcc/config/pa/predicates.md b/gcc-4.9/gcc/config/pa/predicates.md index 8dcfce0e9..405cf7f63 100644 --- a/gcc-4.9/gcc/config/pa/predicates.md +++ b/gcc-4.9/gcc/config/pa/predicates.md @@ -528,20 +528,29 @@ ;; This predicate is used for branch patterns that internally handle ;; register reloading. We need to accept non-symbolic memory operands ;; after reload to ensure that the pattern is still valid if reload -;; didn't find a hard register for the operand. +;; didn't find a hard register for the operand. We also reject index +;; and lo_sum DLT address as these are invalid for move destinations. (define_predicate "reg_before_reload_operand" (match_code "reg,mem") { + rtx op0; + if (register_operand (op, mode)) return true; - if (reload_completed - && memory_operand (op, mode) - && !symbolic_memory_operand (op, mode)) - return true; + if (!reload_in_progress && !reload_completed) + return false; - return false; + if (! MEM_P (op)) + return false; + + op0 = XEXP (op, 0); + + return (memory_address_p (mode, op0) + && !IS_INDEX_ADDR_P (op0) + && !IS_LO_SUM_DLT_ADDR_P (op0) + && !symbolic_memory_operand (op, mode)); }) ;; True iff OP is a register or const_0 operand for MODE. diff --git a/gcc-4.9/gcc/config/rs6000/altivec.h b/gcc-4.9/gcc/config/rs6000/altivec.h index 129cf6fa1..9ee0ae5ec 100644 --- a/gcc-4.9/gcc/config/rs6000/altivec.h +++ b/gcc-4.9/gcc/config/rs6000/altivec.h @@ -124,6 +124,7 @@ #define vec_vcfux __builtin_vec_vcfux #define vec_cts __builtin_vec_cts #define vec_ctu __builtin_vec_ctu +#define vec_cpsgn __builtin_vec_copysign #define vec_expte __builtin_vec_expte #define vec_floor __builtin_vec_floor #define vec_loge __builtin_vec_loge @@ -214,8 +215,10 @@ #define vec_lvsl __builtin_vec_lvsl #define vec_lvsr __builtin_vec_lvsr #define vec_max __builtin_vec_max +#define vec_mergee __builtin_vec_vmrgew #define vec_mergeh __builtin_vec_mergeh #define vec_mergel __builtin_vec_mergel +#define vec_mergeo __builtin_vec_vmrgow #define vec_min __builtin_vec_min #define vec_mladd __builtin_vec_mladd #define vec_msum __builtin_vec_msum @@ -319,6 +322,8 @@ #define vec_sqrt __builtin_vec_sqrt #define vec_vsx_ld __builtin_vec_vsx_ld #define vec_vsx_st __builtin_vec_vsx_st +#define vec_xl __builtin_vec_vsx_ld +#define vec_xst __builtin_vec_vsx_st /* Note, xxsldi and xxpermdi were added as __builtin_vsx_ functions instead of __builtin_vec_ */ @@ -336,6 +341,7 @@ #define vec_vadduqm __builtin_vec_vadduqm #define vec_vbpermq __builtin_vec_vbpermq #define vec_vclz __builtin_vec_vclz +#define vec_cntlz __builtin_vec_vclz #define vec_vclzb __builtin_vec_vclzb #define vec_vclzd __builtin_vec_vclzd #define vec_vclzh __builtin_vec_vclzh diff --git a/gcc-4.9/gcc/config/rs6000/altivec.md b/gcc-4.9/gcc/config/rs6000/altivec.md index a8cfcb739..02ea14237 100644 --- a/gcc-4.9/gcc/config/rs6000/altivec.md +++ b/gcc-4.9/gcc/config/rs6000/altivec.md @@ -67,7 +67,7 @@ UNSPEC_VCTSXS UNSPEC_VLOGEFP UNSPEC_VEXPTEFP - UNSPEC_VLSDOI + UNSPEC_VSLDOI UNSPEC_VUNPACK_HI_SIGN UNSPEC_VUNPACK_LO_SIGN UNSPEC_VUNPACK_HI_SIGN_DIRECT @@ -2077,7 +2077,7 @@ (unspec:VM [(match_operand:VM 1 "register_operand" "v") (match_operand:VM 2 "register_operand" "v") (match_operand:QI 3 "immediate_operand" "i")] - UNSPEC_VLSDOI))] + UNSPEC_VSLDOI))] "TARGET_ALTIVEC" "vsldoi %0,%1,%2,%3" [(set_attr "type" "vecperm")]) @@ -2297,7 +2297,31 @@ "dststt %0,%1,%2" [(set_attr "type" "vecsimple")]) -(define_insn "altivec_lvsl" +(define_expand "altivec_lvsl" + [(use (match_operand:V16QI 0 "register_operand" "")) + (use (match_operand:V16QI 1 "memory_operand" ""))] + "TARGET_ALTIVEC" +{ + if (VECTOR_ELT_ORDER_BIG) + emit_insn (gen_altivec_lvsl_direct (operands[0], operands[1])); + else + { + int i; + rtx mask, perm[16], constv, vperm; + mask = gen_reg_rtx (V16QImode); + emit_insn (gen_altivec_lvsl_direct (mask, operands[1])); + for (i = 0; i < 16; ++i) + perm[i] = GEN_INT (i); + constv = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm)); + constv = force_reg (V16QImode, constv); + vperm = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, mask, mask, constv), + UNSPEC_VPERM); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], vperm)); + } + DONE; +}) + +(define_insn "altivec_lvsl_direct" [(set (match_operand:V16QI 0 "register_operand" "=v") (unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "Z")] UNSPEC_LVSL))] @@ -2305,7 +2329,31 @@ "lvsl %0,%y1" [(set_attr "type" "vecload")]) -(define_insn "altivec_lvsr" +(define_expand "altivec_lvsr" + [(use (match_operand:V16QI 0 "register_operand" "")) + (use (match_operand:V16QI 1 "memory_operand" ""))] + "TARGET_ALTIVEC" +{ + if (VECTOR_ELT_ORDER_BIG) + emit_insn (gen_altivec_lvsr_direct (operands[0], operands[1])); + else + { + int i; + rtx mask, perm[16], constv, vperm; + mask = gen_reg_rtx (V16QImode); + emit_insn (gen_altivec_lvsr_direct (mask, operands[1])); + for (i = 0; i < 16; ++i) + perm[i] = GEN_INT (i); + constv = gen_rtx_CONST_VECTOR (V16QImode, gen_rtvec_v (16, perm)); + constv = force_reg (V16QImode, constv); + vperm = gen_rtx_UNSPEC (V16QImode, gen_rtvec (3, mask, mask, constv), + UNSPEC_VPERM); + emit_insn (gen_rtx_SET (VOIDmode, operands[0], vperm)); + } + DONE; +}) + +(define_insn "altivec_lvsr_direct" [(set (match_operand:V16QI 0 "register_operand" "=v") (unspec:V16QI [(match_operand:V16QI 1 "memory_operand" "Z")] UNSPEC_LVSR))] diff --git a/gcc-4.9/gcc/config/rs6000/darwin.h b/gcc-4.9/gcc/config/rs6000/darwin.h index 0329f3f62..dfd181e43 100644 --- a/gcc-4.9/gcc/config/rs6000/darwin.h +++ b/gcc-4.9/gcc/config/rs6000/darwin.h @@ -206,7 +206,11 @@ extern int darwin_emit_branch_islands; "vrsave", "vscr", \ "spe_acc", "spefscr", \ "sfp", \ - "tfhar", "tfiar", "texasr" \ + "tfhar", "tfiar", "texasr", \ + "rh0", "rh1", "rh2", "rh3", "rh4", "rh5", "rh6", "rh7", \ + "rh8", "rh9", "rh10", "rh11", "rh12", "rh13", "rh14", "rh15", \ + "rh16", "rh17", "rh18", "rh19", "rh20", "rh21", "rh22", "rh23", \ + "rh24", "rh25", "rh26", "rh27", "rh28", "rh29", "rh30", "rh31" \ } /* This outputs NAME to FILE. */ diff --git a/gcc-4.9/gcc/config/rs6000/linux-grte.h b/gcc-4.9/gcc/config/rs6000/linux-grte.h index 53997f027..e69de29bb 100644 --- a/gcc-4.9/gcc/config/rs6000/linux-grte.h +++ b/gcc-4.9/gcc/config/rs6000/linux-grte.h @@ -1,41 +0,0 @@ -/* Definitions for Linux-based GRTE (Google RunTime Environment). - Copyright (C) 2009,2010,2011,2012 Free Software Foundation, Inc. - Contributed by Chris Demetriou and Ollie Wild. - -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. - -Under Section 7 of GPL version 3, you are granted additional -permissions described in the GCC Runtime Library Exception, version -3.1, as published by the Free Software Foundation. - -You should have received a copy of the GNU General Public License and -a copy of the GCC Runtime Library Exception along with this program; -see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -. */ - -/* Overrides LIB_LINUX_SPEC from sysv4.h. */ -#undef LIB_LINUX_SPEC -#define LIB_LINUX_SPEC \ - "%{pthread:-lpthread} \ - %{shared:-lc} \ - %{!shared:%{mieee-fp:-lieee} %{profile:%(libc_p)}%{!profile:%(libc)}}" - -/* When GRTE links statically, it needs its NSS and resolver libraries - linked in as well. Note that when linking statically, these are - enclosed in a group by LINK_GCC_C_SEQUENCE_SPEC. */ -#undef LINUX_GRTE_EXTRA_SPECS -#define LINUX_GRTE_EXTRA_SPECS \ - { "libc", "%{static:%(libc_static);:-lc}" }, \ - { "libc_p", "%{static:%(libc_p_static);:-lc_p}" }, \ - { "libc_static", "-lc -lresolv" }, \ - { "libc_p_static", "-lc_p -lresolv_p" }, diff --git a/gcc-4.9/gcc/config/rs6000/predicates.md b/gcc-4.9/gcc/config/rs6000/predicates.md index 8c384b380..2f4046215 100644 --- a/gcc-4.9/gcc/config/rs6000/predicates.md +++ b/gcc-4.9/gcc/config/rs6000/predicates.md @@ -1783,7 +1783,7 @@ (define_predicate "fusion_gpr_mem_load" (match_code "mem,sign_extend,zero_extend") { - rtx addr; + rtx addr, base, offset; /* Handle sign/zero extend. */ if (GET_CODE (op) == ZERO_EXTEND @@ -1813,24 +1813,79 @@ } addr = XEXP (op, 0); + if (GET_CODE (addr) != PLUS && GET_CODE (addr) != LO_SUM) + return 0; + + base = XEXP (addr, 0); + if (!base_reg_operand (base, GET_MODE (base))) + return 0; + + offset = XEXP (addr, 1); + if (GET_CODE (addr) == PLUS) + return satisfies_constraint_I (offset); + + else if (GET_CODE (addr) == LO_SUM) { - rtx base = XEXP (addr, 0); - rtx offset = XEXP (addr, 1); + if (TARGET_XCOFF || (TARGET_ELF && TARGET_POWERPC64)) + return small_toc_ref (offset, GET_MODE (offset)); - return (base_reg_operand (base, GET_MODE (base)) - && satisfies_constraint_I (offset)); + else if (TARGET_ELF && !TARGET_POWERPC64) + return CONSTANT_P (offset); } - else if (GET_CODE (addr) == LO_SUM) + return 0; +}) + +;; Match a GPR load (lbz, lhz, lwz, ld) that uses a combined address in the +;; memory field with both the addis and the memory offset. Sign extension +;; is not handled here, since lha and lwa are not fused. +(define_predicate "fusion_gpr_mem_combo" + (match_code "mem,zero_extend") +{ + rtx addr, base, offset; + + /* Handle zero extend. */ + if (GET_CODE (op) == ZERO_EXTEND) { - rtx base = XEXP (addr, 0); - rtx offset = XEXP (addr, 1); + op = XEXP (op, 0); + mode = GET_MODE (op); + } + + if (!MEM_P (op)) + return 0; - if (!base_reg_operand (base, GET_MODE (base))) + switch (mode) + { + case QImode: + case HImode: + case SImode: + break; + + case DImode: + if (!TARGET_POWERPC64) return 0; + break; - else if (TARGET_XCOFF || (TARGET_ELF && TARGET_POWERPC64)) + default: + return 0; + } + + addr = XEXP (op, 0); + if (GET_CODE (addr) != PLUS && GET_CODE (addr) != LO_SUM) + return 0; + + base = XEXP (addr, 0); + if (!fusion_gpr_addis (base, GET_MODE (base))) + return 0; + + offset = XEXP (addr, 1); + if (GET_CODE (addr) == PLUS) + return satisfies_constraint_I (offset); + + else if (GET_CODE (addr) == LO_SUM) + { + if (TARGET_XCOFF || (TARGET_ELF && TARGET_POWERPC64)) return small_toc_ref (offset, GET_MODE (offset)); else if (TARGET_ELF && !TARGET_POWERPC64) diff --git a/gcc-4.9/gcc/config/rs6000/rs6000-builtin.def b/gcc-4.9/gcc/config/rs6000/rs6000-builtin.def index 220d1e970..9bb870394 100644 --- a/gcc-4.9/gcc/config/rs6000/rs6000-builtin.def +++ b/gcc-4.9/gcc/config/rs6000/rs6000-builtin.def @@ -1258,6 +1258,16 @@ BU_VSX_2 (VEC_MERGEL_V2DF, "mergel_2df", CONST, vsx_mergel_v2df) BU_VSX_2 (VEC_MERGEL_V2DI, "mergel_2di", CONST, vsx_mergel_v2di) BU_VSX_2 (VEC_MERGEH_V2DF, "mergeh_2df", CONST, vsx_mergeh_v2df) BU_VSX_2 (VEC_MERGEH_V2DI, "mergeh_2di", CONST, vsx_mergeh_v2di) +BU_VSX_2 (XXSPLTD_V2DF, "xxspltd_2df", CONST, vsx_xxspltd_v2df) +BU_VSX_2 (XXSPLTD_V2DI, "xxspltd_2di", CONST, vsx_xxspltd_v2di) +BU_VSX_2 (DIV_V2DI, "div_2di", CONST, vsx_div_v2di) +BU_VSX_2 (UDIV_V2DI, "udiv_2di", CONST, vsx_udiv_v2di) +BU_VSX_2 (MUL_V2DI, "mul_2di", CONST, vsx_mul_v2di) + +BU_VSX_2 (XVCVSXDDP_SCALE, "xvcvsxddp_scale", CONST, vsx_xvcvsxddp_scale) +BU_VSX_2 (XVCVUXDDP_SCALE, "xvcvuxddp_scale", CONST, vsx_xvcvuxddp_scale) +BU_VSX_2 (XVCVDPSXDS_SCALE, "xvcvdpsxds_scale", CONST, vsx_xvcvdpsxds_scale) +BU_VSX_2 (XVCVDPUXDS_SCALE, "xvcvdpuxds_scale", CONST, vsx_xvcvdpuxds_scale) /* VSX abs builtin functions. */ BU_VSX_A (XVABSDP, "xvabsdp", CONST, absv2df2) diff --git a/gcc-4.9/gcc/config/rs6000/rs6000-c.c b/gcc-4.9/gcc/config/rs6000/rs6000-c.c index 46c4a9d8c..8dedeec26 100644 --- a/gcc-4.9/gcc/config/rs6000/rs6000-c.c +++ b/gcc-4.9/gcc/config/rs6000/rs6000-c.c @@ -597,6 +597,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 }, { ALTIVEC_BUILTIN_VEC_ROUND, ALTIVEC_BUILTIN_VRFIN, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0, 0 }, + { ALTIVEC_BUILTIN_VEC_ROUND, VSX_BUILTIN_XVRDPI, + RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0, 0 }, { ALTIVEC_BUILTIN_VEC_RECIP, ALTIVEC_BUILTIN_VRECIPFP, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, { ALTIVEC_BUILTIN_VEC_RECIP, VSX_BUILTIN_RECIP_V2DF, @@ -876,6 +878,18 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, 0 }, + { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, + RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, { ALTIVEC_BUILTIN_VEC_AND, ALTIVEC_BUILTIN_VAND, @@ -930,6 +944,18 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, 0 }, + { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, + RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, { ALTIVEC_BUILTIN_VEC_ANDC, ALTIVEC_BUILTIN_VANDC, @@ -1118,18 +1144,30 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V4SF, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, 0 }, { ALTIVEC_BUILTIN_VEC_CTF, ALTIVEC_BUILTIN_VCFSX, RS6000_BTI_V4SF, RS6000_BTI_V4SI, RS6000_BTI_INTSI, 0 }, + { ALTIVEC_BUILTIN_VEC_CTF, VSX_BUILTIN_XVCVSXDDP_SCALE, + RS6000_BTI_V2DF, RS6000_BTI_V2DI, RS6000_BTI_INTSI, 0}, + { ALTIVEC_BUILTIN_VEC_CTF, VSX_BUILTIN_XVCVUXDDP_SCALE, + RS6000_BTI_V2DF, RS6000_BTI_unsigned_V2DI, RS6000_BTI_INTSI, 0}, { ALTIVEC_BUILTIN_VEC_VCFSX, ALTIVEC_BUILTIN_VCFSX, RS6000_BTI_V4SF, RS6000_BTI_V4SI, RS6000_BTI_INTSI, 0 }, { ALTIVEC_BUILTIN_VEC_VCFUX, ALTIVEC_BUILTIN_VCFUX, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, 0 }, { ALTIVEC_BUILTIN_VEC_CTS, ALTIVEC_BUILTIN_VCTSXS, RS6000_BTI_V4SI, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 }, + { ALTIVEC_BUILTIN_VEC_CTS, VSX_BUILTIN_XVCVDPSXDS_SCALE, + RS6000_BTI_V2DI, RS6000_BTI_V2DF, RS6000_BTI_INTSI, 0 }, { ALTIVEC_BUILTIN_VEC_CTU, ALTIVEC_BUILTIN_VCTUXS, RS6000_BTI_unsigned_V4SI, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 }, + { ALTIVEC_BUILTIN_VEC_CTU, VSX_BUILTIN_XVCVDPUXDS_SCALE, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_V2DF, RS6000_BTI_INTSI, 0 }, { VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_XVDIVSP, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, { VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_XVDIVDP, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, + { VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_DIV_V2DI, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 }, + { VSX_BUILTIN_VEC_DIV, VSX_BUILTIN_UDIV_V2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX_V2DF, RS6000_BTI_V2DF, RS6000_BTI_INTSI, ~RS6000_BTI_V2DF, 0 }, { ALTIVEC_BUILTIN_VEC_LD, ALTIVEC_BUILTIN_LVX_V2DI, @@ -1595,6 +1633,16 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, { ALTIVEC_BUILTIN_VEC_MERGEH, VSX_BUILTIN_VEC_MERGEH_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_MERGEH, VSX_BUILTIN_VEC_MERGEH_V2DI, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_MERGEH, VSX_BUILTIN_VEC_MERGEH_V2DI, + RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_MERGEH, VSX_BUILTIN_VEC_MERGEH_V2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_MERGEH, VSX_BUILTIN_VEC_MERGEH_V2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_MERGEH, VSX_BUILTIN_VEC_MERGEH_V2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_VMRGHW, ALTIVEC_BUILTIN_VMRGHW, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, { ALTIVEC_BUILTIN_VEC_VMRGHW, ALTIVEC_BUILTIN_VMRGHW, @@ -1643,6 +1691,16 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, { ALTIVEC_BUILTIN_VEC_MERGEL, VSX_BUILTIN_VEC_MERGEL_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_MERGEL, VSX_BUILTIN_VEC_MERGEL_V2DI, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_MERGEL, VSX_BUILTIN_VEC_MERGEL_V2DI, + RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_MERGEL, VSX_BUILTIN_VEC_MERGEL_V2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_MERGEL, VSX_BUILTIN_VEC_MERGEL_V2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_MERGEL, VSX_BUILTIN_VEC_MERGEL_V2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_VMRGLW, ALTIVEC_BUILTIN_VMRGLW, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, { ALTIVEC_BUILTIN_VEC_VMRGLW, ALTIVEC_BUILTIN_VMRGLW, @@ -1771,6 +1829,10 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, { VSX_BUILTIN_VEC_MUL, VSX_BUILTIN_XVMULDP, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, + { VSX_BUILTIN_VEC_MUL, VSX_BUILTIN_MUL_V2DI, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 }, + { VSX_BUILTIN_VEC_MUL, VSX_BUILTIN_MUL_V2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_MULE, ALTIVEC_BUILTIN_VMULEUB, RS6000_BTI_unsigned_V8HI, RS6000_BTI_unsigned_V16QI, RS6000_BTI_unsigned_V16QI, 0 }, { ALTIVEC_BUILTIN_VEC_MULE, ALTIVEC_BUILTIN_VMULESB, @@ -1811,6 +1873,18 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, 0 }, { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, 0 }, + { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, + RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 }, { ALTIVEC_BUILTIN_VEC_NOR, ALTIVEC_BUILTIN_VNOR, @@ -1841,6 +1915,18 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, 0 }, + { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, + RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, { ALTIVEC_BUILTIN_VEC_OR, ALTIVEC_BUILTIN_VOR, @@ -1945,6 +2031,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_unsigned_V8HI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 }, { ALTIVEC_BUILTIN_VEC_PACKSU, P8V_BUILTIN_VPKSDUS, RS6000_BTI_unsigned_V4SI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_PACKSU, P8V_BUILTIN_VPKSDUS, + RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_VPKSWUS, ALTIVEC_BUILTIN_VPKSWUS, RS6000_BTI_unsigned_V8HI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 }, { ALTIVEC_BUILTIN_VEC_VPKSHUS, ALTIVEC_BUILTIN_VPKSHUS, @@ -2127,6 +2215,14 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_INTSI, 0 }, { ALTIVEC_BUILTIN_VEC_SPLAT, ALTIVEC_BUILTIN_VSPLTW, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_INTSI, 0 }, + { ALTIVEC_BUILTIN_VEC_SPLAT, VSX_BUILTIN_XXSPLTD_V2DF, + RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_INTSI, 0 }, + { ALTIVEC_BUILTIN_VEC_SPLAT, VSX_BUILTIN_XXSPLTD_V2DI, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_INTSI, 0 }, + { ALTIVEC_BUILTIN_VEC_SPLAT, VSX_BUILTIN_XXSPLTD_V2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_INTSI, 0 }, + { ALTIVEC_BUILTIN_VEC_SPLAT, VSX_BUILTIN_XXSPLTD_V2DI, + RS6000_BTI_bool_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_INTSI, 0 }, { ALTIVEC_BUILTIN_VEC_VSPLTW, ALTIVEC_BUILTIN_VSPLTW, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_INTSI, 0 }, { ALTIVEC_BUILTIN_VEC_VSPLTW, ALTIVEC_BUILTIN_VSPLTW, @@ -2518,6 +2614,18 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, RS6000_BTI_V2DF, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DF, 0 }, + { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, + RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, + RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, 0 }, + { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI, RS6000_BTI_unsigned_V2DI, 0 }, { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, { ALTIVEC_BUILTIN_VEC_XOR, ALTIVEC_BUILTIN_VXOR, @@ -2778,6 +2886,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_V2DF, RS6000_BTI_unsigned_V16QI }, { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_unsigned_V16QI }, + { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V16QI }, { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_unsigned_V16QI }, { ALTIVEC_BUILTIN_VEC_PERM, ALTIVEC_BUILTIN_VPERM_4SI, @@ -2818,6 +2928,12 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_unsigned_V2DI }, { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI, RS6000_BTI_V2DI }, + { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI }, + { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI }, + { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_2DI, + RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_V2DI }, { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_V4SF, RS6000_BTI_bool_V4SI }, { ALTIVEC_BUILTIN_VEC_SEL, ALTIVEC_BUILTIN_VSEL_4SF, @@ -3267,6 +3383,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { { VSX_BUILTIN_VEC_LD, VSX_BUILTIN_LXVD2X_V2DF, RS6000_BTI_V2DF, RS6000_BTI_INTSI, ~RS6000_BTI_V2DF, 0 }, + { VSX_BUILTIN_VEC_LD, VSX_BUILTIN_LXVD2X_V2DF, + RS6000_BTI_V2DF, RS6000_BTI_INTSI, ~RS6000_BTI_double, 0 }, { VSX_BUILTIN_VEC_LD, VSX_BUILTIN_LXVD2X_V2DI, RS6000_BTI_V2DI, RS6000_BTI_INTSI, ~RS6000_BTI_V2DI, 0 }, { VSX_BUILTIN_VEC_LD, VSX_BUILTIN_LXVD2X_V2DI, @@ -3321,6 +3439,8 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { { VSX_BUILTIN_VEC_ST, VSX_BUILTIN_STXVD2X_V2DF, RS6000_BTI_void, RS6000_BTI_V2DF, RS6000_BTI_INTSI, ~RS6000_BTI_V2DF }, + { VSX_BUILTIN_VEC_ST, VSX_BUILTIN_STXVD2X_V2DF, + RS6000_BTI_void, RS6000_BTI_V2DF, RS6000_BTI_INTSI, ~RS6000_BTI_double }, { VSX_BUILTIN_VEC_ST, VSX_BUILTIN_STXVD2X_V2DI, RS6000_BTI_void, RS6000_BTI_V2DI, RS6000_BTI_INTSI, ~RS6000_BTI_V2DI }, { VSX_BUILTIN_VEC_ST, VSX_BUILTIN_STXVD2X_V2DI, @@ -3431,6 +3551,18 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SI, RS6000_BTI_bool_V4SI }, { ALTIVEC_BUILTIN_VEC_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTSW_P, RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SI, RS6000_BTI_V4SI }, + { ALTIVEC_BUILTIN_VEC_VCMPGT_P, P8V_BUILTIN_VCMPGTUD_P, + RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V2DI, RS6000_BTI_unsigned_V2DI }, + { ALTIVEC_BUILTIN_VEC_VCMPGT_P, P8V_BUILTIN_VCMPGTUD_P, + RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_bool_V2DI }, + { ALTIVEC_BUILTIN_VEC_VCMPGT_P, P8V_BUILTIN_VCMPGTUD_P, + RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_unsigned_V2DI, RS6000_BTI_unsigned_V2DI }, + { ALTIVEC_BUILTIN_VEC_VCMPGT_P, P8V_BUILTIN_VCMPGTSD_P, + RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_bool_V2DI, RS6000_BTI_V2DI }, + { ALTIVEC_BUILTIN_VEC_VCMPGT_P, P8V_BUILTIN_VCMPGTSD_P, + RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V2DI, RS6000_BTI_bool_V2DI }, + { ALTIVEC_BUILTIN_VEC_VCMPGT_P, P8V_BUILTIN_VCMPGTSD_P, + RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V2DI, RS6000_BTI_V2DI }, { ALTIVEC_BUILTIN_VEC_VCMPGT_P, ALTIVEC_BUILTIN_VCMPGTFP_P, RS6000_BTI_INTSI, RS6000_BTI_INTSI, RS6000_BTI_V4SF, RS6000_BTI_V4SF }, { ALTIVEC_BUILTIN_VEC_VCMPGT_P, VSX_BUILTIN_XVCMPGTDP_P, @@ -3889,12 +4021,16 @@ const struct altivec_builtin_types altivec_overloaded_builtins[] = { { P8V_BUILTIN_VEC_VMRGEW, P8V_BUILTIN_VMRGEW, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 }, + { P8V_BUILTIN_VEC_VMRGEW, P8V_BUILTIN_VMRGEW, + RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, { P8V_BUILTIN_VEC_VMRGOW, P8V_BUILTIN_VMRGOW, RS6000_BTI_V4SI, RS6000_BTI_V4SI, RS6000_BTI_V4SI, 0 }, { P8V_BUILTIN_VEC_VMRGOW, P8V_BUILTIN_VMRGOW, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, RS6000_BTI_unsigned_V4SI, 0 }, + { P8V_BUILTIN_VEC_VMRGOW, P8V_BUILTIN_VMRGOW, + RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, RS6000_BTI_bool_V4SI, 0 }, { P8V_BUILTIN_VEC_VPOPCNT, P8V_BUILTIN_VPOPCNTB, RS6000_BTI_V16QI, RS6000_BTI_V16QI, 0, 0 }, @@ -4128,7 +4264,8 @@ altivec_build_resolved_builtin (tree *args, int n, argument) is reversed. Patch the arguments here before building the resolved CALL_EXPR. */ if (desc->code == ALTIVEC_BUILTIN_VEC_VCMPGE_P - && desc->overloaded_code != ALTIVEC_BUILTIN_VCMPGEFP_P) + && desc->overloaded_code != ALTIVEC_BUILTIN_VCMPGEFP_P + && desc->overloaded_code != VSX_BUILTIN_XVCMPGEDP_P) { tree t; t = args[2], args[2] = args[1], args[1] = t; @@ -4186,6 +4323,14 @@ altivec_resolve_overloaded_builtin (location_t loc, tree fndecl, if (TARGET_DEBUG_BUILTIN) fprintf (stderr, "altivec_resolve_overloaded_builtin, code = %4d, %s\n", (int)fcode, IDENTIFIER_POINTER (DECL_NAME (fndecl))); + + /* vec_lvsl and vec_lvsr are deprecated for use with LE element order. */ + if (fcode == ALTIVEC_BUILTIN_VEC_LVSL && !VECTOR_ELT_ORDER_BIG) + warning (OPT_Wdeprecated, "vec_lvsl is deprecated for little endian; use \ +assignment for unaligned loads and stores"); + else if (fcode == ALTIVEC_BUILTIN_VEC_LVSR && !VECTOR_ELT_ORDER_BIG) + warning (OPT_Wdeprecated, "vec_lvsr is deprecated for little endian; use \ +assignment for unaligned loads and stores"); /* For now treat vec_splats and vec_promote as the same. */ if (fcode == ALTIVEC_BUILTIN_VEC_SPLATS diff --git a/gcc-4.9/gcc/config/rs6000/rs6000-protos.h b/gcc-4.9/gcc/config/rs6000/rs6000-protos.h index 067a74aa6..aa8e76249 100644 --- a/gcc-4.9/gcc/config/rs6000/rs6000-protos.h +++ b/gcc-4.9/gcc/config/rs6000/rs6000-protos.h @@ -65,6 +65,7 @@ extern void altivec_expand_stvx_be (rtx, rtx, enum machine_mode, unsigned); extern void altivec_expand_stvex_be (rtx, rtx, enum machine_mode, unsigned); extern void rs6000_expand_extract_even (rtx, rtx, rtx); extern void rs6000_expand_interleave (rtx, rtx, rtx, bool); +extern void rs6000_scale_v2df (rtx, rtx, int); extern void build_mask64_2_operands (rtx, rtx *); extern int expand_block_clear (rtx[]); extern int expand_block_move (rtx[]); @@ -79,9 +80,9 @@ extern int mems_ok_for_quad_peep (rtx, rtx); extern bool gpr_or_gpr_p (rtx, rtx); extern bool direct_move_p (rtx, rtx); extern bool quad_load_store_p (rtx, rtx); -extern bool fusion_gpr_load_p (rtx *, bool); +extern bool fusion_gpr_load_p (rtx, rtx, rtx, rtx); extern void expand_fusion_gpr_load (rtx *); -extern const char *emit_fusion_gpr_load (rtx *); +extern const char *emit_fusion_gpr_load (rtx, rtx); extern enum reg_class (*rs6000_preferred_reload_class_ptr) (rtx, enum reg_class); extern enum reg_class (*rs6000_secondary_reload_class_ptr) (enum reg_class, diff --git a/gcc-4.9/gcc/config/rs6000/rs6000.c b/gcc-4.9/gcc/config/rs6000/rs6000.c index 28ccf86df..730e6c8a6 100644 --- a/gcc-4.9/gcc/config/rs6000/rs6000.c +++ b/gcc-4.9/gcc/config/rs6000/rs6000.c @@ -79,6 +79,9 @@ #include "dumpfile.h" #include "cgraph.h" #include "target-globals.h" +#include "real.h" +#include "context.h" +#include "tree-pass.h" #if TARGET_XCOFF #include "xcoffout.h" /* get declarations of xcoff_*_section_name */ #endif @@ -1171,6 +1174,7 @@ static bool rs6000_secondary_reload_move (enum rs6000_reg_type, enum machine_mode, secondary_reload_info *, bool); +rtl_opt_pass *make_pass_analyze_swaps (gcc::context*); /* Hash table stuff for keeping track of TOC entries. */ @@ -1541,17 +1545,6 @@ static const struct attribute_spec rs6000_attribute_table[] = #define TARGET_STACK_PROTECT_FAIL rs6000_stack_protect_fail #endif -/* MPC604EUM 3.5.2 Weak Consistency between Multiple Processors - The PowerPC architecture requires only weak consistency among - processors--that is, memory accesses between processors need not be - sequentially consistent and memory accesses among processors can occur - in any order. The ability to order memory accesses weakly provides - opportunities for more efficient use of the system bus. Unless a - dependency exists, the 604e allows read operations to precede store - operations. */ -#undef TARGET_RELAXED_ORDERING -#define TARGET_RELAXED_ORDERING true - #ifdef HAVE_AS_TLS #undef TARGET_ASM_OUTPUT_DWARF_DTPREL #define TARGET_ASM_OUTPUT_DWARF_DTPREL rs6000_output_dwarf_dtprel @@ -4084,6 +4077,15 @@ static void rs6000_option_override (void) { (void) rs6000_option_override_internal (true); + + /* Register machine-specific passes. This needs to be done at start-up. + It's convenient to do it here (like i386 does). */ + opt_pass *pass_analyze_swaps = make_pass_analyze_swaps (g); + + static struct register_pass_info analyze_swaps_info + = { pass_analyze_swaps, "cse1", 1, PASS_POS_INSERT_BEFORE }; + + register_pass (&analyze_swaps_info); } @@ -6896,24 +6898,6 @@ rs6000_delegitimize_address (rtx orig_x) if (GET_CODE (y) == UNSPEC && XINT (y, 1) == UNSPEC_TOCREL) { -#ifdef ENABLE_CHECKING - if (REG_P (XVECEXP (y, 0, 1)) - && REGNO (XVECEXP (y, 0, 1)) == TOC_REGISTER) - { - /* All good. */ - } - else if (GET_CODE (XVECEXP (y, 0, 1)) == DEBUG_EXPR) - { - /* Weirdness alert. df_note_compute can replace r2 with a - debug_expr when this unspec is in a debug_insn. - Seen in gcc.dg/pr51957-1.c */ - } - else - { - debug_rtx (orig_x); - abort (); - } -#endif y = XVECEXP (y, 0, 0); #ifdef HAVE_AS_TLS @@ -13842,8 +13826,8 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, case ALTIVEC_BUILTIN_MASK_FOR_LOAD: case ALTIVEC_BUILTIN_MASK_FOR_STORE: { - int icode = (BYTES_BIG_ENDIAN ? (int) CODE_FOR_altivec_lvsr - : (int) CODE_FOR_altivec_lvsl); + int icode = (BYTES_BIG_ENDIAN ? (int) CODE_FOR_altivec_lvsr_direct + : (int) CODE_FOR_altivec_lvsl_direct); enum machine_mode tmode = insn_data[icode].operand[0].mode; enum machine_mode mode = insn_data[icode].operand[1].mode; tree arg; @@ -13871,7 +13855,6 @@ rs6000_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, || ! (*insn_data[icode].operand[0].predicate) (target, tmode)) target = gen_reg_rtx (tmode); - /*pat = gen_altivec_lvsr (target, op);*/ pat = GEN_FCN (icode) (target, op); if (!pat) return 0; @@ -16654,10 +16637,13 @@ rs6000_secondary_reload (bool in_p, : (offset + 0x8000 < 0x10000 - extra /* legitimate_address_p */ && (offset & 3) != 0)) { + /* -m32 -mpowerpc64 needs to use a 32-bit scratch register. */ if (in_p) - sri->icode = CODE_FOR_reload_di_load; + sri->icode = ((TARGET_32BIT) ? CODE_FOR_reload_si_load + : CODE_FOR_reload_di_load); else - sri->icode = CODE_FOR_reload_di_store; + sri->icode = ((TARGET_32BIT) ? CODE_FOR_reload_si_store + : CODE_FOR_reload_di_store); sri->extra_cost = 2; ret = NO_REGS; } @@ -30923,6 +30909,23 @@ rs6000_expand_interleave (rtx target, rtx op0, rtx op1, bool highp) rs6000_do_expand_vec_perm (target, op0, op1, vmode, nelt, perm); } +/* Scale a V2DF vector SRC by two to the SCALE and place in TGT. */ +void +rs6000_scale_v2df (rtx tgt, rtx src, int scale) +{ + HOST_WIDE_INT hwi_scale (scale); + REAL_VALUE_TYPE r_pow; + rtvec v = rtvec_alloc (2); + rtx elt; + rtx scale_vec = gen_reg_rtx (V2DFmode); + (void)real_powi (&r_pow, DFmode, &dconst2, hwi_scale); + elt = CONST_DOUBLE_FROM_REAL_VALUE (r_pow, DFmode); + RTVEC_ELT (v, 0) = elt; + RTVEC_ELT (v, 1) = elt; + rs6000_expand_vector_init (scale_vec, gen_rtx_PARALLEL (V2DFmode, v)); + emit_insn (gen_mulv2df3 (tgt, src, scale_vec)); +} + /* Return an RTX representing where to find the function value of a function returning MODE. */ static rtx @@ -32551,6 +32554,14 @@ rs6000_split_logical_inner (rtx dest, if (complement_op2_p) op2 = gen_rtx_NOT (mode, op2); + /* For canonical RTL, if only one arm is inverted it is the first. */ + if (!complement_op1_p && complement_op2_p) + { + rtx temp = op1; + op1 = op2; + op2 = temp; + } + bool_rtx = ((code == NOT) ? gen_rtx_NOT (mode, op1) : gen_rtx_fmt_ee (code, mode, op1, op2)); @@ -32755,25 +32766,14 @@ rs6000_split_logical (rtx operands[3], /* Return true if the peephole2 can combine a load involving a combination of an addis instruction and a load with an offset that can be fused together on - a power8. - - The operands are: - operands[0] register set with addis - operands[1] value set via addis - operands[2] target register being loaded - operands[3] D-form memory reference using operands[0]. - - In addition, we are passed a boolean that is true if this is a peephole2, - and we can use see if the addis_reg is dead after the insn and can be - replaced by the target register. */ + a power8. */ bool -fusion_gpr_load_p (rtx *operands, bool peep2_p) +fusion_gpr_load_p (rtx addis_reg, /* register set via addis. */ + rtx addis_value, /* addis value. */ + rtx target, /* target register that is loaded. */ + rtx mem) /* bottom part of the memory addr. */ { - rtx addis_reg = operands[0]; - rtx addis_value = operands[1]; - rtx target = operands[2]; - rtx mem = operands[3]; rtx addr; rtx base_reg; @@ -32787,9 +32787,6 @@ fusion_gpr_load_p (rtx *operands, bool peep2_p) if (!fusion_gpr_addis (addis_value, GET_MODE (addis_value))) return false; - if (!fusion_gpr_mem_load (mem, GET_MODE (mem))) - return false; - /* Allow sign/zero extension. */ if (GET_CODE (mem) == ZERO_EXTEND || (GET_CODE (mem) == SIGN_EXTEND && TARGET_P8_FUSION_SIGN)) @@ -32798,22 +32795,22 @@ fusion_gpr_load_p (rtx *operands, bool peep2_p) if (!MEM_P (mem)) return false; + if (!fusion_gpr_mem_load (mem, GET_MODE (mem))) + return false; + addr = XEXP (mem, 0); /* either PLUS or LO_SUM. */ if (GET_CODE (addr) != PLUS && GET_CODE (addr) != LO_SUM) return false; /* Validate that the register used to load the high value is either the - register being loaded, or we can safely replace its use in a peephole2. + register being loaded, or we can safely replace its use. - If this is a peephole2, we assume that there are 2 instructions in the - peephole (addis and load), so we want to check if the target register was - not used in the memory address and the register to hold the addis result - is dead after the peephole. */ + This function is only called from the peephole2 pass and we assume that + there are 2 instructions in the peephole (addis and load), so we want to + check if the target register was not used in the memory address and the + register to hold the addis result is dead after the peephole. */ if (REGNO (addis_reg) != REGNO (target)) { - if (!peep2_p) - return false; - if (reg_mentioned_p (target, mem)) return false; @@ -32854,9 +32851,6 @@ expand_fusion_gpr_load (rtx *operands) enum machine_mode extend_mode = target_mode; enum machine_mode ptr_mode = Pmode; enum rtx_code extend = UNKNOWN; - rtx addis_reg = ((ptr_mode == target_mode) - ? target - : simplify_subreg (ptr_mode, target, target_mode, 0)); if (GET_CODE (orig_mem) == ZERO_EXTEND || (TARGET_P8_FUSION_SIGN && GET_CODE (orig_mem) == SIGN_EXTEND)) @@ -32873,13 +32867,14 @@ expand_fusion_gpr_load (rtx *operands) gcc_assert (plus_or_lo_sum == PLUS || plus_or_lo_sum == LO_SUM); offset = XEXP (orig_addr, 1); - new_addr = gen_rtx_fmt_ee (plus_or_lo_sum, ptr_mode, addis_reg, offset); - new_mem = change_address (orig_mem, target_mode, new_addr); + new_addr = gen_rtx_fmt_ee (plus_or_lo_sum, ptr_mode, addis_value, offset); + new_mem = replace_equiv_address_nv (orig_mem, new_addr); if (extend != UNKNOWN) new_mem = gen_rtx_fmt_e (ZERO_EXTEND, extend_mode, new_mem); - emit_insn (gen_rtx_SET (VOIDmode, addis_reg, addis_value)); + new_mem = gen_rtx_UNSPEC (extend_mode, gen_rtvec (1, new_mem), + UNSPEC_FUSION_GPR); emit_insn (gen_rtx_SET (VOIDmode, target, new_mem)); if (extend == SIGN_EXTEND) @@ -32898,55 +32893,40 @@ expand_fusion_gpr_load (rtx *operands) } /* Return a string to fuse an addis instruction with a gpr load to the same - register that we loaded up the addis instruction. The code is complicated, - so we call output_asm_insn directly, and just return "". + register that we loaded up the addis instruction. The address that is used + is the logical address that was formed during peephole2: + (lo_sum (high) (low-part)) - The operands are: - operands[0] register set with addis (must be same reg as target). - operands[1] value set via addis - operands[2] target register being loaded - operands[3] D-form memory reference using operands[0]. */ + The code is complicated, so we call output_asm_insn directly, and just + return "". */ const char * -emit_fusion_gpr_load (rtx *operands) +emit_fusion_gpr_load (rtx target, rtx mem) { - rtx addis_reg = operands[0]; - rtx addis_value = operands[1]; - rtx target = operands[2]; - rtx mem = operands[3]; + rtx addis_value; rtx fuse_ops[10]; rtx addr; rtx load_offset; const char *addis_str = NULL; const char *load_str = NULL; - const char *extend_insn = NULL; const char *mode_name = NULL; char insn_template[80]; enum machine_mode mode; const char *comment_str = ASM_COMMENT_START; - bool sign_p = false; - gcc_assert (REG_P (addis_reg) && REG_P (target)); - gcc_assert (REGNO (addis_reg) == REGNO (target)); - - if (*comment_str == ' ') - comment_str++; - - /* Allow sign/zero extension. */ if (GET_CODE (mem) == ZERO_EXTEND) mem = XEXP (mem, 0); - else if (GET_CODE (mem) == SIGN_EXTEND && TARGET_P8_FUSION_SIGN) - { - sign_p = true; - mem = XEXP (mem, 0); - } + gcc_assert (REG_P (target) && MEM_P (mem)); + + if (*comment_str == ' ') + comment_str++; - gcc_assert (MEM_P (mem)); addr = XEXP (mem, 0); if (GET_CODE (addr) != PLUS && GET_CODE (addr) != LO_SUM) gcc_unreachable (); + addis_value = XEXP (addr, 0); load_offset = XEXP (addr, 1); /* Now emit the load instruction to the same register. */ @@ -32956,29 +32936,22 @@ emit_fusion_gpr_load (rtx *operands) case QImode: mode_name = "char"; load_str = "lbz"; - extend_insn = "extsb %0,%0"; break; case HImode: mode_name = "short"; load_str = "lhz"; - extend_insn = "extsh %0,%0"; break; case SImode: mode_name = "int"; load_str = "lwz"; - extend_insn = "extsw %0,%0"; break; case DImode: - if (TARGET_POWERPC64) - { - mode_name = "long"; - load_str = "ld"; - } - else - gcc_unreachable (); + gcc_assert (TARGET_POWERPC64); + mode_name = "long"; + load_str = "ld"; break; default: @@ -33122,17 +33095,1191 @@ emit_fusion_gpr_load (rtx *operands) else fatal_insn ("Unable to generate load offset for fusion", load_offset); - /* Handle sign extension. The peephole2 pass generates this as a separate - insn, but we handle it just in case it got reattached. */ - if (sign_p) + return ""; +} + +/* Analyze vector computations and remove unnecessary doubleword + swaps (xxswapdi instructions). This pass is performed only + for little-endian VSX code generation. + + For this specific case, loads and stores of 4x32 and 2x64 vectors + are inefficient. These are implemented using the lvx2dx and + stvx2dx instructions, which invert the order of doublewords in + a vector register. Thus the code generation inserts an xxswapdi + after each such load, and prior to each such store. (For spill + code after register assignment, an additional xxswapdi is inserted + following each store in order to return a hard register to its + unpermuted value.) + + The extra xxswapdi instructions reduce performance. This can be + particularly bad for vectorized code. The purpose of this pass + is to reduce the number of xxswapdi instructions required for + correctness. + + The primary insight is that much code that operates on vectors + does not care about the relative order of elements in a register, + so long as the correct memory order is preserved. If we have + a computation where all input values are provided by lvxd2x/xxswapdi + sequences, all outputs are stored using xxswapdi/stvxd2x sequences, + and all intermediate computations are pure SIMD (independent of + element order), then all the xxswapdi's associated with the loads + and stores may be removed. + + This pass uses some of the infrastructure and logical ideas from + the "web" pass in web.c. We create maximal webs of computations + fitting the description above using union-find. Each such web is + then optimized by removing its unnecessary xxswapdi instructions. + + The pass is placed prior to global optimization so that we can + perform the optimization in the safest and simplest way possible; + that is, by replacing each xxswapdi insn with a register copy insn. + Subsequent forward propagation will remove copies where possible. + + There are some operations sensitive to element order for which we + can still allow the operation, provided we modify those operations. + These include CONST_VECTORs, for which we must swap the first and + second halves of the constant vector; and SUBREGs, for which we + must adjust the byte offset to account for the swapped doublewords. + A remaining opportunity would be non-immediate-form splats, for + which we should adjust the selected lane of the input. We should + also make code generation adjustments for sum-across operations, + since this is a common vectorizer reduction. + + Because we run prior to the first split, we can see loads and stores + here that match *vsx_le_perm_{load,store}_. These are vanilla + vector loads and stores that have not yet been split into a permuting + load/store and a swap. (One way this can happen is with a builtin + call to vec_vsx_{ld,st}.) We can handle these as well, but rather + than deleting a swap, we convert the load/store into a permuting + load/store (which effectively removes the swap). */ + +/* Notes on Permutes + + We do not currently handle computations that contain permutes. There + is a general transformation that can be performed correctly, but it + may introduce more expensive code than it replaces. To handle these + would require a cost model to determine when to perform the optimization. + This commentary records how this could be done if desired. + + The most general permute is something like this (example for V16QI): + + (vec_select:V16QI (vec_concat:V32QI (op1:V16QI) (op2:V16QI)) + (parallel [(const_int a0) (const_int a1) + ... + (const_int a14) (const_int a15)])) + + where a0,...,a15 are in [0,31] and select elements from op1 and op2 + to produce in the result. + + Regardless of mode, we can convert the PARALLEL to a mask of 16 + byte-element selectors. Let's call this M, with M[i] representing + the ith byte-element selector value. Then if we swap doublewords + throughout the computation, we can get correct behavior by replacing + M with M' as follows: + + { M[i+8]+8 : i < 8, M[i+8] in [0,7] U [16,23] + M'[i] = { M[i+8]-8 : i < 8, M[i+8] in [8,15] U [24,31] + { M[i-8]+8 : i >= 8, M[i-8] in [0,7] U [16,23] + { M[i-8]-8 : i >= 8, M[i-8] in [8,15] U [24,31] + + This seems promising at first, since we are just replacing one mask + with another. But certain masks are preferable to others. If M + is a mask that matches a vmrghh pattern, for example, M' certainly + will not. Instead of a single vmrghh, we would generate a load of + M' and a vperm. So we would need to know how many xxswapd's we can + remove as a result of this transformation to determine if it's + profitable; and preferably the logic would need to be aware of all + the special preferable masks. + + Another form of permute is an UNSPEC_VPERM, in which the mask is + already in a register. In some cases, this mask may be a constant + that we can discover with ud-chains, in which case the above + transformation is ok. However, the common usage here is for the + mask to be produced by an UNSPEC_LVSL, in which case the mask + cannot be known at compile time. In such a case we would have to + generate several instructions to compute M' as above at run time, + and a cost model is needed again. */ + +/* This is based on the union-find logic in web.c. web_entry_base is + defined in df.h. */ +class swap_web_entry : public web_entry_base +{ + public: + /* Pointer to the insn. */ + rtx insn; + /* Set if insn contains a mention of a vector register. All other + fields are undefined if this field is unset. */ + unsigned int is_relevant : 1; + /* Set if insn is a load. */ + unsigned int is_load : 1; + /* Set if insn is a store. */ + unsigned int is_store : 1; + /* Set if insn is a doubleword swap. This can either be a register swap + or a permuting load or store (test is_load and is_store for this). */ + unsigned int is_swap : 1; + /* Set if the insn has a live-in use of a parameter register. */ + unsigned int is_live_in : 1; + /* Set if the insn has a live-out def of a return register. */ + unsigned int is_live_out : 1; + /* Set if the insn contains a subreg reference of a vector register. */ + unsigned int contains_subreg : 1; + /* Set if the insn contains a 128-bit integer operand. */ + unsigned int is_128_int : 1; + /* Set if this is a call-insn. */ + unsigned int is_call : 1; + /* Set if this insn does not perform a vector operation for which + element order matters, or if we know how to fix it up if it does. + Undefined if is_swap is set. */ + unsigned int is_swappable : 1; + /* A nonzero value indicates what kind of special handling for this + insn is required if doublewords are swapped. Undefined if + is_swappable is not set. */ + unsigned int special_handling : 3; + /* Set if the web represented by this entry cannot be optimized. */ + unsigned int web_not_optimizable : 1; + /* Set if this insn should be deleted. */ + unsigned int will_delete : 1; +}; + +enum special_handling_values { + SH_NONE = 0, + SH_CONST_VECTOR, + SH_SUBREG, + SH_NOSWAP_LD, + SH_NOSWAP_ST, + SH_EXTRACT, + SH_SPLAT +}; + +/* Union INSN with all insns containing definitions that reach USE. + Detect whether USE is live-in to the current function. */ +static void +union_defs (swap_web_entry *insn_entry, rtx insn, df_ref use) +{ + struct df_link *link = DF_REF_CHAIN (use); + + if (!link) + insn_entry[INSN_UID (insn)].is_live_in = 1; + + while (link) { - gcc_assert (extend_insn != NULL); - output_asm_insn (extend_insn, fuse_ops); + if (DF_REF_IS_ARTIFICIAL (link->ref)) + insn_entry[INSN_UID (insn)].is_live_in = 1; + + if (DF_REF_INSN_INFO (link->ref)) + { + rtx def_insn = DF_REF_INSN (link->ref); + (void)unionfind_union (insn_entry + INSN_UID (insn), + insn_entry + INSN_UID (def_insn)); + } + + link = link->next; } +} - return ""; +/* Union INSN with all insns containing uses reached from DEF. + Detect whether DEF is live-out from the current function. */ +static void +union_uses (swap_web_entry *insn_entry, rtx insn, df_ref def) +{ + struct df_link *link = DF_REF_CHAIN (def); + + if (!link) + insn_entry[INSN_UID (insn)].is_live_out = 1; + + while (link) + { + /* This could be an eh use or some other artificial use; + we treat these all the same (killing the optimization). */ + if (DF_REF_IS_ARTIFICIAL (link->ref)) + insn_entry[INSN_UID (insn)].is_live_out = 1; + + if (DF_REF_INSN_INFO (link->ref)) + { + rtx use_insn = DF_REF_INSN (link->ref); + (void)unionfind_union (insn_entry + INSN_UID (insn), + insn_entry + INSN_UID (use_insn)); + } + + link = link->next; + } +} + +/* Return 1 iff INSN is a load insn, including permuting loads that + represent an lvxd2x instruction; else return 0. */ +static unsigned int +insn_is_load_p (rtx insn) +{ + rtx body = PATTERN (insn); + + if (GET_CODE (body) == SET) + { + if (GET_CODE (SET_SRC (body)) == MEM) + return 1; + + if (GET_CODE (SET_SRC (body)) == VEC_SELECT + && GET_CODE (XEXP (SET_SRC (body), 0)) == MEM) + return 1; + + return 0; + } + + if (GET_CODE (body) != PARALLEL) + return 0; + + rtx set = XVECEXP (body, 0, 0); + + if (GET_CODE (set) == SET && GET_CODE (SET_SRC (set)) == MEM) + return 1; + + return 0; +} + +/* Return 1 iff INSN is a store insn, including permuting stores that + represent an stvxd2x instruction; else return 0. */ +static unsigned int +insn_is_store_p (rtx insn) +{ + rtx body = PATTERN (insn); + if (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == MEM) + return 1; + if (GET_CODE (body) != PARALLEL) + return 0; + rtx set = XVECEXP (body, 0, 0); + if (GET_CODE (set) == SET && GET_CODE (SET_DEST (set)) == MEM) + return 1; + return 0; } +/* Return 1 iff INSN swaps doublewords. This may be a reg-reg swap, + a permuting load, or a permuting store. */ +static unsigned int +insn_is_swap_p (rtx insn) +{ + rtx body = PATTERN (insn); + if (GET_CODE (body) != SET) + return 0; + rtx rhs = SET_SRC (body); + if (GET_CODE (rhs) != VEC_SELECT) + return 0; + rtx parallel = XEXP (rhs, 1); + if (GET_CODE (parallel) != PARALLEL) + return 0; + unsigned int len = XVECLEN (parallel, 0); + if (len != 2 && len != 4 && len != 8 && len != 16) + return 0; + for (unsigned int i = 0; i < len / 2; ++i) + { + rtx op = XVECEXP (parallel, 0, i); + if (GET_CODE (op) != CONST_INT || INTVAL (op) != len / 2 + i) + return 0; + } + for (unsigned int i = len / 2; i < len; ++i) + { + rtx op = XVECEXP (parallel, 0, i); + if (GET_CODE (op) != CONST_INT || INTVAL (op) != i - len / 2) + return 0; + } + return 1; +} + +/* Return 1 iff OP is an operand that will not be affected by having + vector doublewords swapped in memory. */ +static unsigned int +rtx_is_swappable_p (rtx op, unsigned int *special) +{ + enum rtx_code code = GET_CODE (op); + int i, j; + rtx parallel; + + switch (code) + { + case LABEL_REF: + case SYMBOL_REF: + case CLOBBER: + case REG: + return 1; + + case VEC_CONCAT: + case ASM_INPUT: + case ASM_OPERANDS: + return 0; + + case CONST_VECTOR: + { + *special = SH_CONST_VECTOR; + return 1; + } + + case VEC_DUPLICATE: + /* Opportunity: If XEXP (op, 0) has the same mode as the result, + and XEXP (op, 1) is a PARALLEL with a single QImode const int, + it represents a vector splat for which we can do special + handling. */ + if (GET_CODE (XEXP (op, 0)) == CONST_INT) + return 1; + else if (GET_CODE (XEXP (op, 0)) == REG + && GET_MODE_INNER (GET_MODE (op)) == GET_MODE (XEXP (op, 0))) + /* This catches V2DF and V2DI splat, at a minimum. */ + return 1; + else if (GET_CODE (XEXP (op, 0)) == VEC_SELECT) + /* If the duplicated item is from a select, defer to the select + processing to see if we can change the lane for the splat. */ + return rtx_is_swappable_p (XEXP (op, 0), special); + else + return 0; + + case VEC_SELECT: + /* A vec_extract operation is ok if we change the lane. */ + if (GET_CODE (XEXP (op, 0)) == REG + && GET_MODE_INNER (GET_MODE (XEXP (op, 0))) == GET_MODE (op) + && GET_CODE ((parallel = XEXP (op, 1))) == PARALLEL + && XVECLEN (parallel, 0) == 1 + && GET_CODE (XVECEXP (parallel, 0, 0)) == CONST_INT) + { + *special = SH_EXTRACT; + return 1; + } + else + return 0; + + case UNSPEC: + { + /* Various operations are unsafe for this optimization, at least + without significant additional work. Permutes are obviously + problematic, as both the permute control vector and the ordering + of the target values are invalidated by doubleword swapping. + Vector pack and unpack modify the number of vector lanes. + Merge-high/low will not operate correctly on swapped operands. + Vector shifts across element boundaries are clearly uncool, + as are vector select and concatenate operations. Vector + sum-across instructions define one operand with a specific + order-dependent element, so additional fixup code would be + needed to make those work. Vector set and non-immediate-form + vector splat are element-order sensitive. A few of these + cases might be workable with special handling if required. */ + int val = XINT (op, 1); + switch (val) + { + default: + break; + case UNSPEC_VMRGH_DIRECT: + case UNSPEC_VMRGL_DIRECT: + case UNSPEC_VPACK_SIGN_SIGN_SAT: + case UNSPEC_VPACK_SIGN_UNS_SAT: + case UNSPEC_VPACK_UNS_UNS_MOD: + case UNSPEC_VPACK_UNS_UNS_MOD_DIRECT: + case UNSPEC_VPACK_UNS_UNS_SAT: + case UNSPEC_VPERM: + case UNSPEC_VPERM_UNS: + case UNSPEC_VPERMHI: + case UNSPEC_VPERMSI: + case UNSPEC_VPKPX: + case UNSPEC_VSLDOI: + case UNSPEC_VSLO: + case UNSPEC_VSRO: + case UNSPEC_VSUM2SWS: + case UNSPEC_VSUM4S: + case UNSPEC_VSUM4UBS: + case UNSPEC_VSUMSWS: + case UNSPEC_VSUMSWS_DIRECT: + case UNSPEC_VSX_CONCAT: + case UNSPEC_VSX_SET: + case UNSPEC_VSX_SLDWI: + case UNSPEC_VUNPACK_HI_SIGN: + case UNSPEC_VUNPACK_HI_SIGN_DIRECT: + case UNSPEC_VUNPACK_LO_SIGN: + case UNSPEC_VUNPACK_LO_SIGN_DIRECT: + case UNSPEC_VUPKHPX: + case UNSPEC_VUPKHS_V4SF: + case UNSPEC_VUPKHU_V4SF: + case UNSPEC_VUPKLPX: + case UNSPEC_VUPKLS_V4SF: + case UNSPEC_VUPKLU_V4SF: + /* The following could be handled as an idiom with XXSPLTW. + These place a scalar in BE element zero, but the XXSPLTW + will currently expect it in BE element 2 in a swapped + region. When one of these feeds an XXSPLTW with no other + defs/uses either way, we can avoid the lane change for + XXSPLTW and things will be correct. TBD. */ + case UNSPEC_VSX_CVDPSPN: + case UNSPEC_VSX_CVSPDP: + case UNSPEC_VSX_CVSPDPN: + return 0; + case UNSPEC_VSPLT_DIRECT: + *special = SH_SPLAT; + return 1; + } + } + + default: + break; + } + + const char *fmt = GET_RTX_FORMAT (code); + int ok = 1; + + for (i = 0; i < GET_RTX_LENGTH (code); ++i) + if (fmt[i] == 'e' || fmt[i] == 'u') + { + unsigned int special_op = SH_NONE; + ok &= rtx_is_swappable_p (XEXP (op, i), &special_op); + /* Ensure we never have two kinds of special handling + for the same insn. */ + if (*special != SH_NONE && special_op != SH_NONE + && *special != special_op) + return 0; + *special = special_op; + } + else if (fmt[i] == 'E') + for (j = 0; j < XVECLEN (op, i); ++j) + { + unsigned int special_op = SH_NONE; + ok &= rtx_is_swappable_p (XVECEXP (op, i, j), &special_op); + /* Ensure we never have two kinds of special handling + for the same insn. */ + if (*special != SH_NONE && special_op != SH_NONE + && *special != special_op) + return 0; + *special = special_op; + } + + return ok; +} + +/* Return 1 iff INSN is an operand that will not be affected by + having vector doublewords swapped in memory (in which case + *SPECIAL is unchanged), or that can be modified to be correct + if vector doublewords are swapped in memory (in which case + *SPECIAL is changed to a value indicating how). */ +static unsigned int +insn_is_swappable_p (swap_web_entry *insn_entry, rtx insn, + unsigned int *special) +{ + /* Calls are always bad. */ + if (GET_CODE (insn) == CALL_INSN) + return 0; + + /* Loads and stores seen here are not permuting, but we can still + fix them up by converting them to permuting ones. Exceptions: + UNSPEC_LVE, UNSPEC_LVX, and UNSPEC_STVX, which have a PARALLEL + body instead of a SET; and UNSPEC_STVE, which has an UNSPEC + for the SET source. */ + rtx body = PATTERN (insn); + int i = INSN_UID (insn); + + if (insn_entry[i].is_load) + { + if (GET_CODE (body) == SET) + { + *special = SH_NOSWAP_LD; + return 1; + } + else + return 0; + } + + if (insn_entry[i].is_store) + { + if (GET_CODE (body) == SET && GET_CODE (SET_SRC (body)) != UNSPEC) + { + *special = SH_NOSWAP_ST; + return 1; + } + else + return 0; + } + + /* Otherwise check the operands for vector lane violations. */ + return rtx_is_swappable_p (body, special); +} + +enum chain_purpose { FOR_LOADS, FOR_STORES }; + +/* Return true if the UD or DU chain headed by LINK is non-empty, + and every entry on the chain references an insn that is a + register swap. Furthermore, if PURPOSE is FOR_LOADS, each such + register swap must have only permuting loads as reaching defs. + If PURPOSE is FOR_STORES, each such register swap must have only + register swaps or permuting stores as reached uses. */ +static bool +chain_contains_only_swaps (swap_web_entry *insn_entry, struct df_link *link, + enum chain_purpose purpose) +{ + if (!link) + return false; + + for (; link; link = link->next) + { + if (!VECTOR_MODE_P (GET_MODE (DF_REF_REG (link->ref)))) + continue; + + if (DF_REF_IS_ARTIFICIAL (link->ref)) + return false; + + rtx reached_insn = DF_REF_INSN (link->ref); + unsigned uid = INSN_UID (reached_insn); + + if (!insn_entry[uid].is_swap || insn_entry[uid].is_load + || insn_entry[uid].is_store) + return false; + + if (purpose == FOR_LOADS) + { + df_ref *use_rec; + for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) + { + df_ref use = *use_rec; + struct df_link *swap_link = DF_REF_CHAIN (use); + + while (swap_link) + { + if (DF_REF_IS_ARTIFICIAL (link->ref)) + return false; + + rtx swap_def_insn = DF_REF_INSN (swap_link->ref); + unsigned uid2 = INSN_UID (swap_def_insn); + + /* Only permuting loads are allowed. */ + if (!insn_entry[uid2].is_swap || !insn_entry[uid2].is_load) + return false; + + swap_link = swap_link->next; + } + } + } + else if (purpose == FOR_STORES) + { + df_ref *def_rec; + for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) + { + df_ref def = *def_rec; + struct df_link *swap_link = DF_REF_CHAIN (def); + + while (swap_link) + { + if (DF_REF_IS_ARTIFICIAL (link->ref)) + return false; + + rtx swap_use_insn = DF_REF_INSN (swap_link->ref); + unsigned uid2 = INSN_UID (swap_use_insn); + + /* Permuting stores or register swaps are allowed. */ + if (!insn_entry[uid2].is_swap || insn_entry[uid2].is_load) + return false; + + swap_link = swap_link->next; + } + } + } + } + + return true; +} + +/* Mark the xxswapdi instructions associated with permuting loads and + stores for removal. Note that we only flag them for deletion here, + as there is a possibility of a swap being reached from multiple + loads, etc. */ +static void +mark_swaps_for_removal (swap_web_entry *insn_entry, unsigned int i) +{ + rtx insn = insn_entry[i].insn; + unsigned uid = INSN_UID (insn); + + if (insn_entry[i].is_load) + { + df_ref *def_rec; + for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) + { + df_ref def = *def_rec; + struct df_link *link = DF_REF_CHAIN (def); + + /* We know by now that these are swaps, so we can delete + them confidently. */ + while (link) + { + rtx use_insn = DF_REF_INSN (link->ref); + insn_entry[INSN_UID (use_insn)].will_delete = 1; + link = link->next; + } + } + } + else if (insn_entry[i].is_store) + { + df_ref *use_rec; + for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) + { + df_ref use = *use_rec; + /* Ignore uses for addressability. */ + machine_mode mode = GET_MODE (DF_REF_REG (use)); + if (!VECTOR_MODE_P (mode)) + continue; + + struct df_link *link = DF_REF_CHAIN (use); + + /* We know by now that these are swaps, so we can delete + them confidently. */ + while (link) + { + rtx def_insn = DF_REF_INSN (link->ref); + insn_entry[INSN_UID (def_insn)].will_delete = 1; + link = link->next; + } + } + } +} + +/* OP is either a CONST_VECTOR or an expression containing one. + Swap the first half of the vector with the second in the first + case. Recurse to find it in the second. */ +static void +swap_const_vector_halves (rtx op) +{ + int i; + enum rtx_code code = GET_CODE (op); + if (GET_CODE (op) == CONST_VECTOR) + { + int half_units = GET_MODE_NUNITS (GET_MODE (op)) / 2; + for (i = 0; i < half_units; ++i) + { + rtx temp = CONST_VECTOR_ELT (op, i); + CONST_VECTOR_ELT (op, i) = CONST_VECTOR_ELT (op, i + half_units); + CONST_VECTOR_ELT (op, i + half_units) = temp; + } + } + else + { + int j; + const char *fmt = GET_RTX_FORMAT (code); + for (i = 0; i < GET_RTX_LENGTH (code); ++i) + if (fmt[i] == 'e' || fmt[i] == 'u') + swap_const_vector_halves (XEXP (op, i)); + else if (fmt[i] == 'E') + for (j = 0; j < XVECLEN (op, i); ++j) + swap_const_vector_halves (XVECEXP (op, i, j)); + } +} + +/* Find all subregs of a vector expression that perform a narrowing, + and adjust the subreg index to account for doubleword swapping. */ +static void +adjust_subreg_index (rtx op) +{ + enum rtx_code code = GET_CODE (op); + if (code == SUBREG + && (GET_MODE_SIZE (GET_MODE (op)) + < GET_MODE_SIZE (GET_MODE (XEXP (op, 0))))) + { + unsigned int index = SUBREG_BYTE (op); + if (index < 8) + index += 8; + else + index -= 8; + SUBREG_BYTE (op) = index; + } + + const char *fmt = GET_RTX_FORMAT (code); + int i,j; + for (i = 0; i < GET_RTX_LENGTH (code); ++i) + if (fmt[i] == 'e' || fmt[i] == 'u') + adjust_subreg_index (XEXP (op, i)); + else if (fmt[i] == 'E') + for (j = 0; j < XVECLEN (op, i); ++j) + adjust_subreg_index (XVECEXP (op, i, j)); +} + +/* Convert the non-permuting load INSN to a permuting one. */ +static void +permute_load (rtx insn) +{ + rtx body = PATTERN (insn); + rtx mem_op = SET_SRC (body); + rtx tgt_reg = SET_DEST (body); + machine_mode mode = GET_MODE (tgt_reg); + int n_elts = GET_MODE_NUNITS (mode); + int half_elts = n_elts / 2; + rtx par = gen_rtx_PARALLEL (mode, rtvec_alloc (n_elts)); + int i, j; + for (i = 0, j = half_elts; i < half_elts; ++i, ++j) + XVECEXP (par, 0, i) = GEN_INT (j); + for (i = half_elts, j = 0; j < half_elts; ++i, ++j) + XVECEXP (par, 0, i) = GEN_INT (j); + rtx sel = gen_rtx_VEC_SELECT (mode, mem_op, par); + SET_SRC (body) = sel; + INSN_CODE (insn) = -1; /* Force re-recognition. */ + df_insn_rescan (insn); + + if (dump_file) + fprintf (dump_file, "Replacing load %d with permuted load\n", + INSN_UID (insn)); +} + +/* Convert the non-permuting store INSN to a permuting one. */ +static void +permute_store (rtx insn) +{ + rtx body = PATTERN (insn); + rtx src_reg = SET_SRC (body); + machine_mode mode = GET_MODE (src_reg); + int n_elts = GET_MODE_NUNITS (mode); + int half_elts = n_elts / 2; + rtx par = gen_rtx_PARALLEL (mode, rtvec_alloc (n_elts)); + int i, j; + for (i = 0, j = half_elts; i < half_elts; ++i, ++j) + XVECEXP (par, 0, i) = GEN_INT (j); + for (i = half_elts, j = 0; j < half_elts; ++i, ++j) + XVECEXP (par, 0, i) = GEN_INT (j); + rtx sel = gen_rtx_VEC_SELECT (mode, src_reg, par); + SET_SRC (body) = sel; + INSN_CODE (insn) = -1; /* Force re-recognition. */ + df_insn_rescan (insn); + + if (dump_file) + fprintf (dump_file, "Replacing store %d with permuted store\n", + INSN_UID (insn)); +} + +/* Given OP that contains a vector extract operation, adjust the index + of the extracted lane to account for the doubleword swap. */ +static void +adjust_extract (rtx insn) +{ + rtx src = SET_SRC (PATTERN (insn)); + /* The vec_select may be wrapped in a vec_duplicate for a splat, so + account for that. */ + rtx sel = GET_CODE (src) == VEC_DUPLICATE ? XEXP (src, 0) : src; + rtx par = XEXP (sel, 1); + int half_elts = GET_MODE_NUNITS (GET_MODE (XEXP (sel, 0))) >> 1; + int lane = INTVAL (XVECEXP (par, 0, 0)); + lane = lane >= half_elts ? lane - half_elts : lane + half_elts; + XVECEXP (par, 0, 0) = GEN_INT (lane); + INSN_CODE (insn) = -1; /* Force re-recognition. */ + df_insn_rescan (insn); + + if (dump_file) + fprintf (dump_file, "Changing lane for extract %d\n", INSN_UID (insn)); +} + +/* Given OP that contains a vector direct-splat operation, adjust the index + of the source lane to account for the doubleword swap. */ +static void +adjust_splat (rtx insn) +{ + rtx body = PATTERN (insn); + rtx unspec = XEXP (body, 1); + int half_elts = GET_MODE_NUNITS (GET_MODE (unspec)) >> 1; + int lane = INTVAL (XVECEXP (unspec, 0, 1)); + lane = lane >= half_elts ? lane - half_elts : lane + half_elts; + XVECEXP (unspec, 0, 1) = GEN_INT (lane); + INSN_CODE (insn) = -1; /* Force re-recognition. */ + df_insn_rescan (insn); + + if (dump_file) + fprintf (dump_file, "Changing lane for splat %d\n", INSN_UID (insn)); +} + +/* The insn described by INSN_ENTRY[I] can be swapped, but only + with special handling. Take care of that here. */ +static void +handle_special_swappables (swap_web_entry *insn_entry, unsigned i) +{ + rtx insn = insn_entry[i].insn; + rtx body = PATTERN (insn); + + switch (insn_entry[i].special_handling) + { + default: + gcc_unreachable (); + case SH_CONST_VECTOR: + { + /* A CONST_VECTOR will only show up somewhere in the RHS of a SET. */ + gcc_assert (GET_CODE (body) == SET); + rtx rhs = SET_SRC (body); + swap_const_vector_halves (rhs); + if (dump_file) + fprintf (dump_file, "Swapping constant halves in insn %d\n", i); + break; + } + case SH_SUBREG: + /* A subreg of the same size is already safe. For subregs that + select a smaller portion of a reg, adjust the index for + swapped doublewords. */ + adjust_subreg_index (body); + if (dump_file) + fprintf (dump_file, "Adjusting subreg in insn %d\n", i); + break; + case SH_NOSWAP_LD: + /* Convert a non-permuting load to a permuting one. */ + permute_load (insn); + break; + case SH_NOSWAP_ST: + /* Convert a non-permuting store to a permuting one. */ + permute_store (insn); + break; + case SH_EXTRACT: + /* Change the lane on an extract operation. */ + adjust_extract (insn); + break; + case SH_SPLAT: + /* Change the lane on a direct-splat operation. */ + adjust_splat (insn); + break; + } +} + +/* Find the insn from the Ith table entry, which is known to be a + register swap Y = SWAP(X). Replace it with a copy Y = X. */ +static void +replace_swap_with_copy (swap_web_entry *insn_entry, unsigned i) +{ + rtx insn = insn_entry[i].insn; + rtx body = PATTERN (insn); + rtx src_reg = XEXP (SET_SRC (body), 0); + rtx copy = gen_rtx_SET (VOIDmode, SET_DEST (body), src_reg); + rtx new_insn = emit_insn_before (copy, insn); + set_block_for_insn (new_insn, BLOCK_FOR_INSN (insn)); + df_insn_rescan (new_insn); + + if (dump_file) + { + unsigned int new_uid = INSN_UID (new_insn); + fprintf (dump_file, "Replacing swap %d with copy %d\n", i, new_uid); + } + + df_insn_delete (insn); + remove_insn (insn); + INSN_DELETED_P (insn) = 1; +} + +/* Dump the swap table to DUMP_FILE. */ +static void +dump_swap_insn_table (swap_web_entry *insn_entry) +{ + int e = get_max_uid (); + fprintf (dump_file, "\nRelevant insns with their flag settings\n\n"); + + for (int i = 0; i < e; ++i) + if (insn_entry[i].is_relevant) + { + swap_web_entry *pred_entry = (swap_web_entry *)insn_entry[i].pred (); + fprintf (dump_file, "%6d %6d ", i, + pred_entry && pred_entry->insn + ? INSN_UID (pred_entry->insn) : 0); + if (insn_entry[i].is_load) + fputs ("load ", dump_file); + if (insn_entry[i].is_store) + fputs ("store ", dump_file); + if (insn_entry[i].is_swap) + fputs ("swap ", dump_file); + if (insn_entry[i].is_live_in) + fputs ("live-in ", dump_file); + if (insn_entry[i].is_live_out) + fputs ("live-out ", dump_file); + if (insn_entry[i].contains_subreg) + fputs ("subreg ", dump_file); + if (insn_entry[i].is_128_int) + fputs ("int128 ", dump_file); + if (insn_entry[i].is_call) + fputs ("call ", dump_file); + if (insn_entry[i].is_swappable) + { + fputs ("swappable ", dump_file); + if (insn_entry[i].special_handling == SH_CONST_VECTOR) + fputs ("special:constvec ", dump_file); + else if (insn_entry[i].special_handling == SH_SUBREG) + fputs ("special:subreg ", dump_file); + else if (insn_entry[i].special_handling == SH_NOSWAP_LD) + fputs ("special:load ", dump_file); + else if (insn_entry[i].special_handling == SH_NOSWAP_ST) + fputs ("special:store ", dump_file); + else if (insn_entry[i].special_handling == SH_EXTRACT) + fputs ("special:extract ", dump_file); + else if (insn_entry[i].special_handling == SH_SPLAT) + fputs ("special:splat ", dump_file); + } + if (insn_entry[i].web_not_optimizable) + fputs ("unoptimizable ", dump_file); + if (insn_entry[i].will_delete) + fputs ("delete ", dump_file); + fputs ("\n", dump_file); + } + fputs ("\n", dump_file); +} + +/* Main entry point for this pass. */ +unsigned int +rs6000_analyze_swaps (function *fun) +{ + swap_web_entry *insn_entry; + basic_block bb; + rtx insn; + + /* Dataflow analysis for use-def chains. */ + df_set_flags (DF_RD_PRUNE_DEAD_DEFS); + df_chain_add_problem (DF_DU_CHAIN | DF_UD_CHAIN); + df_analyze (); + df_set_flags (DF_DEFER_INSN_RESCAN); + + /* Allocate structure to represent webs of insns. */ + insn_entry = XCNEWVEC (swap_web_entry, get_max_uid ()); + + /* Walk the insns to gather basic data. */ + FOR_ALL_BB_FN (bb, fun) + FOR_BB_INSNS (bb, insn) + { + unsigned int uid = INSN_UID (insn); + if (NONDEBUG_INSN_P (insn)) + { + insn_entry[uid].insn = insn; + + if (GET_CODE (insn) == CALL_INSN) + insn_entry[uid].is_call = 1; + + /* Walk the uses and defs to see if we mention vector regs. + Record any constraints on optimization of such mentions. */ + df_ref *use_rec; + for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) + { + df_ref mention = *use_rec; + /* We use DF_REF_REAL_REG here to get inside any subregs. */ + machine_mode mode = GET_MODE (DF_REF_REAL_REG (mention)); + + /* If a use gets its value from a call insn, it will be + a hard register and will look like (reg:V4SI 3 3). + The df analysis creates two mentions for GPR3 and GPR4, + both DImode. We must recognize this and treat it as a + vector mention to ensure the call is unioned with this + use. */ + if (mode == DImode && DF_REF_INSN_INFO (mention)) + { + rtx feeder = DF_REF_INSN (mention); + /* FIXME: It is pretty hard to get from the df mention + to the mode of the use in the insn. We arbitrarily + pick a vector mode here, even though the use might + be a real DImode. We can be too conservative + (create a web larger than necessary) because of + this, so consider eventually fixing this. */ + if (GET_CODE (feeder) == CALL_INSN) + mode = V4SImode; + } + + if (VECTOR_MODE_P (mode) || mode == TImode) + { + insn_entry[uid].is_relevant = 1; + if (mode == TImode || mode == V1TImode) + insn_entry[uid].is_128_int = 1; + if (DF_REF_INSN_INFO (mention)) + insn_entry[uid].contains_subreg + = !rtx_equal_p (DF_REF_REG (mention), + DF_REF_REAL_REG (mention)); + union_defs (insn_entry, insn, mention); + } + } + df_ref *def_rec; + for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) + { + df_ref mention = *def_rec; + /* We use DF_REF_REAL_REG here to get inside any subregs. */ + machine_mode mode = GET_MODE (DF_REF_REAL_REG (mention)); + + /* If we're loading up a hard vector register for a call, + it looks like (set (reg:V4SI 9 9) (...)). The df + analysis creates two mentions for GPR9 and GPR10, both + DImode. So relying on the mode from the mentions + isn't sufficient to ensure we union the call into the + web with the parameter setup code. */ + if (mode == DImode && GET_CODE (insn) == SET + && VECTOR_MODE_P (GET_MODE (SET_DEST (insn)))) + mode = GET_MODE (SET_DEST (insn)); + + if (VECTOR_MODE_P (mode) || mode == TImode) + { + insn_entry[uid].is_relevant = 1; + if (mode == TImode || mode == V1TImode) + insn_entry[uid].is_128_int = 1; + if (DF_REF_INSN_INFO (mention)) + insn_entry[uid].contains_subreg + = !rtx_equal_p (DF_REF_REG (mention), + DF_REF_REAL_REG (mention)); + /* REG_FUNCTION_VALUE_P is not valid for subregs. */ + else if (REG_FUNCTION_VALUE_P (DF_REF_REG (mention))) + insn_entry[uid].is_live_out = 1; + union_uses (insn_entry, insn, mention); + } + } + + if (insn_entry[uid].is_relevant) + { + /* Determine if this is a load or store. */ + insn_entry[uid].is_load = insn_is_load_p (insn); + insn_entry[uid].is_store = insn_is_store_p (insn); + + /* Determine if this is a doubleword swap. If not, + determine whether it can legally be swapped. */ + if (insn_is_swap_p (insn)) + insn_entry[uid].is_swap = 1; + else + { + unsigned int special = SH_NONE; + insn_entry[uid].is_swappable + = insn_is_swappable_p (insn_entry, insn, &special); + if (special != SH_NONE && insn_entry[uid].contains_subreg) + insn_entry[uid].is_swappable = 0; + else if (special != SH_NONE) + insn_entry[uid].special_handling = special; + else if (insn_entry[uid].contains_subreg) + insn_entry[uid].special_handling = SH_SUBREG; + } + } + } + } + + if (dump_file) + { + fprintf (dump_file, "\nSwap insn entry table when first built\n"); + dump_swap_insn_table (insn_entry); + } + + /* Record unoptimizable webs. */ + unsigned e = get_max_uid (), i; + for (i = 0; i < e; ++i) + { + if (!insn_entry[i].is_relevant) + continue; + + swap_web_entry *root + = (swap_web_entry*)(&insn_entry[i])->unionfind_root (); + unsigned uid = INSN_UID (insn_entry[i].insn); + + if (insn_entry[i].is_live_in || insn_entry[i].is_live_out + || (insn_entry[i].contains_subreg + && insn_entry[i].special_handling != SH_SUBREG) + || insn_entry[i].is_128_int || insn_entry[i].is_call + || !(insn_entry[i].is_swappable || insn_entry[i].is_swap)) + root->web_not_optimizable = 1; + + /* If we have loads or stores that aren't permuting then the + optimization isn't appropriate. */ + else if ((insn_entry[i].is_load || insn_entry[i].is_store) + && !insn_entry[i].is_swap && !insn_entry[i].is_swappable) + root->web_not_optimizable = 1; + + /* If we have permuting loads or stores that are not accompanied + by a register swap, the optimization isn't appropriate. */ + else if (insn_entry[i].is_load && insn_entry[i].is_swap) + { + df_ref *def_rec; + + for (def_rec = DF_INSN_UID_DEFS (uid); *def_rec; def_rec++) + { + df_ref def = *def_rec; + struct df_link *link = DF_REF_CHAIN (def); + + if (!chain_contains_only_swaps (insn_entry, link, FOR_LOADS)) + { + root->web_not_optimizable = 1; + break; + } + } + } + else if (insn_entry[i].is_store && insn_entry[i].is_swap) + { + df_ref *use_rec; + + for (use_rec = DF_INSN_UID_USES (uid); *use_rec; use_rec++) + { + df_ref use = *use_rec; + struct df_link *link = DF_REF_CHAIN (use); + + if (!chain_contains_only_swaps (insn_entry, link, FOR_STORES)) + { + root->web_not_optimizable = 1; + break; + } + } + } + } + + if (dump_file) + { + fprintf (dump_file, "\nSwap insn entry table after web analysis\n"); + dump_swap_insn_table (insn_entry); + } + + /* For each load and store in an optimizable web (which implies + the loads and stores are permuting), find the associated + register swaps and mark them for removal. Due to various + optimizations we may mark the same swap more than once. Also + perform special handling for swappable insns that require it. */ + for (i = 0; i < e; ++i) + if ((insn_entry[i].is_load || insn_entry[i].is_store) + && insn_entry[i].is_swap) + { + swap_web_entry* root_entry + = (swap_web_entry*)((&insn_entry[i])->unionfind_root ()); + if (!root_entry->web_not_optimizable) + mark_swaps_for_removal (insn_entry, i); + } + else if (insn_entry[i].is_swappable && insn_entry[i].special_handling) + { + swap_web_entry* root_entry + = (swap_web_entry*)((&insn_entry[i])->unionfind_root ()); + if (!root_entry->web_not_optimizable) + handle_special_swappables (insn_entry, i); + } + + /* Now delete the swaps marked for removal. */ + for (i = 0; i < e; ++i) + if (insn_entry[i].will_delete) + replace_swap_with_copy (insn_entry, i); + + /* Clean up. */ + free (insn_entry); + return 0; +} + +const pass_data pass_data_analyze_swaps = +{ + RTL_PASS, /* type */ + "swaps", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + true, /* has_gate */ + true, /* has_execute */ + TV_NONE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_df_finish, /* todo_flags_finish */ +}; + +class pass_analyze_swaps : public rtl_opt_pass +{ +public: + pass_analyze_swaps(gcc::context *ctxt) + : rtl_opt_pass(pass_data_analyze_swaps, ctxt) + {} + + /* opt_pass methods: */ + bool gate () + { + return (optimize > 0 && !BYTES_BIG_ENDIAN && TARGET_VSX + && rs6000_optimize_swaps); + } + + unsigned int execute () + { + return rs6000_analyze_swaps (cfun); + } + +}; // class pass_analyze_swaps + +rtl_opt_pass * +make_pass_analyze_swaps (gcc::context *ctxt) +{ + return new pass_analyze_swaps (ctxt); +} struct gcc_target targetm = TARGET_INITIALIZER; diff --git a/gcc-4.9/gcc/config/rs6000/rs6000.md b/gcc-4.9/gcc/config/rs6000/rs6000.md index d078491e1..f77754aa1 100644 --- a/gcc-4.9/gcc/config/rs6000/rs6000.md +++ b/gcc-4.9/gcc/config/rs6000/rs6000.md @@ -137,6 +137,7 @@ UNSPEC_UNPACK_128BIT UNSPEC_PACK_128BIT UNSPEC_LSQ + UNSPEC_FUSION_GPR ]) ;; @@ -328,8 +329,25 @@ (define_mode_attr f32_sv [(SF "stxsspx %x1,%y0") (SD "stxsiwzx %x1,%y0")]) ; Definitions for 32-bit fpr direct move +; At present, the decimal modes are not allowed in the traditional altivec +; registers, so restrict the constraints to just the traditional FPRs. (define_mode_attr f32_dm [(SF "wn") (SD "wh")]) +; Definitions for 32-bit VSX +(define_mode_attr f32_vsx [(SF "ww") (SD "wn")]) + +; Definitions for 32-bit use of altivec registers +(define_mode_attr f32_av [(SF "wu") (SD "wn")]) + +; Definitions for 64-bit VSX +(define_mode_attr f64_vsx [(DF "ws") (DD "wn")]) + +; Definitions for 64-bit direct move +(define_mode_attr f64_dm [(DF "wk") (DD "wh")]) + +; Definitions for 64-bit use of altivec registers +(define_mode_attr f64_av [(DF "wv") (DD "wn")]) + ; These modes do not fit in integer registers in 32-bit mode. ; but on e500v2, the gpr are 64 bit registers (define_mode_iterator DIFD [DI (DF "!TARGET_E500_DOUBLE") DD]) @@ -435,7 +453,7 @@ ;; either. ;; Mode attribute for boolean operation register constraints for output -(define_mode_attr BOOL_REGS_OUTPUT [(TI "&r,r,r,wa,v") +(define_mode_attr BOOL_REGS_OUTPUT [(TI "&r,r,r,wt,v") (PTI "&r,r,r") (V16QI "wa,v,&?r,?r,?r") (V8HI "wa,v,&?r,?r,?r") @@ -446,7 +464,7 @@ (V1TI "wa,v,&?r,?r,?r")]) ;; Mode attribute for boolean operation register constraints for operand1 -(define_mode_attr BOOL_REGS_OP1 [(TI "r,0,r,wa,v") +(define_mode_attr BOOL_REGS_OP1 [(TI "r,0,r,wt,v") (PTI "r,0,r") (V16QI "wa,v,r,0,r") (V8HI "wa,v,r,0,r") @@ -457,7 +475,7 @@ (V1TI "wa,v,r,0,r")]) ;; Mode attribute for boolean operation register constraints for operand2 -(define_mode_attr BOOL_REGS_OP2 [(TI "r,r,0,wa,v") +(define_mode_attr BOOL_REGS_OP2 [(TI "r,r,0,wt,v") (PTI "r,r,0") (V16QI "wa,v,r,r,0") (V8HI "wa,v,r,r,0") @@ -470,7 +488,7 @@ ;; Mode attribute for boolean operation register constraints for operand1 ;; for one_cmpl. To simplify things, we repeat the constraint where 0 ;; is used for operand1 or operand2 -(define_mode_attr BOOL_REGS_UNARY [(TI "r,0,0,wa,v") +(define_mode_attr BOOL_REGS_UNARY [(TI "r,0,0,wt,v") (PTI "r,0,0") (V16QI "wa,v,r,0,0") (V8HI "wa,v,r,0,0") @@ -8582,8 +8600,8 @@ [(set (match_operand:BOOL_128 0 "vlogical_operand" "=") (match_operator:BOOL_128 3 "boolean_operator" [(not:BOOL_128 - (match_operand:BOOL_128 2 "vlogical_operand" "")) - (match_operand:BOOL_128 1 "vlogical_operand" "")]))] + (match_operand:BOOL_128 2 "vlogical_operand" "")) + (match_operand:BOOL_128 1 "vlogical_operand" "")]))] "TARGET_P8_VECTOR || (GET_CODE (operands[3]) == AND)" { if (TARGET_VSX && vsx_register_operand (operands[0], mode)) @@ -8598,7 +8616,7 @@ && reload_completed && int_reg_operand (operands[0], mode)" [(const_int 0)] { - rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, false, + rs6000_split_logical (operands, GET_CODE (operands[3]), false, false, true, NULL_RTX); DONE; } @@ -8620,14 +8638,14 @@ [(set (match_operand:TI2 0 "int_reg_operand" "=&r,r,r") (match_operator:TI2 3 "boolean_operator" [(not:TI2 - (match_operand:TI2 1 "int_reg_operand" "r,0,r")) - (match_operand:TI2 2 "int_reg_operand" "r,r,0")]))] + (match_operand:TI2 2 "int_reg_operand" "r,0,r")) + (match_operand:TI2 1 "int_reg_operand" "r,r,0")]))] "!TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)" "#" "reload_completed && !TARGET_P8_VECTOR && (GET_CODE (operands[3]) != AND)" [(const_int 0)] { - rs6000_split_logical (operands, GET_CODE (operands[3]), false, true, false, + rs6000_split_logical (operands, GET_CODE (operands[3]), false, false, true, NULL_RTX); DONE; } @@ -9188,8 +9206,8 @@ }") (define_insn "mov_hardfloat" - [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,wa,wa,,,wu,Z,?,?r,*c*l,!r,*h,!r,!r") - (match_operand:FMOVE32 1 "input_operand" "r,m,r,f,wa,j,,,Z,wu,r,,r,h,0,G,Fn"))] + [(set (match_operand:FMOVE32 0 "nonimmediate_operand" "=!r,!r,m,f,,,,,,Z,?,?r,*c*l,!r,*h,!r,!r") + (match_operand:FMOVE32 1 "input_operand" "r,m,r,f,,j,,,Z,,r,,r, h, 0, G,Fn"))] "(gpc_reg_operand (operands[0], mode) || gpc_reg_operand (operands[1], mode)) && (TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_SINGLE_FLOAT)" @@ -9390,8 +9408,8 @@ ;; reloading. (define_insn "*mov_hardfloat32" - [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,!r,!r,!r") - (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,G,H,F"))] + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,,Z,,,Y,r,!r,!r,!r,!r") + (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,,,j,r,Y,r,G,H,F"))] "! TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && (gpc_reg_operand (operands[0], mode) || gpc_reg_operand (operands[1], mode))" @@ -9459,8 +9477,8 @@ ; ld/std require word-aligned displacements -> 'Y' constraint. ; List Y->r and r->Y before r->r for reload. (define_insn "*mov_hardfloat64" - [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,wv,Z,wa,wa,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,wk") - (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,wv,wa,j,r,Y,r,r,h,0,G,H,F,wg,r,wk,r"))] + [(set (match_operand:FMOVE64 0 "nonimmediate_operand" "=m,d,d,,Z,,,Y,r,!r,*c*l,!r,*h,!r,!r,!r,r,wg,r,") + (match_operand:FMOVE64 1 "input_operand" "d,m,d,Z,,,j,r,Y,r,r,h,0,G,H,F,wg,r,,r"))] "TARGET_POWERPC64 && TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_DOUBLE_FLOAT && (gpc_reg_operand (operands[0], mode) || gpc_reg_operand (operands[1], mode))" @@ -15714,22 +15732,9 @@ ;; a GPR. The addis instruction must be adjacent to the load, and use the same ;; register that is being loaded. The fused ops must be physically adjacent. -;; We use define_peephole for the actual addis/load, and the register used to -;; hold the addis value must be the same as the register being loaded. We use -;; define_peephole2 to change the register used for addis to be the register -;; being loaded, since we can look at whether it is dead after the load insn. - -(define_peephole - [(set (match_operand:P 0 "base_reg_operand" "") - (match_operand:P 1 "fusion_gpr_addis" "")) - (set (match_operand:INT1 2 "base_reg_operand" "") - (match_operand:INT1 3 "fusion_gpr_mem_load" ""))] - "TARGET_P8_FUSION && fusion_gpr_load_p (operands, false)" -{ - return emit_fusion_gpr_load (operands); -} - [(set_attr "type" "load") - (set_attr "length" "8")]) +;; Find cases where the addis that feeds into a load instruction is either used +;; once or is the same as the target register, and replace it with the fusion +;; insn (define_peephole2 [(set (match_operand:P 0 "base_reg_operand" "") @@ -15737,15 +15742,28 @@ (set (match_operand:INT1 2 "base_reg_operand" "") (match_operand:INT1 3 "fusion_gpr_mem_load" ""))] "TARGET_P8_FUSION - && (REGNO (operands[0]) != REGNO (operands[2]) - || GET_CODE (operands[3]) == SIGN_EXTEND) - && fusion_gpr_load_p (operands, true)" + && fusion_gpr_load_p (operands[0], operands[1], operands[2], + operands[3])" [(const_int 0)] { expand_fusion_gpr_load (operands); DONE; }) +;; Fusion insn, created by the define_peephole2 above (and eventually by +;; reload) + +(define_insn "fusion_gpr_load_" + [(set (match_operand:INT1 0 "base_reg_operand" "=&b") + (unspec:INT1 [(match_operand:INT1 1 "fusion_gpr_mem_combo" "")] + UNSPEC_FUSION_GPR))] + "TARGET_P8_FUSION" +{ + return emit_fusion_gpr_load (operands[0], operands[1]); +} + [(set_attr "type" "load") + (set_attr "length" "8")]) + ;; Miscellaneous ISA 2.06 (power7) instructions (define_insn "addg6s" diff --git a/gcc-4.9/gcc/config/rs6000/rs6000.opt b/gcc-4.9/gcc/config/rs6000/rs6000.opt index 4c1a02a52..4d0d5e73d 100644 --- a/gcc-4.9/gcc/config/rs6000/rs6000.opt +++ b/gcc-4.9/gcc/config/rs6000/rs6000.opt @@ -588,3 +588,7 @@ Allow double variables in upper registers with -mcpu=power7 or -mvsx mupper-regs-sf Target Undocumented Mask(UPPER_REGS_SF) Var(rs6000_isa_flags) Allow float variables in upper registers with -mcpu=power8 or -mp8-vector + +moptimize-swaps +Target Undocumented Var(rs6000_optimize_swaps) Init(1) Save +Analyze and remove doubleword swaps from VSX computations. diff --git a/gcc-4.9/gcc/config/rs6000/rtems.h b/gcc-4.9/gcc/config/rs6000/rtems.h index 2402d5336..046488034 100644 --- a/gcc-4.9/gcc/config/rs6000/rtems.h +++ b/gcc-4.9/gcc/config/rs6000/rtems.h @@ -52,7 +52,8 @@ %{mcpu=750: %{!Dppc*: %{!Dmpc*: -Dmpc750} } } \ %{mcpu=821: %{!Dppc*: %{!Dmpc*: -Dmpc821} } } \ %{mcpu=860: %{!Dppc*: %{!Dmpc*: -Dmpc860} } } \ -%{mcpu=8540: %{!Dppc*: %{!Dmpc*: -Dppc8540} } }" +%{mcpu=8540: %{!Dppc*: %{!Dmpc*: -Dppc8540} } } \ +%{mcpu=e6500: -D__PPC_CPU_E6500__}" #undef SUBSUBTARGET_EXTRA_SPECS #define SUBSUBTARGET_EXTRA_SPECS \ diff --git a/gcc-4.9/gcc/config/rs6000/sysv4.h b/gcc-4.9/gcc/config/rs6000/sysv4.h index 7cc543319..9d456ddec 100644 --- a/gcc-4.9/gcc/config/rs6000/sysv4.h +++ b/gcc-4.9/gcc/config/rs6000/sysv4.h @@ -846,11 +846,6 @@ ncrtn.o%s" #define CPP_OS_OPENBSD_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_POSIX_THREADS}" #endif -/* These may be provided by rs6000/linux-grtev2.h. */ -#ifndef LINUX_GRTE_EXTRA_SPECS -#define LINUX_GRTE_EXTRA_SPECS -#endif - /* Define any extra SPECS that the compiler needs to generate. */ /* Override rs6000.h definition. */ #undef SUBTARGET_EXTRA_SPECS @@ -916,7 +911,6 @@ ncrtn.o%s" { "cpp_os_openbsd", CPP_OS_OPENBSD_SPEC }, \ { "cpp_os_default", CPP_OS_DEFAULT_SPEC }, \ { "fbsd_dynamic_linker", FBSD_DYNAMIC_LINKER }, \ - LINUX_GRTE_EXTRA_SPECS \ SUBSUBTARGET_EXTRA_SPECS #define SUBSUBTARGET_EXTRA_SPECS diff --git a/gcc-4.9/gcc/config/rs6000/t-rtems b/gcc-4.9/gcc/config/rs6000/t-rtems index 426f75ac5..eadda0d20 100644 --- a/gcc-4.9/gcc/config/rs6000/t-rtems +++ b/gcc-4.9/gcc/config/rs6000/t-rtems @@ -18,16 +18,24 @@ # along with GCC; see the file COPYING3. If not see # . -MULTILIB_OPTIONS = \ -mcpu=403/mcpu=505/mcpu=603e/mcpu=604/mcpu=860/mcpu=7400/mcpu=8540 \ -msoft-float/mfloat-gprs=double +MULTILIB_OPTIONS = +MULTILIB_DIRNAMES = +MULTILIB_MATCHES = +MULTILIB_EXCEPTIONS = +MULTILIB_REQUIRED = + +MULTILIB_OPTIONS += mcpu=403/mcpu=505/mcpu=603e/mcpu=604/mcpu=860/mcpu=7400/mcpu=8540/mcpu=e6500 +MULTILIB_DIRNAMES += m403 m505 m603e m604 m860 m7400 m8540 me6500 + +MULTILIB_OPTIONS += m32 +MULTILIB_DIRNAMES += m32 -MULTILIB_DIRNAMES = \ -m403 m505 m603e m604 m860 m7400 m8540 \ -nof gprsdouble +MULTILIB_OPTIONS += msoft-float/mfloat-gprs=double +MULTILIB_DIRNAMES += nof gprsdouble + +MULTILIB_OPTIONS += mno-spe/mno-altivec +MULTILIB_DIRNAMES += nospe noaltivec -# MULTILIB_MATCHES = ${MULTILIB_MATCHES_FLOAT} -MULTILIB_MATCHES = MULTILIB_MATCHES += ${MULTILIB_MATCHES_ENDIAN} MULTILIB_MATCHES += ${MULTILIB_MATCHES_SYSV} # Map 405 to 403 @@ -52,37 +60,20 @@ MULTILIB_MATCHES += mcpu?8540=mcpu?8548 # (mfloat-gprs=single is implicit default) MULTILIB_MATCHES += mcpu?8540=mcpu?8540/mfloat-gprs?single -# Soft-float only, default implies msoft-float -# NOTE: Must match with MULTILIB_MATCHES_FLOAT and MULTILIB_MATCHES -MULTILIB_SOFTFLOAT_ONLY = \ -*mcpu=401/*msoft-float* \ -*mcpu=403/*msoft-float* \ -*mcpu=405/*msoft-float* \ -*mcpu=801/*msoft-float* \ -*mcpu=821/*msoft-float* \ -*mcpu=823/*msoft-float* \ -*mcpu=860/*msoft-float* - -# Hard-float only, take out msoft-float -MULTILIB_HARDFLOAT_ONLY = \ -*mcpu=505/*msoft-float* - -# Targets which do not support gprs -MULTILIB_NOGPRS = \ -mfloat-gprs=* \ -*mcpu=403/*mfloat-gprs=* \ -*mcpu=505/*mfloat-gprs=* \ -*mcpu=603e/*mfloat-gprs=* \ -*mcpu=604/*mfloat-gprs=* \ -*mcpu=860/*mfloat-gprs=* \ -*mcpu=7400/*mfloat-gprs=* - -MULTILIB_EXCEPTIONS = - -# Disallow -Dppc and -Dmpc without other options -MULTILIB_EXCEPTIONS += Dppc* Dmpc* +# Enumeration of multilibs -MULTILIB_EXCEPTIONS += \ -${MULTILIB_SOFTFLOAT_ONLY} \ -${MULTILIB_HARDFLOAT_ONLY} \ -${MULTILIB_NOGPRS} +MULTILIB_REQUIRED += msoft-float +MULTILIB_REQUIRED += mcpu=403 +MULTILIB_REQUIRED += mcpu=505 +MULTILIB_REQUIRED += mcpu=603e +MULTILIB_REQUIRED += mcpu=603e/msoft-float +MULTILIB_REQUIRED += mcpu=604 +MULTILIB_REQUIRED += mcpu=604/msoft-float +MULTILIB_REQUIRED += mcpu=7400 +MULTILIB_REQUIRED += mcpu=7400/msoft-float +MULTILIB_REQUIRED += mcpu=8540 +MULTILIB_REQUIRED += mcpu=8540/msoft-float/mno-spe +MULTILIB_REQUIRED += mcpu=8540/mfloat-gprs=double +MULTILIB_REQUIRED += mcpu=860 +MULTILIB_REQUIRED += mcpu=e6500/m32 +MULTILIB_REQUIRED += mcpu=e6500/m32/msoft-float/mno-altivec diff --git a/gcc-4.9/gcc/config/rs6000/vsx.md b/gcc-4.9/gcc/config/rs6000/vsx.md index 2cf5e7a94..9aaf06428 100644 --- a/gcc-4.9/gcc/config/rs6000/vsx.md +++ b/gcc-4.9/gcc/config/rs6000/vsx.md @@ -260,6 +260,14 @@ UNSPEC_VSX_ROUND_IC UNSPEC_VSX_SLDWI UNSPEC_VSX_XXSPLTW + UNSPEC_VSX_XXSPLTD + UNSPEC_VSX_DIVSD + UNSPEC_VSX_DIVUD + UNSPEC_VSX_MULSD + UNSPEC_VSX_XVCVSXDDP + UNSPEC_VSX_XVCVUXDDP + UNSPEC_VSX_XVCVDPSXDS + UNSPEC_VSX_XVCVDPUXDS ]) ;; VSX moves @@ -746,6 +754,34 @@ [(set_attr "type" "") (set_attr "fp_type" "")]) +; Emulate vector with scalar for vec_mul in V2DImode +(define_insn_and_split "vsx_mul_v2di" + [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa") + (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa") + (match_operand:V2DI 2 "vsx_register_operand" "wa")] + UNSPEC_VSX_MULSD))] + "VECTOR_MEM_VSX_P (V2DImode)" + "#" + "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress" + [(const_int 0)] + " +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx op2 = operands[2]; + rtx op3 = gen_reg_rtx (DImode); + rtx op4 = gen_reg_rtx (DImode); + rtx op5 = gen_reg_rtx (DImode); + emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0))); + emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0))); + emit_insn (gen_muldi3 (op5, op3, op4)); + emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1))); + emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1))); + emit_insn (gen_muldi3 (op3, op3, op4)); + emit_insn (gen_vsx_concat_v2di (op0, op5, op3)); +}" + [(set_attr "type" "vecdouble")]) + (define_insn "*vsx_div3" [(set (match_operand:VSX_F 0 "vsx_register_operand" "=,?") (div:VSX_F (match_operand:VSX_F 1 "vsx_register_operand" ",") @@ -755,6 +791,61 @@ [(set_attr "type" "") (set_attr "fp_type" "")]) +; Emulate vector with scalar for vec_div in V2DImode +(define_insn_and_split "vsx_div_v2di" + [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa") + (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa") + (match_operand:V2DI 2 "vsx_register_operand" "wa")] + UNSPEC_VSX_DIVSD))] + "VECTOR_MEM_VSX_P (V2DImode)" + "#" + "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress" + [(const_int 0)] + " +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx op2 = operands[2]; + rtx op3 = gen_reg_rtx (DImode); + rtx op4 = gen_reg_rtx (DImode); + rtx op5 = gen_reg_rtx (DImode); + emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0))); + emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0))); + emit_insn (gen_divdi3 (op5, op3, op4)); + emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1))); + emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1))); + emit_insn (gen_divdi3 (op3, op3, op4)); + emit_insn (gen_vsx_concat_v2di (op0, op5, op3)); +}" + [(set_attr "type" "vecdiv")]) + +(define_insn_and_split "vsx_udiv_v2di" + [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa") + (unspec:V2DI [(match_operand:V2DI 1 "vsx_register_operand" "wa") + (match_operand:V2DI 2 "vsx_register_operand" "wa")] + UNSPEC_VSX_DIVUD))] + "VECTOR_MEM_VSX_P (V2DImode)" + "#" + "VECTOR_MEM_VSX_P (V2DImode) && !reload_completed && !reload_in_progress" + [(const_int 0)] + " +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx op2 = operands[2]; + rtx op3 = gen_reg_rtx (DImode); + rtx op4 = gen_reg_rtx (DImode); + rtx op5 = gen_reg_rtx (DImode); + emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (0))); + emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (0))); + emit_insn (gen_udivdi3 (op5, op3, op4)); + emit_insn (gen_vsx_extract_v2di (op3, op1, GEN_INT (1))); + emit_insn (gen_vsx_extract_v2di (op4, op2, GEN_INT (1))); + emit_insn (gen_udivdi3 (op3, op3, op4)); + emit_insn (gen_vsx_concat_v2di (op0, op5, op3)); +}" + [(set_attr "type" "vecdiv")]) + ;; *tdiv* instruction returning the FG flag (define_expand "vsx_tdiv3_fg" [(set (match_dup 3) @@ -904,11 +995,11 @@ ;; multiply. (define_insn "*vsx_fmav4sf4" - [(set (match_operand:V4SF 0 "vsx_register_operand" "=ws,ws,?wa,?wa,v") + [(set (match_operand:V4SF 0 "vsx_register_operand" "=wf,wf,?wa,?wa,v") (fma:V4SF - (match_operand:V4SF 1 "vsx_register_operand" "%ws,ws,wa,wa,v") - (match_operand:V4SF 2 "vsx_register_operand" "ws,0,wa,0,v") - (match_operand:V4SF 3 "vsx_register_operand" "0,ws,0,wa,v")))] + (match_operand:V4SF 1 "vsx_register_operand" "%wf,wf,wa,wa,v") + (match_operand:V4SF 2 "vsx_register_operand" "wf,0,wa,0,v") + (match_operand:V4SF 3 "vsx_register_operand" "0,wf,0,wa,v")))] "VECTOR_UNIT_VSX_P (V4SFmode)" "@ xvmaddasp %x0,%x1,%x2 @@ -919,11 +1010,11 @@ [(set_attr "type" "vecfloat")]) (define_insn "*vsx_fmav2df4" - [(set (match_operand:V2DF 0 "vsx_register_operand" "=ws,ws,?wa,?wa") + [(set (match_operand:V2DF 0 "vsx_register_operand" "=wd,wd,?wa,?wa") (fma:V2DF - (match_operand:V2DF 1 "vsx_register_operand" "%ws,ws,wa,wa") - (match_operand:V2DF 2 "vsx_register_operand" "ws,0,wa,0") - (match_operand:V2DF 3 "vsx_register_operand" "0,ws,0,wa")))] + (match_operand:V2DF 1 "vsx_register_operand" "%wd,wd,wa,wa") + (match_operand:V2DF 2 "vsx_register_operand" "wd,0,wa,0") + (match_operand:V2DF 3 "vsx_register_operand" "0,wd,0,wa")))] "VECTOR_UNIT_VSX_P (V2DFmode)" "@ xvmaddadp %x0,%x1,%x2 @@ -1268,6 +1359,102 @@ "xscvspdpn %x0,%x1" [(set_attr "type" "fp")]) +;; Convert and scale (used by vec_ctf, vec_cts, vec_ctu for double/long long) + +(define_expand "vsx_xvcvsxddp_scale" + [(match_operand:V2DF 0 "vsx_register_operand" "") + (match_operand:V2DI 1 "vsx_register_operand" "") + (match_operand:QI 2 "immediate_operand" "")] + "VECTOR_UNIT_VSX_P (V2DFmode)" +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + int scale = INTVAL(operands[2]); + emit_insn (gen_vsx_xvcvsxddp (op0, op1)); + if (scale != 0) + rs6000_scale_v2df (op0, op0, -scale); + DONE; +}) + +(define_insn "vsx_xvcvsxddp" + [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa") + (unspec:V2DF [(match_operand:V2DI 1 "vsx_register_operand" "wa")] + UNSPEC_VSX_XVCVSXDDP))] + "VECTOR_UNIT_VSX_P (V2DFmode)" + "xvcvsxddp %x0,%x1" + [(set_attr "type" "vecdouble")]) + +(define_expand "vsx_xvcvuxddp_scale" + [(match_operand:V2DF 0 "vsx_register_operand" "") + (match_operand:V2DI 1 "vsx_register_operand" "") + (match_operand:QI 2 "immediate_operand" "")] + "VECTOR_UNIT_VSX_P (V2DFmode)" +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + int scale = INTVAL(operands[2]); + emit_insn (gen_vsx_xvcvuxddp (op0, op1)); + if (scale != 0) + rs6000_scale_v2df (op0, op0, -scale); + DONE; +}) + +(define_insn "vsx_xvcvuxddp" + [(set (match_operand:V2DF 0 "vsx_register_operand" "=wa") + (unspec:V2DF [(match_operand:V2DI 1 "vsx_register_operand" "wa")] + UNSPEC_VSX_XVCVUXDDP))] + "VECTOR_UNIT_VSX_P (V2DFmode)" + "xvcvuxddp %x0,%x1" + [(set_attr "type" "vecdouble")]) + +(define_expand "vsx_xvcvdpsxds_scale" + [(match_operand:V2DI 0 "vsx_register_operand" "") + (match_operand:V2DF 1 "vsx_register_operand" "") + (match_operand:QI 2 "immediate_operand" "")] + "VECTOR_UNIT_VSX_P (V2DFmode)" +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx tmp = gen_reg_rtx (V2DFmode); + int scale = INTVAL(operands[2]); + if (scale != 0) + rs6000_scale_v2df (tmp, op1, scale); + emit_insn (gen_vsx_xvcvdpsxds (op0, tmp)); + DONE; +}) + +(define_insn "vsx_xvcvdpsxds" + [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa") + (unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")] + UNSPEC_VSX_XVCVDPSXDS))] + "VECTOR_UNIT_VSX_P (V2DFmode)" + "xvcvdpsxds %x0,%x1" + [(set_attr "type" "vecdouble")]) + +(define_expand "vsx_xvcvdpuxds_scale" + [(match_operand:V2DI 0 "vsx_register_operand" "") + (match_operand:V2DF 1 "vsx_register_operand" "") + (match_operand:QI 2 "immediate_operand" "")] + "VECTOR_UNIT_VSX_P (V2DFmode)" +{ + rtx op0 = operands[0]; + rtx op1 = operands[1]; + rtx tmp = gen_reg_rtx (V2DFmode); + int scale = INTVAL(operands[2]); + if (scale != 0) + rs6000_scale_v2df (tmp, op1, scale); + emit_insn (gen_vsx_xvcvdpuxds (op0, tmp)); + DONE; +}) + +(define_insn "vsx_xvcvdpuxds" + [(set (match_operand:V2DI 0 "vsx_register_operand" "=wa") + (unspec:V2DI [(match_operand:V2DF 1 "vsx_register_operand" "wa")] + UNSPEC_VSX_XVCVDPUXDS))] + "VECTOR_UNIT_VSX_P (V2DFmode)" + "xvcvdpuxds %x0,%x1" + [(set_attr "type" "vecdouble")]) + ;; Convert from 64-bit to 32-bit types ;; Note, favor the Altivec registers since the usual use of these instructions ;; is in vector converts and we need to use the Altivec vperm instruction. @@ -1359,8 +1546,8 @@ (define_insn "vsx_concat_" [(set (match_operand:VSX_D 0 "vsx_register_operand" "=,?") (vec_concat:VSX_D - (match_operand: 1 "vsx_register_operand" "ws,") - (match_operand: 2 "vsx_register_operand" "ws,")))] + (match_operand: 1 "vsx_register_operand" ",") + (match_operand: 2 "vsx_register_operand" ",")))] "VECTOR_MEM_VSX_P (mode)" { if (BYTES_BIG_ENDIAN) @@ -1647,7 +1834,7 @@ [(set (match_operand: 0 "register_operand" "=d,wv,wr") (vec_select: (match_operand:VSX_D 1 "memory_operand" "m,Z,m") - (parallel [(match_operand:QI 2 "vsx_scalar_64bit" "wD,wD,wD")])))] + (parallel [(const_int 0)])))] "VECTOR_MEM_VSX_P (mode)" "@ lfd%U1%X1 %0,%1 @@ -1921,6 +2108,22 @@ "xxspltw %x0,%x1,%2" [(set_attr "type" "vecperm")]) +;; V2DF/V2DI splat for use by vec_splat builtin +(define_insn "vsx_xxspltd_" + [(set (match_operand:VSX_D 0 "vsx_register_operand" "=wa") + (unspec:VSX_D [(match_operand:VSX_D 1 "vsx_register_operand" "wa") + (match_operand:QI 2 "u5bit_cint_operand" "i")] + UNSPEC_VSX_XXSPLTD))] + "VECTOR_MEM_VSX_P (mode)" +{ + if ((VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 0) + || (!VECTOR_ELT_ORDER_BIG && INTVAL (operands[2]) == 1)) + return "xxpermdi %x0,%x1,%x1,0"; + else + return "xxpermdi %x0,%x1,%x1,3"; +} + [(set_attr "type" "vecperm")]) + ;; V4SF/V4SI interleave (define_insn "vsx_xxmrghw_" [(set (match_operand:VSX_W 0 "vsx_register_operand" "=wf,?") @@ -2041,7 +2244,7 @@ ;; to the top element of the V2DF array without doing an extract. (define_insn_and_split "*vsx_reduc__v2df_scalar" - [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?wa,ws,?wa") + [(set (match_operand:DF 0 "vfloat_operand" "=&ws,&?ws,ws,?ws") (vec_select:DF (VEC_reduc:V2DF (vec_concat:V2DF diff --git a/gcc-4.9/gcc/config/rs6000/xcoff.h b/gcc-4.9/gcc/config/rs6000/xcoff.h index f2b7bd07a..10123313f 100644 --- a/gcc-4.9/gcc/config/rs6000/xcoff.h +++ b/gcc-4.9/gcc/config/rs6000/xcoff.h @@ -304,14 +304,15 @@ do { fputs (LOCAL_COMMON_ASM_OP, (FILE)); \ RS6000_OUTPUT_BASENAME ((FILE), (NAME)); \ if ((ALIGN) > 32) \ - fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%s,%u\n", \ + fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%s%u_,%u\n", \ (SIZE), xcoff_bss_section_name, \ + floor_log2 ((ALIGN) / BITS_PER_UNIT), \ floor_log2 ((ALIGN) / BITS_PER_UNIT)); \ else if ((SIZE) > 4) \ - fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%s,3\n", \ + fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%s3_,3\n", \ (SIZE), xcoff_bss_section_name); \ else \ - fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%s\n", \ + fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%s,2\n", \ (SIZE), xcoff_bss_section_name); \ } while (0) #endif diff --git a/gcc-4.9/gcc/config/rx/rx.c b/gcc-4.9/gcc/config/rx/rx.c index 4242c1a97..11a825cfa 100644 --- a/gcc-4.9/gcc/config/rx/rx.c +++ b/gcc-4.9/gcc/config/rx/rx.c @@ -733,7 +733,7 @@ rx_print_operand (FILE * file, rtx op, int letter) break; case 'R': - gcc_assert (GET_MODE_SIZE (GET_MODE (op)) < 4); + gcc_assert (GET_MODE_SIZE (GET_MODE (op)) <= 4); unsigned_load = true; /* Fall through. */ case 'Q': diff --git a/gcc-4.9/gcc/config/rx/rx.h b/gcc-4.9/gcc/config/rx/rx.h index d99b19ad2..06a0ae850 100644 --- a/gcc-4.9/gcc/config/rx/rx.h +++ b/gcc-4.9/gcc/config/rx/rx.h @@ -433,9 +433,9 @@ typedef unsigned int CUMULATIVE_ARGS; /* Compute the alignment needed for label X in various situations. If the user has specified an alignment then honour that, otherwise use rx_align_for_label. */ -#define JUMP_ALIGN(x) (align_jumps ? align_jumps : rx_align_for_label (x, 0)) -#define LABEL_ALIGN(x) (align_labels ? align_labels : rx_align_for_label (x, 3)) -#define LOOP_ALIGN(x) (align_loops ? align_loops : rx_align_for_label (x, 2)) +#define JUMP_ALIGN(x) (align_jumps > 1 ? align_jumps_log : rx_align_for_label (x, 0)) +#define LABEL_ALIGN(x) (align_labels > 1 ? align_labels_log : rx_align_for_label (x, 3)) +#define LOOP_ALIGN(x) (align_loops > 1 ? align_loops_log : rx_align_for_label (x, 2)) #define LABEL_ALIGN_AFTER_BARRIER(x) rx_align_for_label (x, 0) #define ASM_OUTPUT_MAX_SKIP_ALIGN(STREAM, LOG, MAX_SKIP) \ diff --git a/gcc-4.9/gcc/config/s390/s390.c b/gcc-4.9/gcc/config/s390/s390.c index aac8de848..866de858c 100644 --- a/gcc-4.9/gcc/config/s390/s390.c +++ b/gcc-4.9/gcc/config/s390/s390.c @@ -9130,11 +9130,14 @@ s390_emit_epilogue (bool sibcall) if (! sibcall) { /* Fetch return address from stack before load multiple, - this will do good for scheduling. */ - - if (cfun_frame_layout.save_return_addr_p - || (cfun_frame_layout.first_restore_gpr < BASE_REGNUM - && cfun_frame_layout.last_restore_gpr > RETURN_REGNUM)) + this will do good for scheduling. + + Only do this if we already decided that r14 needs to be + saved to a stack slot. (And not just because r14 happens to + be in between two GPRs which need saving.) Otherwise it + would be difficult to take that decision back in + s390_optimize_prologue. */ + if (cfun_gpr_save_slot (RETURN_REGNUM) == -1) { int return_regnum = find_unused_clobbered_reg(); if (!return_regnum) @@ -9149,6 +9152,12 @@ s390_emit_epilogue (bool sibcall) addr = gen_rtx_MEM (Pmode, addr); set_mem_alias_set (addr, get_frame_alias_set ()); emit_move_insn (return_reg, addr); + + /* Once we did that optimization we have to make sure + s390_optimize_prologue does not try to remove the + store of r14 since we will not be able to find the + load issued here. */ + cfun_frame_layout.save_return_addr_p = true; } } diff --git a/gcc-4.9/gcc/config/s390/s390.md b/gcc-4.9/gcc/config/s390/s390.md index b17c1fac8..10d7a5a6d 100644 --- a/gcc-4.9/gcc/config/s390/s390.md +++ b/gcc-4.9/gcc/config/s390/s390.md @@ -460,7 +460,7 @@ ;; This iterator and attribute allow to combine most atomic operations. (define_code_iterator ATOMIC [and ior xor plus minus mult]) (define_code_iterator ATOMIC_Z196 [and ior xor plus]) -(define_code_attr atomic [(and "and") (ior "ior") (xor "xor") +(define_code_attr atomic [(and "and") (ior "or") (xor "xor") (plus "add") (minus "sub") (mult "nand")]) (define_code_attr noxa [(and "n") (ior "o") (xor "x") (plus "a")]) diff --git a/gcc-4.9/gcc/config/sh/predicates.md b/gcc-4.9/gcc/config/sh/predicates.md index 73bb880d6..3af1f8a14 100644 --- a/gcc-4.9/gcc/config/sh/predicates.md +++ b/gcc-4.9/gcc/config/sh/predicates.md @@ -398,7 +398,7 @@ (define_predicate "general_extend_operand" (match_code "subreg,reg,mem,truncate") { - if (GET_CODE (op) == TRUNCATE) + if (reload_completed && GET_CODE (op) == TRUNCATE) return arith_operand (op, mode); if (MEM_P (op) || (GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))) diff --git a/gcc-4.9/gcc/config/sh/sh-mem.cc b/gcc-4.9/gcc/config/sh/sh-mem.cc index 45af23acb..e5ef165cf 100644 --- a/gcc-4.9/gcc/config/sh/sh-mem.cc +++ b/gcc-4.9/gcc/config/sh/sh-mem.cc @@ -1,5 +1,5 @@ /* Helper routines for memory move and comparison insns. - Copyright (C) 2013-2014 Free Software Foundation, Inc. + Copyright (C) 2013-2015 Free Software Foundation, Inc. This file is part of GCC. @@ -226,7 +226,7 @@ sh_expand_cmpstr (rtx *operands) emit_move_insn (tmp3, addr2); emit_move_insn (s2_addr, plus_constant (Pmode, s2_addr, 4)); - /*start long loop. */ + /* start long loop. */ emit_label (L_loop_long); emit_move_insn (tmp2, tmp3); @@ -335,7 +335,7 @@ sh_expand_cmpnstr (rtx *operands) rtx len = force_reg (SImode, operands[3]); int constp = CONST_INT_P (operands[3]); - /* Loop on a register count. */ + /* Loop on a register count. */ if (constp) { rtx tmp0 = gen_reg_rtx (SImode); @@ -364,7 +364,7 @@ sh_expand_cmpnstr (rtx *operands) add_int_reg_note (jump, REG_BR_PROB, prob_likely); } - /* word count. Do we have iterations ? */ + /* word count. Do we have iterations ? */ emit_insn (gen_lshrsi3 (lenw, len, GEN_INT (2))); /*start long loop. */ @@ -407,6 +407,7 @@ sh_expand_cmpnstr (rtx *operands) /* end loop. Reached max iterations. */ if (! sbytes) { + emit_insn (gen_subsi3 (operands[0], tmp1, tmp2)); jump = emit_jump_insn (gen_jump_compact (L_return)); emit_barrier_after (jump); } @@ -482,6 +483,13 @@ sh_expand_cmpnstr (rtx *operands) jump = emit_jump_insn (gen_jump_compact( L_end_loop_byte)); emit_barrier_after (jump); } + else + { + emit_insn (gen_cmpeqsi_t (len, const0_rtx)); + emit_move_insn (operands[0], const0_rtx); + jump = emit_jump_insn (gen_branch_true (L_return)); + add_int_reg_note (jump, REG_BR_PROB, prob_unlikely); + } addr1 = adjust_automodify_address (addr1, QImode, s1_addr, 0); addr2 = adjust_automodify_address (addr2, QImode, s2_addr, 0); @@ -522,14 +530,14 @@ sh_expand_cmpnstr (rtx *operands) emit_insn (gen_zero_extendqisi2 (tmp2, gen_lowpart (QImode, tmp2))); emit_insn (gen_zero_extendqisi2 (tmp1, gen_lowpart (QImode, tmp1))); - emit_label (L_return); - emit_insn (gen_subsi3 (operands[0], tmp1, tmp2)); + emit_label (L_return); + return true; } -/* Emit code to perform a strlen +/* Emit code to perform a strlen. OPERANDS[0] is the destination. OPERANDS[1] is the string. @@ -568,7 +576,7 @@ sh_expand_strlen (rtx *operands) addr1 = adjust_automodify_address (addr1, SImode, current_addr, 0); - /*start long loop. */ + /* start long loop. */ emit_label (L_loop_long); /* tmp1 is aligned, OK to load. */ diff --git a/gcc-4.9/gcc/config/sh/sh.c b/gcc-4.9/gcc/config/sh/sh.c index 3d4553a6e..06798181a 100644 --- a/gcc-4.9/gcc/config/sh/sh.c +++ b/gcc-4.9/gcc/config/sh/sh.c @@ -2957,7 +2957,7 @@ enum struct ashl_lshr_sequence { char insn_count; - char amount[6]; + signed char amount[6]; char clobbers_t; }; diff --git a/gcc-4.9/gcc/config/sh/sh.md b/gcc-4.9/gcc/config/sh/sh.md index ab1f0a51c..d957e5540 100644 --- a/gcc-4.9/gcc/config/sh/sh.md +++ b/gcc-4.9/gcc/config/sh/sh.md @@ -868,9 +868,9 @@ (define_insn "*cmp_div0s_0" [(set (reg:SI T_REG) - (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand") + (eq:SI (lshiftrt:SI (match_operand:SI 0 "arith_reg_operand" "%r") (const_int 31)) - (ge:SI (match_operand:SI 1 "arith_reg_operand") + (ge:SI (match_operand:SI 1 "arith_reg_operand" "r") (const_int 0))))] "TARGET_SH1" "div0s %0,%1" @@ -4563,6 +4563,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -4803,6 +4809,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -4896,6 +4908,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_ashrsi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -4995,6 +5013,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_ashrdi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -5069,6 +5093,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashlsi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_lshrsi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -5263,6 +5293,12 @@ label: { if (TARGET_SHMEDIA) { + if (CONST_INT_P (operands[2]) && INTVAL (operands[2]) < 0) + { + operands[2] = GEN_INT (-INTVAL (operands[2])); + emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2])); + DONE; + } emit_insn (gen_lshrdi3_media (operands[0], operands[1], operands[2])); DONE; } @@ -6295,10 +6331,9 @@ label: }) (define_expand "extendqihi2" - [(set (match_operand:HI 0 "arith_reg_dest" "") - (sign_extend:HI (match_operand:QI 1 "arith_reg_operand" "")))] - "" - "") + [(set (match_operand:HI 0 "arith_reg_dest") + (sign_extend:HI (match_operand:QI 1 "arith_reg_operand")))] + "TARGET_SH1") (define_insn "*extendqihi2_compact_reg" [(set (match_operand:HI 0 "arith_reg_dest" "=r") diff --git a/gcc-4.9/gcc/config/sh/sh_optimize_sett_clrt.cc b/gcc-4.9/gcc/config/sh/sh_optimize_sett_clrt.cc index 313e5b5f4..3791cc76c 100644 --- a/gcc-4.9/gcc/config/sh/sh_optimize_sett_clrt.cc +++ b/gcc-4.9/gcc/config/sh/sh_optimize_sett_clrt.cc @@ -111,7 +111,7 @@ private: // Given a start insn and its basic block, recursively determine all // possible ccreg values in all basic block paths that can lead to the // start insn. - void find_last_ccreg_values (rtx start_insn, basic_block bb, + bool find_last_ccreg_values (rtx start_insn, basic_block bb, std::vector& values_out, std::vector& prev_visited_bb) const; @@ -226,8 +226,8 @@ sh_optimize_sett_clrt::execute (void) ccreg_values.clear (); visited_bbs.clear (); - find_last_ccreg_values (PREV_INSN (i), bb, ccreg_values, - visited_bbs); + bool ok = find_last_ccreg_values (PREV_INSN (i), bb, ccreg_values, + visited_bbs); log_msg ("number of ccreg values collected: %u\n", (unsigned int)ccreg_values.size ()); @@ -235,7 +235,7 @@ sh_optimize_sett_clrt::execute (void) // If all the collected values are equal and are equal to the // constant value of the setcc insn, the setcc insn can be // removed. - if (all_ccreg_values_equal (ccreg_values) + if (ok && all_ccreg_values_equal (ccreg_values) && rtx_equal_p (ccreg_values.front ().value, setcc_val)) { log_msg ("all values are "); @@ -309,7 +309,7 @@ sh_optimize_sett_clrt gcc_unreachable (); } -void +bool sh_optimize_sett_clrt ::find_last_ccreg_values (rtx start_insn, basic_block bb, std::vector& values_out, @@ -348,7 +348,7 @@ sh_optimize_sett_clrt log_msg ("\n"); values_out.push_back (v); - return; + return true; } if (any_condjump_p (i) && onlyjump_p (i) && !prev_visited_bb.empty ()) @@ -372,7 +372,7 @@ sh_optimize_sett_clrt log_msg ("\n"); values_out.push_back (v); - return; + return true; } } @@ -393,10 +393,14 @@ sh_optimize_sett_clrt for (edge_iterator ei = ei_start (bb->preds); !ei_end_p (ei); ei_next (&ei)) { + if (ei_edge (ei)->flags & EDGE_COMPLEX) + log_return (false, "aborting due to complex edge\n"); + basic_block pred_bb = ei_edge (ei)->src; pred_bb_count += 1; - find_last_ccreg_values (BB_END (pred_bb), pred_bb, values_out, - prev_visited_bb); + if (!find_last_ccreg_values (BB_END (pred_bb), pred_bb, values_out, + prev_visited_bb)) + return false; } prev_visited_bb.pop_back (); @@ -419,6 +423,8 @@ sh_optimize_sett_clrt values_out.push_back (v); } + + return true; } bool diff --git a/gcc-4.9/gcc/config/sh/sh_treg_combine.cc b/gcc-4.9/gcc/config/sh/sh_treg_combine.cc index e73604022..38e28038d 100644 --- a/gcc-4.9/gcc/config/sh/sh_treg_combine.cc +++ b/gcc-4.9/gcc/config/sh/sh_treg_combine.cc @@ -78,14 +78,17 @@ Example 1) In [bb 4] elimination of the comparison would require inversion of the branch condition and compensation of other BBs. -Instead an inverting reg-move can be used: +Instead the comparison in [bb 3] can be replaced with the comparison in [bb 5] +by using a reg-reg move. In [bb 4] a logical not is used to compensate the +inverted condition. [bb 3] (set (reg:SI 167) (reg:SI 173)) -> bb 5 [BB 4] -(set (reg:SI 167) (not:SI (reg:SI 177))) +(set (reg:SI 147 t) (eq:SI (reg:SI 177) (const_int 0))) +(set (reg:SI 167) (reg:SI 147 t)) -> bb 5 [bb 5] @@ -214,9 +217,9 @@ In order to handle cases such as above the RTL pass does the following: and replace the comparisons in the BBs with reg-reg copies to get the operands in place (create new pseudo regs). - - If the cstores differ, try to apply the special case - (eq (reg) (const_int 0)) -> inverted = (not (reg)). - for the subordinate cstore types and eliminate the dominating ones. + - If the cstores differ and the comparison is a test against zero, + use reg-reg copies for the dominating cstores and logical not cstores + for the subordinate cstores. - If the comparison types in the BBs are not the same, or the first approach doesn't work out for some reason, try to eliminate the comparison before the @@ -558,7 +561,8 @@ private: bool can_extend_ccreg_usage (const bb_entry& e, const cbranch_trace& trace) const; - // Create an insn rtx that is a negating reg move (not operation). + // Create an insn rtx that performs a logical not (test != 0) on the src_reg + // and stores the result in dst_reg. rtx make_not_reg_insn (rtx dst_reg, rtx src_reg) const; // Create an insn rtx that inverts the ccreg. @@ -892,12 +896,32 @@ sh_treg_combine::can_remove_comparison (const bb_entry& e, rtx sh_treg_combine::make_not_reg_insn (rtx dst_reg, rtx src_reg) const { - // This will to go through expanders and may output multiple insns - // for multi-word regs. + // On SH we can do only SImode and DImode comparisons. + if (! (GET_MODE (src_reg) == SImode || GET_MODE (src_reg) == DImode)) + return NULL; + + // On SH we can store the ccreg into an SImode or DImode reg only. + if (! (GET_MODE (dst_reg) == SImode || GET_MODE (dst_reg) == DImode)) + return NULL; + start_sequence (); - expand_simple_unop (GET_MODE (dst_reg), NOT, src_reg, dst_reg, 0); + + emit_insn (gen_rtx_SET (VOIDmode, m_ccreg, + gen_rtx_fmt_ee (EQ, SImode, src_reg, const0_rtx))); + + if (GET_MODE (dst_reg) == SImode) + emit_move_insn (dst_reg, m_ccreg); + else if (GET_MODE (dst_reg) == DImode) + { + emit_move_insn (gen_lowpart (SImode, dst_reg), m_ccreg); + emit_move_insn (gen_highpart (SImode, dst_reg), const0_rtx); + } + else + gcc_unreachable (); + rtx i = get_insns (); end_sequence (); + return i; } @@ -1080,7 +1104,12 @@ sh_treg_combine::try_combine_comparisons (cbranch_trace& trace, // There is one special case though, where an integer comparison // (eq (reg) (const_int 0)) // can be inverted with a sequence - // (eq (not (reg)) (const_int 0)) + // (set (t) (eq (reg) (const_int 0)) + // (set (reg) (t)) + // (eq (reg) (const_int 0)) + // + // FIXME: On SH2A it might be better to use the nott insn in this case, + // i.e. do the try_eliminate_cstores approach instead. if (inv_cstore_count != 0 && cstore_count != 0) { if (make_not_reg_insn (comp_op0, comp_op0) == NULL_RTX) diff --git a/gcc-4.9/gcc/config/sh/sync.md b/gcc-4.9/gcc/config/sh/sync.md index a0a22a1f5..a3acaac56 100644 --- a/gcc-4.9/gcc/config/sh/sync.md +++ b/gcc-4.9/gcc/config/sh/sync.md @@ -466,6 +466,7 @@ (set (mem:SI (match_dup 1)) (unspec:SI [(match_operand:SI 2 "arith_operand" "rI08")] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG))] "TARGET_ATOMIC_HARD_LLCS || (TARGET_SH4A_ARCH && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)" @@ -484,6 +485,7 @@ (set (mem:QIHI (match_dup 1)) (unspec:QIHI [(match_operand:QIHI 2 "register_operand" "r")] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG)) (clobber (match_scratch:SI 3 "=&r")) (clobber (match_scratch:SI 4 "=1"))] @@ -617,6 +619,7 @@ [(FETCHOP:SI (mem:SI (match_dup 1)) (match_operand:SI 2 "" ""))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG))] "TARGET_ATOMIC_HARD_LLCS || (TARGET_SH4A_ARCH && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)" @@ -637,6 +640,7 @@ [(FETCHOP:QIHI (mem:QIHI (match_dup 1)) (match_operand:QIHI 2 "" ""))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG)) (clobber (match_scratch:SI 3 "=&r")) (clobber (match_scratch:SI 4 "=1"))] @@ -784,6 +788,7 @@ [(not:SI (and:SI (mem:SI (match_dup 1)) (match_operand:SI 2 "logical_operand" "rK08")))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG))] "TARGET_ATOMIC_HARD_LLCS || (TARGET_SH4A_ARCH && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)" @@ -805,6 +810,7 @@ [(not:QIHI (and:QIHI (mem:QIHI (match_dup 1)) (match_operand:QIHI 2 "logical_operand" "rK08")))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG)) (clobber (match_scratch:SI 3 "=&r")) (clobber (match_scratch:SI 4 "=1"))] @@ -903,7 +909,7 @@ " and %0,%3" "\n" " not %3,%3" "\n" " mov. %3,@%1" "\n" - " stc %4,sr"; + " ldc %4,sr"; } [(set_attr "length" "20")]) @@ -960,7 +966,8 @@ (set (mem:SI (match_dup 1)) (unspec:SI [(FETCHOP:SI (mem:SI (match_dup 1)) (match_dup 2))] - UNSPEC_ATOMIC))] + UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1))] "TARGET_ATOMIC_HARD_LLCS || (TARGET_SH4A_ARCH && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)" { @@ -980,6 +987,7 @@ (unspec:QIHI [(FETCHOP:QIHI (mem:QIHI (match_dup 1)) (match_dup 2))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG)) (clobber (match_scratch:SI 3 "=&r")) (clobber (match_scratch:SI 4 "=1"))] @@ -1124,7 +1132,8 @@ (set (mem:SI (match_dup 1)) (unspec:SI [(not:SI (and:SI (mem:SI (match_dup 1)) (match_dup 2)))] - UNSPEC_ATOMIC))] + UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1))] "TARGET_ATOMIC_HARD_LLCS || (TARGET_SH4A_ARCH && TARGET_ATOMIC_ANY && !TARGET_ATOMIC_STRICT)" { @@ -1145,6 +1154,7 @@ (unspec:QIHI [(not:QIHI (and:QIHI (mem:QIHI (match_dup 1)) (match_dup 2)))] UNSPEC_ATOMIC)) + (set (reg:SI T_REG) (const_int 1)) (clobber (reg:SI R0_REG)) (clobber (match_scratch:SI 3 "=&r")) (clobber (match_scratch:SI 4 "=1"))] @@ -1353,7 +1363,7 @@ " ldc r0,sr" "\n" " mov.b @%0,r0" "\n" " mov.b %1,@%0" "\n" - " stc %2,sr" "\n" + " ldc %2,sr" "\n" " tst r0,r0"; } [(set_attr "length" "16")]) diff --git a/gcc-4.9/gcc/config/sparc/leon.md b/gcc-4.9/gcc/config/sparc/leon.md index 82b6a0d96..ad22e3b59 100644 --- a/gcc-4.9/gcc/config/sparc/leon.md +++ b/gcc-4.9/gcc/config/sparc/leon.md @@ -29,11 +29,11 @@ ;; Use a double reservation to work around the load pipeline hazard on UT699. (define_insn_reservation "leon3_load" 1 - (and (eq_attr "cpu" "leon3") (eq_attr "type" "load,sload")) + (and (eq_attr "cpu" "leon3,leon3v7") (eq_attr "type" "load,sload")) "leon_memory*2") (define_insn_reservation "leon_store" 2 - (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "store")) + (and (eq_attr "cpu" "leon,leon3,leon3v7") (eq_attr "type" "store")) "leon_memory*2") ;; This describes Gaisler Research's FPU @@ -44,21 +44,21 @@ (define_cpu_unit "grfpu_ds" "grfpu") (define_insn_reservation "leon_fp_alu" 4 - (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fp,fpcmp,fpmul")) + (and (eq_attr "cpu" "leon,leon3,leon3v7") (eq_attr "type" "fp,fpcmp,fpmul")) "grfpu_alu, nothing*3") (define_insn_reservation "leon_fp_divs" 16 - (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpdivs")) + (and (eq_attr "cpu" "leon,leon3,leon3v7") (eq_attr "type" "fpdivs")) "grfpu_ds*14, nothing*2") (define_insn_reservation "leon_fp_divd" 17 - (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpdivd")) + (and (eq_attr "cpu" "leon,leon3,leon3v7") (eq_attr "type" "fpdivd")) "grfpu_ds*15, nothing*2") (define_insn_reservation "leon_fp_sqrts" 24 - (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpsqrts")) + (and (eq_attr "cpu" "leon,leon3,leon3v7") (eq_attr "type" "fpsqrts")) "grfpu_ds*22, nothing*2") (define_insn_reservation "leon_fp_sqrtd" 25 - (and (eq_attr "cpu" "leon,leon3") (eq_attr "type" "fpsqrtd")) + (and (eq_attr "cpu" "leon,leon3,leon3v7") (eq_attr "type" "fpsqrtd")) "grfpu_ds*23, nothing*2") diff --git a/gcc-4.9/gcc/config/sparc/linux.h b/gcc-4.9/gcc/config/sparc/linux.h index c54ba2cb5..c40bb0b78 100644 --- a/gcc-4.9/gcc/config/sparc/linux.h +++ b/gcc-4.9/gcc/config/sparc/linux.h @@ -147,12 +147,6 @@ do { \ /* Static stack checking is supported by means of probes. */ #define STACK_CHECK_STATIC_BUILTIN 1 -/* Linux currently uses RMO in uniprocessor mode, which is equivalent to - TMO, and TMO in multiprocessor mode. But they reserve the right to - change their minds. */ -#undef SPARC_RELAXED_ORDERING -#define SPARC_RELAXED_ORDERING true - #undef NEED_INDICATE_EXEC_STACK #define NEED_INDICATE_EXEC_STACK 1 diff --git a/gcc-4.9/gcc/config/sparc/linux64.h b/gcc-4.9/gcc/config/sparc/linux64.h index f00fb42ff..12bb3780b 100644 --- a/gcc-4.9/gcc/config/sparc/linux64.h +++ b/gcc-4.9/gcc/config/sparc/linux64.h @@ -261,12 +261,6 @@ do { \ /* Static stack checking is supported by means of probes. */ #define STACK_CHECK_STATIC_BUILTIN 1 -/* Linux currently uses RMO in uniprocessor mode, which is equivalent to - TMO, and TMO in multiprocessor mode. But they reserve the right to - change their minds. */ -#undef SPARC_RELAXED_ORDERING -#define SPARC_RELAXED_ORDERING true - #undef NEED_INDICATE_EXEC_STACK #define NEED_INDICATE_EXEC_STACK 1 diff --git a/gcc-4.9/gcc/config/sparc/sparc-opts.h b/gcc-4.9/gcc/config/sparc/sparc-opts.h index 13b375ae1..26017edc0 100644 --- a/gcc-4.9/gcc/config/sparc/sparc-opts.h +++ b/gcc-4.9/gcc/config/sparc/sparc-opts.h @@ -31,6 +31,7 @@ enum processor_type { PROCESSOR_HYPERSPARC, PROCESSOR_LEON, PROCESSOR_LEON3, + PROCESSOR_LEON3V7, PROCESSOR_SPARCLITE, PROCESSOR_F930, PROCESSOR_F934, diff --git a/gcc-4.9/gcc/config/sparc/sparc.c b/gcc-4.9/gcc/config/sparc/sparc.c index 5b00cca47..f7fc957b4 100644 --- a/gcc-4.9/gcc/config/sparc/sparc.c +++ b/gcc-4.9/gcc/config/sparc/sparc.c @@ -786,9 +786,6 @@ char sparc_hard_reg_printed[8]; #define TARGET_ATTRIBUTE_TABLE sparc_attribute_table #endif -#undef TARGET_RELAXED_ORDERING -#define TARGET_RELAXED_ORDERING SPARC_RELAXED_ORDERING - #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE sparc_option_override @@ -1246,6 +1243,7 @@ sparc_option_override (void) { TARGET_CPU_hypersparc, PROCESSOR_HYPERSPARC }, { TARGET_CPU_leon, PROCESSOR_LEON }, { TARGET_CPU_leon3, PROCESSOR_LEON3 }, + { TARGET_CPU_leon3v7, PROCESSOR_LEON3V7 }, { TARGET_CPU_sparclite, PROCESSOR_F930 }, { TARGET_CPU_sparclite86x, PROCESSOR_SPARCLITE86X }, { TARGET_CPU_sparclet, PROCESSOR_TSC701 }, @@ -1274,6 +1272,7 @@ sparc_option_override (void) { "hypersparc", MASK_ISA, MASK_V8|MASK_FPU }, { "leon", MASK_ISA, MASK_V8|MASK_LEON|MASK_FPU }, { "leon3", MASK_ISA, MASK_V8|MASK_LEON3|MASK_FPU }, + { "leon3v7", MASK_ISA, MASK_LEON3|MASK_FPU }, { "sparclite", MASK_ISA, MASK_SPARCLITE }, /* The Fujitsu MB86930 is the original sparclite chip, with no FPU. */ { "f930", MASK_ISA|MASK_FPU, MASK_SPARCLITE }, @@ -1526,6 +1525,7 @@ sparc_option_override (void) sparc_costs = &leon_costs; break; case PROCESSOR_LEON3: + case PROCESSOR_LEON3V7: sparc_costs = &leon3_costs; break; case PROCESSOR_SPARCLET: @@ -6801,28 +6801,30 @@ function_arg_union_value (int size, enum machine_mode mode, int slotno, } /* Used by function_arg and sparc_function_value_1 to implement the conventions - for passing and returning large (BLKmode) vectors. + for passing and returning BLKmode vectors. Return an expression valid as a return value for the FUNCTION_ARG and TARGET_FUNCTION_VALUE. - SIZE is the size in bytes of the vector (at least 8 bytes). + SIZE is the size in bytes of the vector. REGNO is the FP hard register the vector will be passed in. */ static rtx function_arg_vector_value (int size, int regno) { - int i, nregs = size / 8; - rtx regs; - - regs = gen_rtx_PARALLEL (BLKmode, rtvec_alloc (nregs)); + const int nregs = MAX (1, size / 8); + rtx regs = gen_rtx_PARALLEL (BLKmode, rtvec_alloc (nregs)); - for (i = 0; i < nregs; i++) - { + if (size < 8) + XVECEXP (regs, 0, 0) + = gen_rtx_EXPR_LIST (VOIDmode, + gen_rtx_REG (SImode, regno), + const0_rtx); + else + for (int i = 0; i < nregs; i++) XVECEXP (regs, 0, i) = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (DImode, regno + 2*i), GEN_INT (i*8)); - } return regs; } @@ -6868,10 +6870,9 @@ sparc_function_arg_1 (cumulative_args_t cum_v, enum machine_mode mode, || (TARGET_ARCH64 && size <= 16)); if (mode == BLKmode) - return function_arg_vector_value (size, - SPARC_FP_ARG_FIRST + 2*slotno); - else - mclass = MODE_FLOAT; + return function_arg_vector_value (size, SPARC_FP_ARG_FIRST + 2*slotno); + + mclass = MODE_FLOAT; } if (TARGET_ARCH32) @@ -7315,10 +7316,9 @@ sparc_function_value_1 (const_tree type, enum machine_mode mode, || (TARGET_ARCH64 && size <= 32)); if (mode == BLKmode) - return function_arg_vector_value (size, - SPARC_FP_ARG_FIRST); - else - mclass = MODE_FLOAT; + return function_arg_vector_value (size, SPARC_FP_ARG_FIRST); + + mclass = MODE_FLOAT; } if (TARGET_ARCH64 && type) diff --git a/gcc-4.9/gcc/config/sparc/sparc.h b/gcc-4.9/gcc/config/sparc/sparc.h index dd2b5ad9c..87f1d82d6 100644 --- a/gcc-4.9/gcc/config/sparc/sparc.h +++ b/gcc-4.9/gcc/config/sparc/sparc.h @@ -106,17 +106,6 @@ extern enum cmodel sparc_cmodel; #define SPARC_DEFAULT_CMODEL CM_32 -/* The SPARC-V9 architecture defines a relaxed memory ordering model (RMO) - which requires the following macro to be true if enabled. Prior to V9, - there are no instructions to even talk about memory synchronization. - Note that the UltraSPARC III processors don't implement RMO, unlike the - UltraSPARC II processors. Niagara, Niagara-2, and Niagara-3 do not - implement RMO either. - - Default to false; for example, Solaris never enables RMO, only ever uses - total memory ordering (TMO). */ -#define SPARC_RELAXED_ORDERING false - /* Do not use the .note.GNU-stack convention by default. */ #define NEED_INDICATE_EXEC_STACK 0 @@ -137,21 +126,22 @@ extern enum cmodel sparc_cmodel; #define TARGET_CPU_hypersparc 3 #define TARGET_CPU_leon 4 #define TARGET_CPU_leon3 5 -#define TARGET_CPU_sparclite 6 -#define TARGET_CPU_f930 6 /* alias */ -#define TARGET_CPU_f934 6 /* alias */ -#define TARGET_CPU_sparclite86x 7 -#define TARGET_CPU_sparclet 8 -#define TARGET_CPU_tsc701 8 /* alias */ -#define TARGET_CPU_v9 9 /* generic v9 implementation */ -#define TARGET_CPU_sparcv9 9 /* alias */ -#define TARGET_CPU_sparc64 9 /* alias */ -#define TARGET_CPU_ultrasparc 10 -#define TARGET_CPU_ultrasparc3 11 -#define TARGET_CPU_niagara 12 -#define TARGET_CPU_niagara2 13 -#define TARGET_CPU_niagara3 14 -#define TARGET_CPU_niagara4 15 +#define TARGET_CPU_leon3v7 6 +#define TARGET_CPU_sparclite 7 +#define TARGET_CPU_f930 7 /* alias */ +#define TARGET_CPU_f934 7 /* alias */ +#define TARGET_CPU_sparclite86x 8 +#define TARGET_CPU_sparclet 9 +#define TARGET_CPU_tsc701 9 /* alias */ +#define TARGET_CPU_v9 10 /* generic v9 implementation */ +#define TARGET_CPU_sparcv9 10 /* alias */ +#define TARGET_CPU_sparc64 10 /* alias */ +#define TARGET_CPU_ultrasparc 11 +#define TARGET_CPU_ultrasparc3 12 +#define TARGET_CPU_niagara 13 +#define TARGET_CPU_niagara2 14 +#define TARGET_CPU_niagara3 15 +#define TARGET_CPU_niagara4 16 #if TARGET_CPU_DEFAULT == TARGET_CPU_v9 \ || TARGET_CPU_DEFAULT == TARGET_CPU_ultrasparc \ @@ -239,6 +229,11 @@ extern enum cmodel sparc_cmodel; #define ASM_CPU32_DEFAULT_SPEC AS_LEON_FLAG #endif +#if TARGET_CPU_DEFAULT == TARGET_CPU_leon3v7 +#define CPP_CPU32_DEFAULT_SPEC "-D__leon__" +#define ASM_CPU32_DEFAULT_SPEC AS_LEONV7_FLAG +#endif + #endif #if !defined(CPP_CPU32_DEFAULT_SPEC) || !defined(CPP_CPU64_DEFAULT_SPEC) @@ -285,6 +280,7 @@ extern enum cmodel sparc_cmodel; %{mcpu=hypersparc:-D__hypersparc__ -D__sparc_v8__} \ %{mcpu=leon:-D__leon__ -D__sparc_v8__} \ %{mcpu=leon3:-D__leon__ -D__sparc_v8__} \ +%{mcpu=leon3v7:-D__leon__} \ %{mcpu=v9:-D__sparc_v9__} \ %{mcpu=ultrasparc:-D__sparc_v9__} \ %{mcpu=ultrasparc3:-D__sparc_v9__} \ @@ -334,6 +330,7 @@ extern enum cmodel sparc_cmodel; %{mcpu=hypersparc:-Av8} \ %{mcpu=leon:" AS_LEON_FLAG "} \ %{mcpu=leon3:" AS_LEON_FLAG "} \ +%{mcpu=leon3v7:" AS_LEONV7_FLAG "} \ %{mv8plus:-Av8plus} \ %{mcpu=v9:-Av9} \ %{mcpu=ultrasparc:%{!mv8plus:-Av9a}} \ @@ -1760,8 +1757,10 @@ extern int sparc_indent_opcode; #ifdef HAVE_AS_LEON #define AS_LEON_FLAG "-Aleon" +#define AS_LEONV7_FLAG "-Aleon" #else #define AS_LEON_FLAG "-Av8" +#define AS_LEONV7_FLAG "-Av7" #endif /* We use gcc _mcount for profiling. */ diff --git a/gcc-4.9/gcc/config/sparc/sparc.md b/gcc-4.9/gcc/config/sparc/sparc.md index 76c331597..954c297fd 100644 --- a/gcc-4.9/gcc/config/sparc/sparc.md +++ b/gcc-4.9/gcc/config/sparc/sparc.md @@ -221,6 +221,7 @@ hypersparc, leon, leon3, + leon3v7, sparclite, f930, f934, diff --git a/gcc-4.9/gcc/config/sparc/sparc.opt b/gcc-4.9/gcc/config/sparc/sparc.opt index 64e40955a..3cd2b603a 100644 --- a/gcc-4.9/gcc/config/sparc/sparc.opt +++ b/gcc-4.9/gcc/config/sparc/sparc.opt @@ -152,6 +152,9 @@ Enum(sparc_processor_type) String(leon) Value(PROCESSOR_LEON) EnumValue Enum(sparc_processor_type) String(leon3) Value(PROCESSOR_LEON3) +EnumValue +Enum(sparc_processor_type) String(leon3v7) Value(PROCESSOR_LEON3V7) + EnumValue Enum(sparc_processor_type) String(sparclite) Value(PROCESSOR_SPARCLITE) diff --git a/gcc-4.9/gcc/config/sparc/t-rtems b/gcc-4.9/gcc/config/sparc/t-rtems index 86a230261..ae7a33ab4 100644 --- a/gcc-4.9/gcc/config/sparc/t-rtems +++ b/gcc-4.9/gcc/config/sparc/t-rtems @@ -17,6 +17,15 @@ # . # -MULTILIB_OPTIONS = msoft-float mcpu=v8/mcpu=leon3 -MULTILIB_DIRNAMES = soft v8 leon3 +MULTILIB_OPTIONS = msoft-float mcpu=v8/mcpu=leon3/mcpu=leon3v7 muser-mode +MULTILIB_DIRNAMES = soft v8 leon3 leon3v7 user-mode MULTILIB_MATCHES = msoft-float=mno-fpu + +MULTILIB_EXCEPTIONS = muser-mode +MULTILIB_EXCEPTIONS += mcpu=leon3 +MULTILIB_EXCEPTIONS += mcpu=leon3v7 +MULTILIB_EXCEPTIONS += msoft-float/mcpu=leon3 +MULTILIB_EXCEPTIONS += msoft-float/mcpu=leon3v7 +MULTILIB_EXCEPTIONS += msoft-float/muser-mode +MULTILIB_EXCEPTIONS += msoft-float/mcpu=v8/muser-mode +MULTILIB_EXCEPTIONS += mcpu=v8/muser-mode diff --git a/gcc-4.9/gcc/configure b/gcc-4.9/gcc/configure index 3e62398ee..cb1d3004f 100755 --- a/gcc-4.9/gcc/configure +++ b/gcc-4.9/gcc/configure @@ -17990,7 +17990,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 17984 "configure" +#line 17993 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -18096,7 +18096,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 18090 "configure" +#line 18099 "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -27008,6 +27008,53 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_pie" >&5 $as_echo "$gcc_cv_ld_pie" >&6; } +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking linker PIE support with copy reloc" >&5 +$as_echo_n "checking linker PIE support with copy reloc... " >&6; } +gcc_cv_ld_pie_copyreloc=no +if test $gcc_cv_ld_pie = yes ; then + if test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then + gcc_cv_ld_pie_copyreloc=yes + fi + elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then + # Check if linker supports -pie option with copy reloc + case "$target" in + i?86-*-linux* | x86_64-*-linux*) + cat > conftest1.s < conftest2.s < /dev/null 2>&1 \ + && $gcc_cv_ld -shared -melf_x86_64 -o conftest1.so conftest1.o > /dev/null 2>&1 \ + && $gcc_cv_as --64 -o conftest2.o conftest2.s > /dev/null 2>&1 \ + && $gcc_cv_ld -pie -melf_x86_64 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then + gcc_cv_ld_pie_copyreloc=yes + fi + rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s + ;; + esac + fi +fi + +cat >>confdefs.h <<_ACEOF +#define HAVE_LD_PIE_COPYRELOC `if test x"$gcc_cv_ld_pie_copyreloc" = xyes; then echo 1; else echo 0; fi` +_ACEOF + +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_ld_pie_copyreloc" >&5 +$as_echo "$gcc_cv_ld_pie_copyreloc" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking linker EH-compatible garbage collection of sections" >&5 $as_echo_n "checking linker EH-compatible garbage collection of sections... " >&6; } gcc_cv_ld_eh_gc_sections=no @@ -27989,7 +28036,47 @@ if test "x${CLOOGLIBS}" != "x" ; then $as_echo "#define HAVE_cloog 1" >>confdefs.h + + # Check whether isl_schedule_constraints_compute_schedule is available; + # it's new in ISL-0.13. + saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $ISLINC" + saved_LIBS="$LIBS" + LIBS="$LIBS $CLOOGLIBS $ISLLIBS $GMPLIBS" + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking Checking for isl_schedule_constraints_compute_schedule" >&5 +$as_echo_n "checking Checking for isl_schedule_constraints_compute_schedule... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +isl_schedule_constraints_compute_schedule (NULL); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_has_isl_schedule_constraints_compute_schedule=yes +else + ac_has_isl_schedule_constraints_compute_schedule=no fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_has_isl_schedule_constraints_compute_schedule" >&5 +$as_echo "$ac_has_isl_schedule_constraints_compute_schedule" >&6; } + + LIBS="$saved_LIBS" + CFLAGS="$saved_CFLAGS" + + if test x"$ac_has_isl_schedule_constraints_compute_schedule" = x"yes"; then + +$as_echo "#define HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE 1" >>confdefs.h + + fi +fi + # Check for plugin support # Check whether --enable-plugin was given. diff --git a/gcc-4.9/gcc/configure.ac b/gcc-4.9/gcc/configure.ac index 0918ff324..a871103ff 100644 --- a/gcc-4.9/gcc/configure.ac +++ b/gcc-4.9/gcc/configure.ac @@ -4709,6 +4709,49 @@ if test x"$gcc_cv_ld_pie" = xyes; then fi AC_MSG_RESULT($gcc_cv_ld_pie) +AC_MSG_CHECKING(linker PIE support with copy reloc) +gcc_cv_ld_pie_copyreloc=no +if test $gcc_cv_ld_pie = yes ; then + if test $in_tree_ld = yes ; then + if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 25 -o "$gcc_cv_gld_major_version" -gt 2; then + gcc_cv_ld_pie_copyreloc=yes + fi + elif test x$gcc_cv_as != x -a x$gcc_cv_ld != x ; then + # Check if linker supports -pie option with copy reloc + case "$target" in + i?86-*-linux* | x86_64-*-linux*) + cat > conftest1.s < conftest2.s < /dev/null 2>&1 \ + && $gcc_cv_ld -shared -melf_x86_64 -o conftest1.so conftest1.o > /dev/null 2>&1 \ + && $gcc_cv_as --64 -o conftest2.o conftest2.s > /dev/null 2>&1 \ + && $gcc_cv_ld -pie -melf_x86_64 -o conftest conftest2.o conftest1.so > /dev/null 2>&1; then + gcc_cv_ld_pie_copyreloc=yes + fi + rm -f conftest conftest1.so conftest1.o conftest2.o conftest1.s conftest2.s + ;; + esac + fi +fi +AC_DEFINE_UNQUOTED(HAVE_LD_PIE_COPYRELOC, + [`if test x"$gcc_cv_ld_pie_copyreloc" = xyes; then echo 1; else echo 0; fi`], + [Define 0/1 if your linker supports -pie option with copy reloc.]) +AC_MSG_RESULT($gcc_cv_ld_pie_copyreloc) + AC_MSG_CHECKING(linker EH-compatible garbage collection of sections) gcc_cv_ld_eh_gc_sections=no if test $in_tree_ld = yes ; then @@ -5569,8 +5612,31 @@ AC_ARG_VAR(CLOOGLIBS,[How to link CLOOG]) AC_ARG_VAR(CLOOGINC,[How to find CLOOG include files]) if test "x${CLOOGLIBS}" != "x" ; then AC_DEFINE(HAVE_cloog, 1, [Define if cloog is in use.]) + + # Check whether isl_schedule_constraints_compute_schedule is available; + # it's new in ISL-0.13. + saved_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $ISLINC" + saved_LIBS="$LIBS" + LIBS="$LIBS $CLOOGLIBS $ISLLIBS $GMPLIBS" + + AC_MSG_CHECKING([Checking for isl_schedule_constraints_compute_schedule]) + AC_TRY_LINK([#include ], + [isl_schedule_constraints_compute_schedule (NULL);], + [ac_has_isl_schedule_constraints_compute_schedule=yes], + [ac_has_isl_schedule_constraints_compute_schedule=no]) + AC_MSG_RESULT($ac_has_isl_schedule_constraints_compute_schedule) + + LIBS="$saved_LIBS" + CFLAGS="$saved_CFLAGS" + + if test x"$ac_has_isl_schedule_constraints_compute_schedule" = x"yes"; then + AC_DEFINE(HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE, 1, + [Define if isl_schedule_constraints_compute_schedule exists.]) + fi fi + # Check for plugin support AC_ARG_ENABLE(plugin, [AS_HELP_STRING([--enable-plugin], [enable plugin support])], diff --git a/gcc-4.9/gcc/convert.c b/gcc-4.9/gcc/convert.c index 91c1da265..cb57b29e0 100644 --- a/gcc-4.9/gcc/convert.c +++ b/gcc-4.9/gcc/convert.c @@ -97,6 +97,15 @@ convert_to_real (tree type, tree expr) enum built_in_function fcode = builtin_mathfn_code (expr); tree itype = TREE_TYPE (expr); + if (TREE_CODE (expr) == COMPOUND_EXPR) + { + tree t = convert_to_real (type, TREE_OPERAND (expr, 1)); + if (t == TREE_OPERAND (expr, 1)) + return expr; + return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t), + TREE_OPERAND (expr, 0), t); + } + /* Disable until we figure out how to decide whether the functions are present in runtime. */ /* Convert (float)sqrt((double)x) where x is float into sqrtf(x) */ @@ -403,6 +412,15 @@ convert_to_integer (tree type, tree expr) return error_mark_node; } + if (ex_form == COMPOUND_EXPR) + { + tree t = convert_to_integer (type, TREE_OPERAND (expr, 1)); + if (t == TREE_OPERAND (expr, 1)) + return expr; + return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, TREE_TYPE (t), + TREE_OPERAND (expr, 0), t); + } + /* Convert e.g. (long)round(d) -> lround(d). */ /* If we're converting to char, we may encounter differing behavior between converting from double->char vs double->long->char. @@ -891,6 +909,14 @@ convert_to_complex (tree type, tree expr) if (TYPE_MAIN_VARIANT (elt_type) == TYPE_MAIN_VARIANT (subtype)) return expr; + else if (TREE_CODE (expr) == COMPOUND_EXPR) + { + tree t = convert_to_complex (type, TREE_OPERAND (expr, 1)); + if (t == TREE_OPERAND (expr, 1)) + return expr; + return build2_loc (EXPR_LOCATION (expr), COMPOUND_EXPR, + TREE_TYPE (t), TREE_OPERAND (expr, 0), t); + } else if (TREE_CODE (expr) == COMPLEX_EXPR) return fold_build2 (COMPLEX_EXPR, type, convert (subtype, TREE_OPERAND (expr, 0)), diff --git a/gcc-4.9/gcc/coverage.c b/gcc-4.9/gcc/coverage.c index bfc5731ff..93f394d84 100644 --- a/gcc-4.9/gcc/coverage.c +++ b/gcc-4.9/gcc/coverage.c @@ -177,6 +177,10 @@ static unsigned num_cpp_defines = 0; static struct str_list *cpp_includes_head = NULL, *cpp_includes_tail = NULL; static unsigned num_cpp_includes = 0; +/* List of lines read from -fprofile-generate-buildinfo=filename. */ +struct str_list *build_info_array_head = NULL, *build_info_array_tail = NULL; +static unsigned num_build_info = 0; + /* True if the current module has any asm statements. */ static bool has_asm_statement; @@ -805,6 +809,25 @@ read_counts_file (const char *da_file_name, unsigned module_id) sum.ctrs[GCOV_COUNTER_ARCS].histogram); new_summary = 0; } + else if (tag == GCOV_TAG_BUILD_INFO) + { + /* Build info strings are not used by the compiler, read and + ignore. */ + gcov_unsigned_t num_strings; + char **build_info_strings = gcov_read_build_info (length, + &num_strings); + for (unsigned i = 0; i < num_strings; i++) + free (build_info_strings[i]); + free (build_info_strings); + } + else if (tag == GCOV_TAG_COMDAT_ZERO_FIXUP) + { + /* Zero-profile fixup flags are not used by the compiler, read and + ignore. */ + gcov_unsigned_t num_fn; + int *zero_fixup_flags = gcov_read_comdat_zero_fixup (length, &num_fn); + free (zero_fixup_flags); + } else if (GCOV_TAG_IS_COUNTER (tag) && fn_ident) { counts_entry_t **slot, *entry, elt; @@ -1761,6 +1784,7 @@ build_info_type (tree type, tree fn_info_ptr_type) { tree field, fields = NULL_TREE; tree merge_fn_type, mod_type; + tree string_type, string_ptr_type; /* Version ident */ field = build_decl (BUILTINS_LOCATION, FIELD_DECL, NULL_TREE, @@ -1828,6 +1852,17 @@ build_info_type (tree type, tree fn_info_ptr_type) DECL_CHAIN (field) = fields; fields = field; + /* build_info string array */ + string_type = build_pointer_type ( + build_qualified_type (char_type_node, + TYPE_QUAL_CONST)); + string_ptr_type = build_pointer_type + (build_qualified_type (string_type, TYPE_QUAL_CONST)); + field = build_decl (BUILTINS_LOCATION, FIELD_DECL, + NULL_TREE, string_ptr_type); + DECL_CHAIN (field) = fields; + fields = field; + finish_builtin_struct (type, "__gcov_info", fields, NULL_TREE); } @@ -2227,6 +2262,96 @@ build_gcov_module_info_value (tree mod_type) return mod_info; } +/* Returns the value of the build info string read earlier. */ + +static tree +build_gcov_build_info_value (void) +{ + tree build_info; + tree value = NULL_TREE; + tree string_type, index_type, string_array_type; + vec *v = NULL; + char name_buf[50]; + + string_type = build_pointer_type ( + build_qualified_type (char_type_node, + TYPE_QUAL_CONST)); + index_type = build_index_type (build_int_cst (NULL_TREE, num_build_info)); + string_array_type = build_array_type (string_type, index_type); + + build_str_array_value (string_type, &v, + build_info_array_head); + value = build_constructor (string_array_type, v); + + build_info = build_decl (BUILTINS_LOCATION, VAR_DECL, + NULL_TREE, TREE_TYPE (value)); + TREE_STATIC (build_info) = 1; + ASM_GENERATE_INTERNAL_LABEL (name_buf, "BUILDINFO", 0); + DECL_NAME (build_info) = get_identifier (name_buf); + DECL_INITIAL (build_info) = value; + + /* Build structure. */ + varpool_finalize_decl (build_info); + + return build_info; +} + +/* Add S to the end of the string-list, the head and tail of which are + pointed-to by HEAD and TAIL, respectively. */ + +static void +str_list_append (struct str_list **head, struct str_list **tail, const char *s) +{ + struct str_list *e = XNEW (struct str_list); + e->str = XNEWVEC (char, strlen (s) + 1); + strcpy (e->str, s); + e->next = NULL; + if (*tail) + (*tail)->next = e; + else + *head = e; + *tail = e; +} + +/* Read file specified to -fprofile-generate-buildinfo=filename option and + create a list of strings to include in build_info array. */ + +static void +read_buildinfo (void) +{ + char buf[1024]; + FILE *buildinfo = fopen (flag_profile_generate_buildinfo, "r"); + if (!buildinfo) + { + error ("could not open -fprofile-generate-buildinfo file %qs: %m", + flag_profile_generate_buildinfo); + } + + while (fgets (buf, sizeof buf, buildinfo) != NULL) + { + /* Remove end of line. */ + int len = strlen (buf); + if (len >= 1 && buf[len - 1] =='\n') + buf[len - 1] = '\0'; + str_list_append (&build_info_array_head, &build_info_array_tail, buf); + num_build_info++; + } + /* Terminate with an empty string. */ + str_list_append (&build_info_array_head, &build_info_array_tail, ""); + num_build_info++; + if (ferror (buildinfo)) + { + error ("error reading -fprofile-generate-buildinfo file %qs: %m", + flag_profile_generate_buildinfo); + } + + if (fclose (buildinfo)) + { + error ("could not close -fprofile-generate-buildinfo file %qs: %m", + flag_profile_generate_buildinfo); + } +} + /* Returns a CONSTRUCTOR for the gcov_info object. INFO_TYPE is the gcov_info structure type, FN_ARY is the array of pointers to function info objects. */ @@ -2238,6 +2363,7 @@ build_info (tree info_type, tree fn_ary) tree merge_fn_type, n_funcs; unsigned ix; tree mod_value = NULL_TREE; + tree buildinfo_value = NULL_TREE; tree filename_string; int da_file_name_len; vec *v1 = NULL; @@ -2320,6 +2446,20 @@ build_info (tree info_type, tree fn_ary) build1 (ADDR_EXPR, TREE_TYPE (info_fields), fn_ary)); info_fields = DECL_CHAIN (info_fields); + /* build_info string array */ + if (flag_profile_generate_buildinfo) + read_buildinfo (); + if (num_build_info) + { + buildinfo_value = build_gcov_build_info_value (); + CONSTRUCTOR_APPEND_ELT (v1, info_fields, + build1 (ADDR_EXPR, TREE_TYPE (info_fields), + buildinfo_value)); + } + else + CONSTRUCTOR_APPEND_ELT (v1, info_fields, null_pointer_node); + info_fields = DECL_CHAIN (info_fields); + gcc_assert (!info_fields); return build_constructor (info_type, v1); } @@ -2846,22 +2986,9 @@ coverage_finish (void) da_file_name = NULL; } -/* Add S to the end of the string-list, the head and tail of which are - pointed-to by HEAD and TAIL, respectively. */ +extern bool is_kernel_build; -static void -str_list_append (struct str_list **head, struct str_list **tail, const char *s) -{ - struct str_list *e = XNEW (struct str_list); - e->str = XNEWVEC (char, strlen (s) + 1); - strcpy (e->str, s); - e->next = NULL; - if (*tail) - (*tail)->next = e; - else - *head = e; - *tail = e; -} +#define KERNEL_BUILD_PREDEF_STRING "__KERNEL__" /* Copies the macro def or undef CPP_DEF and saves the copy in a list. IS_DEF is a flag indicating if CPP_DEF represents @@ -2875,6 +3002,11 @@ coverage_note_define (const char *cpp_def, bool is_def) strcpy (s + 1, cpp_def); str_list_append (&cpp_defines_head, &cpp_defines_tail, s); num_cpp_defines++; + + /* When -D__KERNEL__ is in the option list, we assume this is + compilation for Linux Kernel. */ + if (!strcmp(cpp_def, KERNEL_BUILD_PREDEF_STRING)) + is_kernel_build = is_def; } /* Copies the -imacro/-include FILENAME and saves the copy in a list. */ diff --git a/gcc-4.9/gcc/cp/ChangeLog b/gcc-4.9/gcc/cp/ChangeLog index 0c7ab3320..8fcbbe653 100644 --- a/gcc-4.9/gcc/cp/ChangeLog +++ b/gcc-4.9/gcc/cp/ChangeLog @@ -1,3 +1,134 @@ +2015-01-07 Jason Merrill + + PR c++/64487 + * semantics.c (finish_offsetof): Handle templates here. + * parser.c (cp_parser_builtin_offsetof): Not here. + + PR c++/64352 + * pt.c (tsubst_copy_and_build): Pass complain to mark_used. + + PR c++/64251 + * decl2.c (mark_used): Don't mark if in_template_function. + + PR c++/64297 + * typeck.c (apply_memfn_quals): Correct wrong TYPE_CANONICAL. + + PR c++/64029 + * decl.c (grok_reference_init): Complete array type. + + PR c++/63657 + PR c++/38958 + * call.c (set_up_extended_ref_temp): Set TREE_USED on the reference + if the temporary has a non-trivial destructor. + * decl.c (poplevel): Don't look through references. + + PR c++/63658 + * pt.c (convert_nontype_argument): Call convert_from_reference. + (check_instantiated_arg): Don't be confused by reference refs. + (unify): Look through reference refs on the arg, too. + * mangle.c (write_template_arg): Look through reference refs. + +2014-12-19 Paolo Carlini + + PR c++/60955 + * pt.c (struct warning_sentinel): Move it... + * cp-tree.h: ... here. + * semantics.c (force_paren_expr): Use it. + +2014-11-21 Jason Merrill + + PR c++/63849 + * mangle.c (decl_mangling_context): Use template_type_parameter_p. + +2014-11-11 Paolo Carlini + + PR c++/63265 + * pt.c (tsubst_copy_and_build, case COND_EXPR): Maybe fold to + constant the condition. + +2014-10-30 Release Manager + + * GCC 4.9.2 released. + +2014-10-15 Jason Merrill + + PR c++/63455 + Revert: + * parser.c (cp_parser_abort_tentative_parse): Make sure we haven't + committed to this tentative parse. + +2014-10-09 Jason Merrill + + PR c++/63415 + * pt.c (value_dependent_expression_p) [CONSTRUCTOR]: Check the type. + (iterative_hash_template_arg): Likewise. + + PR c++/63437 + * cp-tree.h (REF_PARENTHESIZED_P): Also allow INDIRECT_REF. + * semantics.c (force_paren_expr): And set it. + * typeck.c (check_return_expr): And handle it. + +2014-10-08 Jason Merrill + + PR c++/63405 + * pt.c (tsubst_pack_expansion): Limit simple expansion to type packs. + +2014-09-25 Jakub Jelinek + + PR c++/63249 + * semantics.c (handle_omp_array_sections_1): Call mark_rvalue_use + on low_bound and length. + +2014-09-22 Paolo Carlini + + PR c++/62219 + * pt.c (check_default_tmpl_args): Check LAMBDA_FUNCTION_P. + +2014-09-19 Jason Merrill + + PR c++/61465 + * call.c (convert_like_real) [ck_identity]: Call mark_rvalue_use + after pulling out an element from a CONSTRUCTOR. + +2014-09-18 Jakub Jelinek + + PR c++/63248 + * semantics.c (finish_omp_clauses): Don't call cp_omp_mappable_type + on type of type dependent expressions, and don't call it if + handle_omp_array_sections has kept TREE_LIST because something + was type dependent. + * pt.c (tsubst_expr) : + Use keep_next_level, begin_omp_structured_block and + finish_omp_structured_block instead of push_stmt_list and + pop_stmt_list. + +2014-09-10 Jason Merrill + + PR c++/63139 + * pt.c (tsubst_pack_expansion): Simplify substitution into T.... + +2014-09-09 Jason Merrill + + PR lto/53808 + PR c++/61659 + * decl2.c (note_comdat_fn): New. + (set_comdat): New. + (cp_write_global_declarations): Call set_comdat. + * method.c (implicitly_declare_fn): Call note_comdat_fn. + * pt.c (tsubst_decl) [FUNCTION_DECL]: Likewise. + * decl2.c (mark_needed): Mark clones. + (import_export_decl): Not here. + + PR c++/61214 + PR c++/62224 + * decl2.c (decl_needed_p): Revert virtual functions change. + +2014-09-05 Jason Merrill + + PR c++/62659 + * semantics.c (potential_constant_expression_1): Handle un-folded + pointer to member constants. + 2014-08-26 Jason Merrill PR c++/58624 diff --git a/gcc-4.9/gcc/cp/call.c b/gcc-4.9/gcc/cp/call.c index 223188a51..db43bf10d 100644 --- a/gcc-4.9/gcc/cp/call.c +++ b/gcc-4.9/gcc/cp/call.c @@ -6094,7 +6094,6 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, return expr; } case ck_identity: - expr = mark_rvalue_use (expr); if (BRACE_ENCLOSED_INITIALIZER_P (expr)) { int nelts = CONSTRUCTOR_NELTS (expr); @@ -6105,6 +6104,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum, else gcc_unreachable (); } + expr = mark_rvalue_use (expr); if (type_unknown_p (expr)) expr = instantiate_type (totype, expr, complain); @@ -9412,6 +9412,10 @@ set_up_extended_ref_temp (tree decl, tree expr, vec **cleanups, /* Check whether the dtor is callable. */ cxx_maybe_build_cleanup (var, tf_warning_or_error); } + /* Avoid -Wunused-variable warning (c++/38958). */ + if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type) + && TREE_CODE (decl) == VAR_DECL) + TREE_USED (decl) = DECL_READ_P (decl) = true; *initp = init; return var; diff --git a/gcc-4.9/gcc/cp/cp-tree.h b/gcc-4.9/gcc/cp/cp-tree.h index b062b9733..ac60ad5b9 100644 --- a/gcc-4.9/gcc/cp/cp-tree.h +++ b/gcc-4.9/gcc/cp/cp-tree.h @@ -101,7 +101,7 @@ c-common.h, not after. TARGET_EXPR_DIRECT_INIT_P (in TARGET_EXPR) FNDECL_USED_AUTO (in FUNCTION_DECL) DECLTYPE_FOR_LAMBDA_PROXY (in DECLTYPE_TYPE) - REF_PARENTHESIZED_P (in COMPONENT_REF, SCOPE_REF) + REF_PARENTHESIZED_P (in COMPONENT_REF, INDIRECT_REF) AGGR_INIT_ZERO_FIRST (in AGGR_INIT_EXPR) 3: (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). ICS_BAD_FLAG (in _CONV) @@ -1099,6 +1099,18 @@ struct GTY(()) saved_scope { #define processing_specialization scope_chain->x_processing_specialization #define processing_explicit_instantiation scope_chain->x_processing_explicit_instantiation +/* RAII sentinel to disable certain warnings during template substitution + and elsewhere. */ + +struct warning_sentinel +{ + int &flag; + int val; + warning_sentinel(int& flag, bool suppress=true) + : flag(flag), val(flag) { if (suppress) flag = 0; } + ~warning_sentinel() { flag = val; } +}; + /* The cached class binding level, from the most recently exited class, or NULL if none. */ @@ -3039,11 +3051,12 @@ extern void decl_shadowed_for_var_insert (tree, tree); #define PAREN_STRING_LITERAL_P(NODE) \ TREE_LANG_FLAG_0 (STRING_CST_CHECK (NODE)) -/* Indicates whether a COMPONENT_REF has been parenthesized. Currently - only set some of the time in C++14 mode. */ +/* Indicates whether a COMPONENT_REF has been parenthesized, or an + INDIRECT_REF comes from parenthesizing a VAR_DECL. Currently only set + some of the time in C++14 mode. */ #define REF_PARENTHESIZED_P(NODE) \ - TREE_LANG_FLAG_2 (COMPONENT_REF_CHECK (NODE)) + TREE_LANG_FLAG_2 (TREE_CHECK2 ((NODE), COMPONENT_REF, INDIRECT_REF)) /* Nonzero if this AGGR_INIT_EXPR provides for initialization via a constructor call, rather than an ordinary function call. */ @@ -5352,12 +5365,13 @@ extern bool mark_used (tree, tsubst_flags_t); extern void finish_static_data_member_decl (tree, tree, bool, tree, int); extern tree cp_build_parm_decl (tree, tree); extern tree get_guard (tree); -extern tree get_guard_cond (tree); +extern tree get_guard_cond (tree, bool); extern tree set_guard (tree); extern tree get_tls_wrapper_fn (tree); extern void mark_needed (tree); extern bool decl_needed_p (tree); extern void note_vague_linkage_fn (tree); +extern void note_comdat_fn (tree); extern tree build_artificial_parm (tree, tree); extern bool possibly_inlined_p (tree); extern int parm_index (tree); diff --git a/gcc-4.9/gcc/cp/decl.c b/gcc-4.9/gcc/cp/decl.c index df4813deb..50faaebc6 100644 --- a/gcc-4.9/gcc/cp/decl.c +++ b/gcc-4.9/gcc/cp/decl.c @@ -632,8 +632,7 @@ poplevel (int keep, int reverse, int functionbody) push_local_binding where the list of decls returned by getdecls is built. */ decl = TREE_CODE (d) == TREE_LIST ? TREE_VALUE (d) : d; - // See through references for improved -Wunused-variable (PR 38958). - tree type = non_reference (TREE_TYPE (decl)); + tree type = TREE_TYPE (decl); if (VAR_P (decl) && (! TREE_USED (decl) || !DECL_READ_P (decl)) && ! DECL_IN_SYSTEM_HEADER (decl) @@ -4822,11 +4821,26 @@ grok_reference_init (tree decl, tree type, tree init, int flags) init = build_x_compound_expr_from_list (init, ELK_INIT, tf_warning_or_error); - if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE + tree ttype = TREE_TYPE (type); + if (TREE_CODE (ttype) != ARRAY_TYPE && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) /* Note: default conversion is only called in very special cases. */ init = decay_conversion (init, tf_warning_or_error); + /* check_initializer handles this for non-reference variables, but for + references we need to do it here or the initializer will get the + incomplete array type and confuse later calls to + cp_complete_array_type. */ + if (TREE_CODE (ttype) == ARRAY_TYPE + && TYPE_DOMAIN (ttype) == NULL_TREE + && (BRACE_ENCLOSED_INITIALIZER_P (init) + || TREE_CODE (init) == STRING_CST)) + { + cp_complete_array_type (&ttype, init, false); + if (ttype != TREE_TYPE (type)) + type = cp_build_reference_type (ttype, TYPE_REF_IS_RVALUE (type)); + } + /* Convert INIT to the reference type TYPE. This may involve the creation of a temporary, whose lifetime must be the same as that of the reference. If so, a DECL_EXPR for the temporary will be @@ -7021,7 +7035,7 @@ expand_static_init (tree decl, tree init) looks like: static guard; - if (!guard.first_byte) { + if (!__atomic_load (guard.first_byte)) { if (__cxa_guard_acquire (&guard)) { bool flag = false; try { @@ -7051,16 +7065,11 @@ expand_static_init (tree decl, tree init) /* Create the guard variable. */ guard = get_guard (decl); - /* This optimization isn't safe on targets with relaxed memory - consistency. On such targets we force synchronization in - __cxa_guard_acquire. */ - if (!targetm.relaxed_ordering || !thread_guard) - { - /* Begin the conditional initialization. */ - if_stmt = begin_if_stmt (); - finish_if_stmt_cond (get_guard_cond (guard), if_stmt); - then_clause = begin_compound_stmt (BCS_NO_SCOPE); - } + /* Begin the conditional initialization. */ + if_stmt = begin_if_stmt (); + + finish_if_stmt_cond (get_guard_cond (guard, thread_guard), if_stmt); + then_clause = begin_compound_stmt (BCS_NO_SCOPE); if (thread_guard) { @@ -7129,12 +7138,9 @@ expand_static_init (tree decl, tree init) finish_if_stmt (inner_if_stmt); } - if (!targetm.relaxed_ordering || !thread_guard) - { - finish_compound_stmt (then_clause); - finish_then_clause (if_stmt); - finish_if_stmt (if_stmt); - } + finish_compound_stmt (then_clause); + finish_then_clause (if_stmt); + finish_if_stmt (if_stmt); } else if (DECL_THREAD_LOCAL_P (decl)) tls_aggregates = tree_cons (init, decl, tls_aggregates); @@ -13685,13 +13691,16 @@ begin_destructor_body (void) initialize_vtbl_ptrs (current_class_ptr); finish_compound_stmt (compound_stmt); - /* Insert a cleanup to let the back end know that the object is dead - when we exit the destructor, either normally or via exception. */ - tree clobber = build_constructor (current_class_type, NULL); - TREE_THIS_VOLATILE (clobber) = true; - tree exprstmt = build2 (MODIFY_EXPR, current_class_type, - current_class_ref, clobber); - finish_decl_cleanup (NULL_TREE, exprstmt); + if (flag_lifetime_dse) + { + /* Insert a cleanup to let the back end know that the object is dead + when we exit the destructor, either normally or via exception. */ + tree clobber = build_constructor (current_class_type, NULL); + TREE_THIS_VOLATILE (clobber) = true; + tree exprstmt = build2 (MODIFY_EXPR, current_class_type, + current_class_ref, clobber); + finish_decl_cleanup (NULL_TREE, exprstmt); + } /* And insert cleanups for our bases and members so that they will be properly destroyed if we throw. */ diff --git a/gcc-4.9/gcc/cp/decl2.c b/gcc-4.9/gcc/cp/decl2.c index 4fc03e912..074108eea 100644 --- a/gcc-4.9/gcc/cp/decl2.c +++ b/gcc-4.9/gcc/cp/decl2.c @@ -99,6 +99,10 @@ static GTY(()) vec *pending_statics; may need to emit outline anyway. */ static GTY(()) vec *deferred_fns; +/* A list of functions which we might want to set DECL_COMDAT on at EOF. */ + +static GTY(()) vec *maybe_comdat_fns; + /* A list of decls that use types with no linkage, which we need to make sure are defined. */ static GTY(()) vec *no_linkage_decls; @@ -608,7 +612,7 @@ check_classfn (tree ctype, tree function, tree template_parms) int ix; bool is_template; tree pushed_scope; - + if (DECL_USE_TEMPLATE (function) && !(TREE_CODE (function) == TEMPLATE_DECL && DECL_TEMPLATE_SPECIALIZATION (function)) @@ -717,7 +721,7 @@ check_classfn (tree ctype, tree function, tree template_parms) pop_scope (pushed_scope); return OVL_CURRENT (fndecls); } - + error_at (DECL_SOURCE_LOCATION (function), "prototype for %q#D does not match any in class %qT", function, ctype); @@ -1582,7 +1586,7 @@ coerce_new_type (tree type) if (TREE_PURPOSE (args)) { /* [basic.stc.dynamic.allocation] - + The first parameter shall not have an associated default argument. */ error ("the first parameter of % cannot " @@ -1893,6 +1897,12 @@ mark_needed (tree decl) definition. */ struct cgraph_node *node = cgraph_get_create_node (decl); node->forced_by_abi = true; + + /* #pragma interface and -frepo code can call mark_needed for + maybe-in-charge 'tors; mark the clones as well. */ + tree clone; + FOR_EACH_CLONE (clone, decl) + mark_needed (clone); } else if (TREE_CODE (decl) == VAR_DECL) { @@ -1931,11 +1941,6 @@ decl_needed_p (tree decl) if (flag_keep_inline_dllexport && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) return true; - /* Virtual functions might be needed for devirtualization. */ - if (flag_devirtualize - && TREE_CODE (decl) == FUNCTION_DECL - && DECL_VIRTUAL_P (decl)) - return true; /* Otherwise, DECL does not need to be emitted -- yet. A subsequent reference to DECL might cause it to be emitted later. */ return false; @@ -2206,7 +2211,7 @@ determine_visibility (tree decl) if (DECL_VISIBILITY_SPECIFIED (fn)) { DECL_VISIBILITY (decl) = DECL_VISIBILITY (fn); - DECL_VISIBILITY_SPECIFIED (decl) = + DECL_VISIBILITY_SPECIFIED (decl) = DECL_VISIBILITY_SPECIFIED (fn); } else @@ -2287,7 +2292,7 @@ determine_visibility (tree decl) tree attribs = (TREE_CODE (decl) == TYPE_DECL ? TYPE_ATTRIBUTES (TREE_TYPE (decl)) : DECL_ATTRIBUTES (decl)); - + if (args != error_mark_node) { tree pattern = DECL_TEMPLATE_RESULT (TI_TEMPLATE (tinfo)); @@ -2680,17 +2685,7 @@ import_export_decl (tree decl) { /* The repository indicates that this entity should be defined here. Make sure the back end honors that request. */ - if (VAR_P (decl)) - mark_needed (decl); - else if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl) - || DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl)) - { - tree clone; - FOR_EACH_CLONE (clone, decl) - mark_needed (clone); - } - else - mark_needed (decl); + mark_needed (decl); /* Output the definition as an ordinary strong definition. */ DECL_EXTERNAL (decl) = 0; DECL_INTERFACE_KNOWN (decl) = 1; @@ -2921,6 +2916,27 @@ get_guard (tree decl) return guard; } +/* Return an atomic load of src with the appropriate memory model. */ + +static tree +build_atomic_load_byte (tree src, HOST_WIDE_INT model) +{ + tree ptr_type = build_pointer_type (char_type_node); + tree mem_model = build_int_cst (integer_type_node, model); + tree t, addr, val; + unsigned int size; + int fncode; + + size = tree_to_uhwi (TYPE_SIZE_UNIT (char_type_node)); + + fncode = BUILT_IN_ATOMIC_LOAD_N + exact_log2 (size) + 1; + t = builtin_decl_implicit ((enum built_in_function) fncode); + + addr = build1 (ADDR_EXPR, ptr_type, src); + val = build_call_expr (t, 2, addr, mem_model); + return val; +} + /* Return those bits of the GUARD variable that should be set when the guarded entity is actually initialized. */ @@ -2947,12 +2963,14 @@ get_guard_bits (tree guard) variable has already been initialized. */ tree -get_guard_cond (tree guard) +get_guard_cond (tree guard, bool thread_safe) { tree guard_value; - /* Check to see if the GUARD is zero. */ - guard = get_guard_bits (guard); + if (!thread_safe) + guard = get_guard_bits (guard); + else + guard = build_atomic_load_byte (guard, MEMMODEL_ACQUIRE); /* Mask off all but the low bit. */ if (targetm.cxx.guard_mask_bit ()) @@ -2986,7 +3004,7 @@ set_guard (tree guard) guard_init = integer_one_node; if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard))) guard_init = convert (TREE_TYPE (guard), guard_init); - return cp_build_modify_expr (guard, NOP_EXPR, guard_init, + return cp_build_modify_expr (guard, NOP_EXPR, guard_init, tf_warning_or_error); } @@ -3038,9 +3056,15 @@ get_local_tls_init_fn (void) void_list_node)); SET_DECL_LANGUAGE (fn, lang_c); TREE_PUBLIC (fn) = false; + TREE_STATIC (fn) = true; DECL_ARTIFICIAL (fn) = true; mark_used (fn); SET_IDENTIFIER_GLOBAL_VALUE (sname, fn); + /* In LIPO mode make sure we record the new global value so that it + is cleared before parsing the next aux module. */ + if (L_IPO_COMP_MODE && !is_parsing_done_p ()) + add_decl_to_current_module_scope (fn, + NAMESPACE_LEVEL (global_namespace)); } return fn; } @@ -3105,6 +3129,11 @@ get_tls_init_fn (tree var) DECL_BEFRIENDING_CLASSES (fn) = var; SET_IDENTIFIER_GLOBAL_VALUE (sname, fn); + /* In LIPO mode make sure we record the new global value so that it + is cleared before parsing the next aux module. */ + if (L_IPO_COMP_MODE && !is_parsing_done_p ()) + add_decl_to_current_module_scope (fn, + NAMESPACE_LEVEL (global_namespace)); } return fn; } @@ -3162,6 +3191,11 @@ get_tls_wrapper_fn (tree var) DECL_BEFRIENDING_CLASSES (fn) = var; SET_IDENTIFIER_GLOBAL_VALUE (sname, fn); + /* In LIPO mode make sure we record the new global value so that it + is cleared before parsing the next aux module. */ + if (L_IPO_COMP_MODE && !is_parsing_done_p ()) + add_decl_to_current_module_scope (fn, + NAMESPACE_LEVEL (global_namespace)); } return fn; } @@ -3473,7 +3507,7 @@ get_priority_info (int priority) some optimizers (enabled by -O2 -fprofile-arcs) might crash when trying to refer to a temporary variable that does not have it's DECL_CONTECT() properly set. */ -static tree +static tree fix_temporary_vars_context_r (tree *node, int * /*unused*/, void * /*unused1*/) @@ -3520,7 +3554,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp) /* Make sure temporary variables in the initialiser all have their DECL_CONTEXT() set to a value different from NULL_TREE. This can happen when global variables initialisers are built. - In that case, the DECL_CONTEXT() of the global variables _AND_ of all + In that case, the DECL_CONTEXT() of the global variables _AND_ of all the temporary variables that might have been generated in the accompagning initialisers is NULL_TREE, meaning the variables have been declared in the global namespace. @@ -3567,7 +3601,7 @@ one_static_initialization_or_destruction (tree decl, tree init, bool initp) /* When using __cxa_atexit, we never try to destroy anything from a static destructor. */ gcc_assert (initp); - guard_cond = get_guard_cond (guard); + guard_cond = get_guard_cond (guard, false); } /* If we don't have __cxa_atexit, then we will be running destructors from .fini sections, or their equivalents. So, @@ -3992,19 +4026,19 @@ cpp_check (tree t, cpp_operation op) /* Collect source file references recursively, starting from NAMESPC. */ -static void -collect_source_refs (tree namespc) +static void +collect_source_refs (tree namespc) { tree t; - if (!namespc) + if (!namespc) return; /* Iterate over names in this name space. */ for (t = NAMESPACE_LEVEL (namespc)->names; t; t = TREE_CHAIN (t)) if (!DECL_IS_BUILTIN (t) ) collect_source_ref (DECL_SOURCE_FILE (t)); - + /* Dump siblings, if any */ collect_source_refs (TREE_CHAIN (namespc)); @@ -4218,8 +4252,12 @@ handle_tls_init (void) one_static_initialization_or_destruction (var, init, true); #ifdef ASM_OUTPUT_DEF - /* Output init aliases even with -fno-extern-tls-init. */ - if (TREE_PUBLIC (var)) + /* Output init aliases even with -fno-extern-tls-init. Don't emit + aliases in LIPO aux modules, since the corresponding __tls_init + will be static promoted and deleted, so the variable's tls init + function will be resolved by its own primary module. An alias + would prevent the promoted aux __tls_init from being deleted. */ + if (TREE_PUBLIC (var) && !L_IPO_IS_AUXILIARY_MODULE) { tree single_init_fn = get_tls_init_fn (var); if (single_init_fn == NULL_TREE) @@ -4254,6 +4292,34 @@ dump_tu (void) } } +/* Much like the above, but not necessarily defined. 4.9 hack for setting + DECL_COMDAT on DECL_EXTERNAL functions, along with set_comdat. */ + +void +note_comdat_fn (tree decl) +{ + vec_safe_push (maybe_comdat_fns, decl); +} + +/* DECL is a function with vague linkage that was not + instantiated/synthesized in this translation unit. Set DECL_COMDAT for + the benefit of can_refer_decl_in_current_unit_p. */ + +static void +set_comdat (tree decl) +{ + DECL_COMDAT (decl) = true; + + tree clone; + FOR_EACH_CLONE (clone, decl) + set_comdat (clone); + + if (DECL_VIRTUAL_P (decl)) + for (tree thunk = DECL_THUNKS (decl); thunk; + thunk = DECL_CHAIN (thunk)) + DECL_COMDAT (thunk) = true; +} + /* This routine is called at the end of compilation. Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction @@ -4603,6 +4669,8 @@ cp_write_global_declarations (void) bool reconsider = false; location_t locus; struct pointer_set_t *candidates; + size_t i; + tree decl; locus = input_location; at_eof = 1; @@ -4667,6 +4735,10 @@ cp_write_global_declarations (void) vtv_build_vtable_verify_fndecl (); } + FOR_EACH_VEC_SAFE_ELT (maybe_comdat_fns, i, decl) + if (!DECL_COMDAT (decl) && vague_linkage_p (decl)) + set_comdat (decl); + finalize_compilation_unit (); if (flag_vtable_verify) @@ -4941,7 +5013,7 @@ mark_used (tree decl, tsubst_flags_t complain) --function_depth; } - if (processing_template_decl) + if (processing_template_decl || in_template_function ()) return true; /* Check this too in case we're within fold_non_dependent_expr. */ diff --git a/gcc-4.9/gcc/cp/mangle.c b/gcc-4.9/gcc/cp/mangle.c index 169f84451..0ed28087c 100644 --- a/gcc-4.9/gcc/cp/mangle.c +++ b/gcc-4.9/gcc/cp/mangle.c @@ -763,8 +763,7 @@ decl_mangling_context (tree decl) if (extra) return extra; } - else if (TREE_CODE (decl) == TYPE_DECL - && TREE_CODE (TREE_TYPE (decl)) == TEMPLATE_TYPE_PARM) + else if (template_type_parameter_p (decl)) /* template type parms have no mangling context. */ return NULL_TREE; return CP_DECL_CONTEXT (decl); @@ -3112,6 +3111,8 @@ write_template_arg (tree node) } } + if (REFERENCE_REF_P (node)) + node = TREE_OPERAND (node, 0); if (TREE_CODE (node) == NOP_EXPR && TREE_CODE (TREE_TYPE (node)) == REFERENCE_TYPE) { diff --git a/gcc-4.9/gcc/cp/method.c b/gcc-4.9/gcc/cp/method.c index 5365b669c..9db214405 100644 --- a/gcc-4.9/gcc/cp/method.c +++ b/gcc-4.9/gcc/cp/method.c @@ -1775,6 +1775,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, DECL_EXTERNAL (fn) = true; DECL_NOT_REALLY_EXTERN (fn) = 1; DECL_DECLARED_INLINE_P (fn) = 1; + note_comdat_fn (fn); gcc_assert (!TREE_USED (fn)); /* Restore PROCESSING_TEMPLATE_DECL. */ diff --git a/gcc-4.9/gcc/cp/parser.c b/gcc-4.9/gcc/cp/parser.c index 88478bf13..29b590ea4 100644 --- a/gcc-4.9/gcc/cp/parser.c +++ b/gcc-4.9/gcc/cp/parser.c @@ -8499,12 +8499,7 @@ cp_parser_builtin_offsetof (cp_parser *parser) } success: - /* If we're processing a template, we can't finish the semantics yet. - Otherwise we can fold the entire expression now. */ - if (processing_template_decl) - expr = build1 (OFFSETOF_EXPR, size_type_node, expr); - else - expr = finish_offsetof (expr); + expr = finish_offsetof (expr); failure: parser->integral_constant_expression_p = save_ice_p; @@ -25009,8 +25004,6 @@ cp_parser_commit_to_topmost_tentative_parse (cp_parser* parser) static void cp_parser_abort_tentative_parse (cp_parser* parser) { - gcc_assert (parser->context->status != CP_PARSER_STATUS_KIND_COMMITTED - || errorcount > 0); cp_parser_simulate_error (parser); /* Now, pretend that we want to see if the construct was successfully parsed. */ diff --git a/gcc-4.9/gcc/cp/pt.c b/gcc-4.9/gcc/cp/pt.c index a049a1e21..c8cc3ef47 100644 --- a/gcc-4.9/gcc/cp/pt.c +++ b/gcc-4.9/gcc/cp/pt.c @@ -1610,6 +1610,7 @@ iterative_hash_template_arg (tree arg, hashval_t val) case CONSTRUCTOR: { tree field, value; + iterative_hash_template_arg (TREE_TYPE (arg), val); FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (arg), i, field, value) { val = iterative_hash_template_arg (field, val); @@ -4439,9 +4440,11 @@ check_default_tmpl_args (tree decl, tree parms, bool is_primary, local scope. */ return true; - if (TREE_CODE (decl) == TYPE_DECL - && TREE_TYPE (decl) - && LAMBDA_TYPE_P (TREE_TYPE (decl))) + if ((TREE_CODE (decl) == TYPE_DECL + && TREE_TYPE (decl) + && LAMBDA_TYPE_P (TREE_TYPE (decl))) + || (TREE_CODE (decl) == FUNCTION_DECL + && LAMBDA_FUNCTION_P (decl))) /* A lambda doesn't have an explicit declaration; don't complain about the parms of the enclosing class. */ return true; @@ -6090,7 +6093,7 @@ convert_nontype_argument (tree type, tree expr, tsubst_flags_t complain) right type? */ gcc_assert (same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (expr))); - return expr; + return convert_from_reference (expr); } /* Subroutine of coerce_template_template_parms, which returns 1 if @@ -9825,6 +9828,17 @@ tsubst_pack_expansion (tree t, tree args, tsubst_flags_t complain, } } + /* If the expansion is just T..., return the matching argument pack. */ + if (!unsubstituted_packs + && TREE_PURPOSE (packs) == pattern) + { + tree args = ARGUMENT_PACK_ARGS (TREE_VALUE (packs)); + if (TREE_CODE (t) == TYPE_PACK_EXPANSION + || pack_expansion_args_count (args)) + return args; + /* Otherwise use the normal path so we get convert_from_reference. */ + } + /* We cannot expand this expansion expression, because we don't have all of the argument packs we need. */ if (use_pack_expansion_extra_args_p (packs, len, unsubstituted_packs)) @@ -10686,6 +10700,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) the type earlier (template/friend54.C). */ RETURN (new_r); + if (!DECL_FRIEND_P (r)) + note_comdat_fn (r); + /* We're not supposed to instantiate default arguments until they are called, for a template. But, for a declaration like: @@ -13869,8 +13886,6 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, case OMP_SECTIONS: case OMP_SINGLE: case OMP_TEAMS: - case OMP_TARGET_DATA: - case OMP_TARGET: tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false, args, complain, in_decl); stmt = push_stmt_list (); @@ -13883,6 +13898,22 @@ tsubst_expr (tree t, tree args, tsubst_flags_t complain, tree in_decl, add_stmt (t); break; + case OMP_TARGET_DATA: + case OMP_TARGET: + tmp = tsubst_omp_clauses (OMP_CLAUSES (t), false, + args, complain, in_decl); + keep_next_level (true); + stmt = begin_omp_structured_block (); + + RECUR (OMP_BODY (t)); + stmt = finish_omp_structured_block (stmt); + + t = copy_node (t); + OMP_BODY (t) = stmt; + OMP_CLAUSES (t) = tmp; + add_stmt (t); + break; + case OMP_TARGET_UPDATE: tmp = tsubst_omp_clauses (OMP_TARGET_UPDATE_CLAUSES (t), false, args, complain, in_decl); @@ -14129,16 +14160,6 @@ tsubst_non_call_postfix_expression (tree t, tree args, return t; } -/* Sentinel to disable certain warnings during template substitution. */ - -struct warning_sentinel { - int &flag; - int val; - warning_sentinel(int& flag, bool suppress=true) - : flag(flag), val(flag) { if (suppress) flag = 0; } - ~warning_sentinel() { flag = val; } -}; - /* Like tsubst but deals with expressions and performs semantic analysis. FUNCTION_P is true if T is the "F" in "F (ARGS)". */ @@ -14802,7 +14823,7 @@ tsubst_copy_and_build (tree t, /* Remember that there was a reference to this entity. */ if (DECL_P (function)) - mark_used (function); + mark_used (function, complain); /* Put back tf_decltype for the actual call. */ complain |= decltype_flag; @@ -14849,11 +14870,13 @@ tsubst_copy_and_build (tree t, case COND_EXPR: { tree cond = RECUR (TREE_OPERAND (t, 0)); + tree folded_cond = (maybe_constant_value + (fold_non_dependent_expr_sfinae (cond, tf_none))); tree exp1, exp2; - if (TREE_CODE (cond) == INTEGER_CST) + if (TREE_CODE (folded_cond) == INTEGER_CST) { - if (integer_zerop (cond)) + if (integer_zerop (folded_cond)) { ++c_inhibit_evaluation_warnings; exp1 = RECUR (TREE_OPERAND (t, 1)); @@ -14867,6 +14890,7 @@ tsubst_copy_and_build (tree t, exp2 = RECUR (TREE_OPERAND (t, 2)); --c_inhibit_evaluation_warnings; } + cond = folded_cond; } else { @@ -15417,6 +15441,7 @@ check_instantiated_arg (tree tmpl, tree t, tsubst_flags_t complain) constant. */ else if (TREE_TYPE (t) && INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (t)) + && !REFERENCE_REF_P (t) && !TREE_CONSTANT (t)) { if (complain & tf_error) @@ -18140,8 +18165,12 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict, case INDIRECT_REF: if (REFERENCE_REF_P (parm)) - return unify (tparms, targs, TREE_OPERAND (parm, 0), arg, - strict, explain_p); + { + if (REFERENCE_REF_P (arg)) + arg = TREE_OPERAND (arg, 0); + return unify (tparms, targs, TREE_OPERAND (parm, 0), arg, + strict, explain_p); + } /* FALLTHRU */ default: @@ -20776,6 +20805,8 @@ value_dependent_expression_p (tree expression) { unsigned ix; tree val; + if (dependent_type_p (TREE_TYPE (expression))) + return true; FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expression), ix, val) if (value_dependent_expression_p (val)) return true; diff --git a/gcc-4.9/gcc/cp/semantics.c b/gcc-4.9/gcc/cp/semantics.c index db4f9fdcd..cb26ef96c 100644 --- a/gcc-4.9/gcc/cp/semantics.c +++ b/gcc-4.9/gcc/cp/semantics.c @@ -1629,7 +1629,12 @@ force_paren_expr (tree expr) tree type = unlowered_expr_type (expr); bool rval = !!(kind & clk_rvalueref); type = cp_build_reference_type (type, rval); + /* This inhibits warnings in, eg, cxx_mark_addressable + (c++/60955). */ + warning_sentinel s (extra_warnings); expr = build_static_cast (type, expr, tf_error); + if (expr != error_mark_node) + REF_PARENTHESIZED_P (expr) = true; } } @@ -3804,6 +3809,14 @@ finish_bases (tree type, bool direct) tree finish_offsetof (tree expr) { + /* If we're processing a template, we can't finish the semantics yet. + Otherwise we can fold the entire expression now. */ + if (processing_template_decl) + { + expr = build1 (OFFSETOF_EXPR, size_type_node, expr); + return expr; + } + if (TREE_CODE (expr) == PSEUDO_DTOR_EXPR) { error ("cannot apply % to destructor %<~%T%>", @@ -4280,6 +4293,10 @@ handle_omp_array_sections_1 (tree c, tree t, vec &types, length); return error_mark_node; } + if (low_bound) + low_bound = mark_rvalue_use (low_bound); + if (length) + length = mark_rvalue_use (length); if (low_bound && TREE_CODE (low_bound) == INTEGER_CST && TYPE_PRECISION (TREE_TYPE (low_bound)) @@ -5645,7 +5662,9 @@ finish_omp_clauses (tree clauses) else { t = OMP_CLAUSE_DECL (c); - if (!cp_omp_mappable_type (TREE_TYPE (t))) + if (TREE_CODE (t) != TREE_LIST + && !type_dependent_expression_p (t) + && !cp_omp_mappable_type (TREE_TYPE (t))) { error_at (OMP_CLAUSE_LOCATION (c), "array section does not have mappable type " @@ -5685,6 +5704,7 @@ finish_omp_clauses (tree clauses) remove = true; else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER) + && !type_dependent_expression_p (t) && !cp_omp_mappable_type ((TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE) ? TREE_TYPE (TREE_TYPE (t)) @@ -10208,6 +10228,11 @@ potential_constant_expression_1 (tree t, bool want_rval, tsubst_flags_t flags) designates an object with thread or automatic storage duration; */ t = TREE_OPERAND (t, 0); + + if (TREE_CODE (t) == OFFSET_REF && PTRMEM_OK_P (t)) + /* A pointer-to-member constant. */ + return true; + #if 0 /* FIXME adjust when issue 1197 is fully resolved. For now don't do any checking here, as we might dereference the pointer later. If diff --git a/gcc-4.9/gcc/cp/typeck.c b/gcc-4.9/gcc/cp/typeck.c index 3c8d62fbc..1d1ddb284 100644 --- a/gcc-4.9/gcc/cp/typeck.c +++ b/gcc-4.9/gcc/cp/typeck.c @@ -8583,6 +8583,20 @@ check_return_expr (tree retval, bool *no_warning) if (VOID_TYPE_P (functype)) return error_mark_node; + /* If we had an id-expression obfuscated by force_paren_expr, we need + to undo it so we can try to treat it as an rvalue below. */ + if (cxx_dialect >= cxx1y + && INDIRECT_REF_P (retval) + && REF_PARENTHESIZED_P (retval)) + { + retval = TREE_OPERAND (retval, 0); + while (TREE_CODE (retval) == NON_LVALUE_EXPR + || TREE_CODE (retval) == NOP_EXPR) + retval = TREE_OPERAND (retval, 0); + gcc_assert (TREE_CODE (retval) == ADDR_EXPR); + retval = TREE_OPERAND (retval, 0); + } + /* Under C++0x [12.8/16 class.copy], a returned lvalue is sometimes treated as an rvalue for the purposes of overload resolution to favor move constructors over copy constructors. @@ -8871,6 +8885,12 @@ 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-4.9/gcc/cppbuiltin.c b/gcc-4.9/gcc/cppbuiltin.c index 8b2c6b4d3..770e23e16 100644 --- a/gcc-4.9/gcc/cppbuiltin.c +++ b/gcc-4.9/gcc/cppbuiltin.c @@ -107,6 +107,9 @@ define_builtin_macros_for_compilation_flags (cpp_reader *pfile) flag_finite_math_only); if (flag_cilkplus) cpp_define (pfile, "__cilk=200"); + + if (flag_shrink_wrap_frame_pointer) + cpp_define (pfile, "SHRINK_WRAP_FRAME_POINTER"); } diff --git a/gcc-4.9/gcc/cprop.c b/gcc-4.9/gcc/cprop.c index 6a3429e19..c3acb05c1 100644 --- a/gcc-4.9/gcc/cprop.c +++ b/gcc-4.9/gcc/cprop.c @@ -790,11 +790,8 @@ try_replace_reg (rtx from, rtx to, rtx insn) /* REG_EQUAL may get simplified into register. We don't allow that. Remove that note. This code ought not to happen, because previous code ought to synthesize - reg-reg move, but be on the safe side. The REG_EQUAL note is - also removed when the source is a constant. */ - if (note && REG_NOTE_KIND (note) == REG_EQUAL - && (REG_P (XEXP (note, 0)) - || (set && CONSTANT_P (SET_SRC (set))))) + reg-reg move, but be on the safe side. */ + if (note && REG_NOTE_KIND (note) == REG_EQUAL && REG_P (XEXP (note, 0))) remove_note (insn, note); return success; diff --git a/gcc-4.9/gcc/dbgcnt.def b/gcc-4.9/gcc/dbgcnt.def index cd05e27ae..e910c3eb1 100644 --- a/gcc-4.9/gcc/dbgcnt.def +++ b/gcc-4.9/gcc/dbgcnt.def @@ -191,3 +191,4 @@ DEBUG_COUNTER (split_for_sched2) DEBUG_COUNTER (tail_call) DEBUG_COUNTER (ira_move) DEBUG_COUNTER (registered_jump_thread) +DEBUG_COUNTER (fpset_insert) diff --git a/gcc-4.9/gcc/df.h b/gcc-4.9/gcc/df.h index 2de800c09..3020955c1 100644 --- a/gcc-4.9/gcc/df.h +++ b/gcc-4.9/gcc/df.h @@ -1134,21 +1134,23 @@ df_get_artificial_uses (unsigned int bb_index) /* web */ -/* This entry is allocated for each reference in the insn stream. */ -struct web_entry +class web_entry_base { - /* Pointer to the parent in the union/find tree. */ - struct web_entry *pred; - /* Newly assigned register to the entry. Set only for roots. */ - rtx reg; - void* extra_info; -}; + private: + /* Reference to the parent in the union/find tree. */ + web_entry_base *pred_pvt; + + public: + /* Accessors. */ + web_entry_base *pred () { return pred_pvt; } + void set_pred (web_entry_base *p) { pred_pvt = p; } -extern struct web_entry *unionfind_root (struct web_entry *); -extern bool unionfind_union (struct web_entry *, struct web_entry *); -extern void union_defs (df_ref, struct web_entry *, - unsigned int *used, struct web_entry *, - bool (*fun) (struct web_entry *, struct web_entry *)); + /* Find representative in union-find tree. */ + web_entry_base *unionfind_root (); + + /* Union with another set, returning TRUE if they are already unioned. */ + friend bool unionfind_union (web_entry_base *first, web_entry_base *second); +}; extern bool df_check_ud_du_memory_usage (void); diff --git a/gcc-4.9/gcc/doc/cpp.texi b/gcc-4.9/gcc/doc/cpp.texi index aaed739fb..0a6e50caa 100644 --- a/gcc-4.9/gcc/doc/cpp.texi +++ b/gcc-4.9/gcc/doc/cpp.texi @@ -2354,8 +2354,8 @@ This macro is defined, with value 3, when @option{-fstack-protector-strong} is in use. @item __SANITIZE_ADDRESS__ -This macro is defined, with value 1, when @option{-fsanitize=address} is -in use. +This macro is defined, with value 1, when @option{-fsanitize=address} +or @option{-fsanitize=kernel-address} are in use. @item __TIMESTAMP__ This macro expands to a string constant that describes the date and time diff --git a/gcc-4.9/gcc/doc/extend.texi b/gcc-4.9/gcc/doc/extend.texi index dfdedb617..4c0914a35 100644 --- a/gcc-4.9/gcc/doc/extend.texi +++ b/gcc-4.9/gcc/doc/extend.texi @@ -3527,6 +3527,35 @@ function should not save and restore registers R0..R7. This can be used on SH3* and SH4* targets that have a second R0..R7 register bank for non-reentrant interrupt handlers. +@item noplt +@cindex @code{noplt} function attribute +The @code{noplt} attribute is the counterpart to option @option{-fno-plt} and +does not use PLT for calls to functions marked with this attribute in position +independent code. + +@smallexample +@group +/* Externally defined function foo. */ +int foo () __attribute__ ((noplt)); + +int +main (/* @r{@dots{}} */) +@{ + /* @r{@dots{}} */ + foo (); + /* @r{@dots{}} */ +@} +@end group +@end smallexample + +The @code{noplt} attribute on function foo tells the compiler to assume that +the function foo is externally defined and the call to foo must avoid the PLT +in position independent code. + +Additionally, a few targets also convert calls to those functions that are +marked to not use the PLT to use the GOT instead for non-position independent +code. + @item optimize @cindex @code{optimize} function attribute The @code{optimize} attribute is used to specify that a function is to @@ -14016,16 +14045,22 @@ vector bool int vec_cmplt (vector unsigned int, vector unsigned int); vector bool int vec_cmplt (vector signed int, vector signed int); vector bool int vec_cmplt (vector float, vector float); +vector float vec_cpsgn (vector float, vector float); + vector float vec_ctf (vector unsigned int, const int); vector float vec_ctf (vector signed int, const int); +vector double vec_ctf (vector unsigned long, const int); +vector double vec_ctf (vector signed long, const int); vector float vec_vcfsx (vector signed int, const int); vector float vec_vcfux (vector unsigned int, const int); vector signed int vec_cts (vector float, const int); +vector signed long vec_cts (vector double, const int); vector unsigned int vec_ctu (vector float, const int); +vector unsigned long vec_ctu (vector double, const int); void vec_dss (const int); @@ -14861,6 +14896,16 @@ vector float vec_splat (vector float, const int); vector signed int vec_splat (vector signed int, const int); vector unsigned int vec_splat (vector unsigned int, const int); vector bool int vec_splat (vector bool int, const int); +vector signed long vec_splat (vector signed long, const int); +vector unsigned long vec_splat (vector unsigned long, const int); + +vector signed char vec_splats (signed char); +vector unsigned char vec_splats (unsigned char); +vector signed short vec_splats (signed short); +vector unsigned short vec_splats (unsigned short); +vector signed int vec_splats (signed int); +vector unsigned int vec_splats (unsigned int); +vector float vec_splats (float); vector float vec_vspltw (vector float, const int); vector signed int vec_vspltw (vector signed int, const int); @@ -15565,17 +15610,32 @@ vector double vec_add (vector double, vector double); vector double vec_and (vector double, vector double); vector double vec_and (vector double, vector bool long); vector double vec_and (vector bool long, vector double); +vector long vec_and (vector long, vector long); +vector long vec_and (vector long, vector bool long); +vector long vec_and (vector bool long, vector long); +vector unsigned long vec_and (vector unsigned long, vector unsigned long); +vector unsigned long vec_and (vector unsigned long, vector bool long); +vector unsigned long vec_and (vector bool long, vector unsigned long); vector double vec_andc (vector double, vector double); vector double vec_andc (vector double, vector bool long); vector double vec_andc (vector bool long, vector double); +vector long vec_andc (vector long, vector long); +vector long vec_andc (vector long, vector bool long); +vector long vec_andc (vector bool long, vector long); +vector unsigned long vec_andc (vector unsigned long, vector unsigned long); +vector unsigned long vec_andc (vector unsigned long, vector bool long); +vector unsigned long vec_andc (vector bool long, vector unsigned long); vector double vec_ceil (vector double); vector bool long vec_cmpeq (vector double, vector double); vector bool long vec_cmpge (vector double, vector double); vector bool long vec_cmpgt (vector double, vector double); vector bool long vec_cmple (vector double, vector double); vector bool long vec_cmplt (vector double, vector double); +vector double vec_cpsgn (vector double, vector double); vector float vec_div (vector float, vector float); vector double vec_div (vector double, vector double); +vector long vec_div (vector long, vector long); +vector unsigned long vec_div (vector unsigned long, vector unsigned long); vector double vec_floor (vector double); vector double vec_ld (int, const vector double *); vector double vec_ld (int, const double *); @@ -15585,38 +15645,83 @@ vector unsigned char vec_lvsl (int, const volatile double *); vector unsigned char vec_lvsr (int, const volatile double *); vector double vec_madd (vector double, vector double, vector double); vector double vec_max (vector double, vector double); +vector signed long vec_mergeh (vector signed long, vector signed long); +vector signed long vec_mergeh (vector signed long, vector bool long); +vector signed long vec_mergeh (vector bool long, vector signed long); +vector unsigned long vec_mergeh (vector unsigned long, vector unsigned long); +vector unsigned long vec_mergeh (vector unsigned long, vector bool long); +vector unsigned long vec_mergeh (vector bool long, vector unsigned long); +vector signed long vec_mergel (vector signed long, vector signed long); +vector signed long vec_mergel (vector signed long, vector bool long); +vector signed long vec_mergel (vector bool long, vector signed long); +vector unsigned long vec_mergel (vector unsigned long, vector unsigned long); +vector unsigned long vec_mergel (vector unsigned long, vector bool long); +vector unsigned long vec_mergel (vector bool long, vector unsigned long); vector double vec_min (vector double, vector double); vector float vec_msub (vector float, vector float, vector float); vector double vec_msub (vector double, vector double, vector double); vector float vec_mul (vector float, vector float); vector double vec_mul (vector double, vector double); +vector long vec_mul (vector long, vector long); +vector unsigned long vec_mul (vector unsigned long, vector unsigned long); vector float vec_nearbyint (vector float); vector double vec_nearbyint (vector double); vector float vec_nmadd (vector float, vector float, vector float); vector double vec_nmadd (vector double, vector double, vector double); vector double vec_nmsub (vector double, vector double, vector double); vector double vec_nor (vector double, vector double); +vector long vec_nor (vector long, vector long); +vector long vec_nor (vector long, vector bool long); +vector long vec_nor (vector bool long, vector long); +vector unsigned long vec_nor (vector unsigned long, vector unsigned long); +vector unsigned long vec_nor (vector unsigned long, vector bool long); +vector unsigned long vec_nor (vector bool long, vector unsigned long); vector double vec_or (vector double, vector double); vector double vec_or (vector double, vector bool long); vector double vec_or (vector bool long, vector double); -vector double vec_perm (vector double, - vector double, - vector unsigned char); +vector long vec_or (vector long, vector long); +vector long vec_or (vector long, vector bool long); +vector long vec_or (vector bool long, vector long); +vector unsigned long vec_or (vector unsigned long, vector unsigned long); +vector unsigned long vec_or (vector unsigned long, vector bool long); +vector unsigned long vec_or (vector bool long, vector unsigned long); +vector double vec_perm (vector double, vector double, vector unsigned char); +vector long vec_perm (vector long, vector long, vector unsigned char); +vector unsigned long vec_perm (vector unsigned long, vector unsigned long, + vector unsigned char); vector double vec_rint (vector double); vector double vec_recip (vector double, vector double); vector double vec_rsqrt (vector double); vector double vec_rsqrte (vector double); vector double vec_sel (vector double, vector double, vector bool long); vector double vec_sel (vector double, vector double, vector unsigned long); -vector double vec_sub (vector double, vector double); +vector long vec_sel (vector long, vector long, vector long); +vector long vec_sel (vector long, vector long, vector unsigned long); +vector long vec_sel (vector long, vector long, vector bool long); +vector unsigned long vec_sel (vector unsigned long, vector unsigned long, + vector long); +vector unsigned long vec_sel (vector unsigned long, vector unsigned long, + vector unsigned long); +vector unsigned long vec_sel (vector unsigned long, vector unsigned long, + vector bool long); +vector double vec_splats (double); +vector signed long vec_splats (signed long); +vector unsigned long vec_splats (unsigned long); vector float vec_sqrt (vector float); vector double vec_sqrt (vector double); void vec_st (vector double, int, vector double *); void vec_st (vector double, int, double *); +vector double vec_sub (vector double, vector double); vector double vec_trunc (vector double); vector double vec_xor (vector double, vector double); vector double vec_xor (vector double, vector bool long); vector double vec_xor (vector bool long, vector double); +vector long vec_xor (vector long, vector long); +vector long vec_xor (vector long, vector bool long); +vector long vec_xor (vector bool long, vector long); +vector unsigned long vec_xor (vector unsigned long, vector unsigned long); +vector unsigned long vec_xor (vector unsigned long, vector bool long); +vector unsigned long vec_xor (vector bool long, vector unsigned long); int vec_all_eq (vector double, vector double); int vec_all_ge (vector double, vector double); int vec_all_gt (vector double, vector double); @@ -15745,17 +15850,30 @@ vector unsigned long long vec_add (vector unsigned long long, vector unsigned long long); int vec_all_eq (vector long long, vector long long); +int vec_all_eq (vector unsigned long long, vector unsigned long long); int vec_all_ge (vector long long, vector long long); +int vec_all_ge (vector unsigned long long, vector unsigned long long); int vec_all_gt (vector long long, vector long long); +int vec_all_gt (vector unsigned long long, vector unsigned long long); int vec_all_le (vector long long, vector long long); +int vec_all_le (vector unsigned long long, vector unsigned long long); int vec_all_lt (vector long long, vector long long); +int vec_all_lt (vector unsigned long long, vector unsigned long long); int vec_all_ne (vector long long, vector long long); +int vec_all_ne (vector unsigned long long, vector unsigned long long); + int vec_any_eq (vector long long, vector long long); +int vec_any_eq (vector unsigned long long, vector unsigned long long); int vec_any_ge (vector long long, vector long long); +int vec_any_ge (vector unsigned long long, vector unsigned long long); int vec_any_gt (vector long long, vector long long); +int vec_any_gt (vector unsigned long long, vector unsigned long long); int vec_any_le (vector long long, vector long long); +int vec_any_le (vector unsigned long long, vector unsigned long long); int vec_any_lt (vector long long, vector long long); +int vec_any_lt (vector unsigned long long, vector unsigned long long); int vec_any_ne (vector long long, vector long long); +int vec_any_ne (vector unsigned long long, vector unsigned long long); vector long long vec_eqv (vector long long, vector long long); vector long long vec_eqv (vector bool long long, vector long long); @@ -15793,6 +15911,14 @@ vector long long vec_max (vector long long, vector long long); vector unsigned long long vec_max (vector unsigned long long, vector unsigned long long); +vector signed int vec_mergee (vector signed int, vector signed int); +vector unsigned int vec_mergee (vector unsigned int, vector unsigned int); +vector bool int vec_mergee (vector bool int, vector bool int); + +vector signed int vec_mergeo (vector signed int, vector signed int); +vector unsigned int vec_mergeo (vector unsigned int, vector unsigned int); +vector bool int vec_mergeo (vector bool int, vector bool int); + vector long long vec_min (vector long long, vector long long); vector unsigned long long vec_min (vector unsigned long long, vector unsigned long long); @@ -15871,6 +15997,8 @@ vector unsigned int vec_packs (vector unsigned long long, vector unsigned long long); vector unsigned int vec_packsu (vector long long, vector long long); +vector unsigned int vec_packsu (vector unsigned long long, + vector unsigned long long); vector long long vec_rl (vector long long, vector unsigned long long); @@ -15912,6 +16040,15 @@ vector unsigned long long vec_vaddudm (vector unsigned long long, vector long long vec_vbpermq (vector signed char, vector signed char); vector long long vec_vbpermq (vector unsigned char, vector unsigned char); +vector long long vec_cntlz (vector long long); +vector unsigned long long vec_cntlz (vector unsigned long long); +vector int vec_cntlz (vector int); +vector unsigned int vec_cntlz (vector int); +vector short vec_cntlz (vector short); +vector unsigned short vec_cntlz (vector unsigned short); +vector signed char vec_cntlz (vector signed char); +vector unsigned char vec_cntlz (vector unsigned char); + vector long long vec_vclz (vector long long); vector unsigned long long vec_vclz (vector unsigned long long); vector int vec_vclz (vector int); diff --git a/gcc-4.9/gcc/doc/gcov-tool.texi b/gcc-4.9/gcc/doc/gcov-tool.texi index ff8b9e22f..3a6687289 100644 --- a/gcc-4.9/gcc/doc/gcov-tool.texi +++ b/gcc-4.9/gcc/doc/gcov-tool.texi @@ -103,8 +103,7 @@ in these kind of counters. @section Invoking @command{gcov-tool} @smallexample -gcov-tool @r{[}@var{global-options}@r{]} SUB_COMMAND -@r{[}@var{sub_command-options}@r{]} @var{profile_dir} +gcov-tool @r{[}@var{global-options}@r{]} SUB_COMMAND @r{[}@var{sub_command-options}@r{]} @var{profile_dir} @end smallexample @command{gcov-tool} accepts the following options: @@ -123,6 +122,15 @@ gcov-tool rewrite [rewrite-options] @var{directory} [@option{-o}|@option{--output} @var{directory}] [@option{-s}|@option{--scale} @var{float_or_simple-frac_value}] [@option{-n}|@option{--normalize} @var{long_long_value}] + +gcov-tool overlap [overlap-options] @var{directory1} @var{directory2} + [@option{-v}|@option{--verbose}] + [@option{-h}|@option{--hotonly}] + [@option{-f}|@option{--function}] + [@option{-F}|@option{--fullname}] + [@option{-o}|@option{--object}] + [@option{-t}|@option{--hot_threshold}] @var{float} + @c man end @c man begin SEEALSO gpl(7), gfdl(7), fsf-funding(7), gcc(1), gcov(1) and the Info entry for @@ -182,8 +190,42 @@ or simple fraction value form, such 1, 2, 2/3, and 5/3. @itemx --normalize Normalize the profile. The specified value is the max counter value in the new profile. +@end table + +@item overlap +Computer the overlap score between the two specified profile directories. +The overlap score is computed based on the arc profiles. It is defined as +the sum of min (p1_counter[i] / p1_sum_all, p2_counter[i] / p2_sum_all), +for all arc counter i, where p1_counter[i] and p2_counter[i] are two +matched counters and p1_sum_all and p2_sum_all are the sum of counter +values in profile 1 and profile 2, respectively. + +@table @gcctabopt +@item -v +@itemx --verbose +Set the verbose mode. + +@item -h +@itemx --hotonly +Only print info for hot objects/functions. +@item -f +@itemx --function +Print function level overlap score. + +@item -F +@itemx --fullname +Print full gcda filename. + +@item -o +@itemx --object +Print object level overlap score. + +@item -t @var{float} +@itemx --hot_threshold +Set the threshold for hot counter value. @end table + @end table @c man end diff --git a/gcc-4.9/gcc/doc/install.texi b/gcc-4.9/gcc/doc/install.texi index ccb7e7b10..9f66a47ef 100644 --- a/gcc-4.9/gcc/doc/install.texi +++ b/gcc-4.9/gcc/doc/install.texi @@ -1489,6 +1489,10 @@ be built. This can be useful for debugging, or for compatibility with previous Ada build procedures, when it was required to explicitly do a @samp{make -C gcc gnatlib_and_tools}. +@item --disable-libsanitizer +Specify that the run-time libraries for the various sanitizers should +not be built. + @item --disable-libssp Specify that the run-time libraries for stack smashing protection should not be built. diff --git a/gcc-4.9/gcc/doc/invoke.texi b/gcc-4.9/gcc/doc/invoke.texi index bee61f058..f8350c418 100644 --- a/gcc-4.9/gcc/doc/invoke.texi +++ b/gcc-4.9/gcc/doc/invoke.texi @@ -372,7 +372,8 @@ Objective-C and Objective-C++ Dialects}. -fdelete-null-pointer-checks -fdevirtualize -fdevirtualize-speculatively -fdse @gol -fearly-inlining -fipa-sra -fexpensive-optimizations -ffat-lto-objects @gol -ffast-math -ffinite-math-only -ffloat-store -fexcess-precision=@var{style} @gol --fforward-propagate -ffp-contract=@var{style} -ffunction-sections @gol +-fforward-propagate -ffp-contract=@var{style} @gol +-ffunction-attribute-list -ffunction-sections @gol -fgcse -fgcse-after-reload -fgcse-las -fgcse-lm -fgraphite-identity @gol -fgcse-sm -fhoist-adjacent-loads -fif-conversion @gol -fif-conversion2 -findirect-inlining @gol @@ -462,7 +463,7 @@ Objective-C and Objective-C++ Dialects}. @item Linker Options @xref{Link Options,,Options for Linking}. @gccoptlist{@var{object-file-name} -l@var{library} @gol --nostartfiles -nodefaultlibs -nostdlib -pie -rdynamic @gol +-nostartfiles -nodefaultlibs -no-pie -nostdlib -pie -rdynamic @gol -s -static -static-libgcc -static-libstdc++ @gol -static-libasan -static-libtsan -static-liblsan -static-libubsan @gol -shared -shared-libgcc -symbolic @gol @@ -668,7 +669,6 @@ Objective-C and Objective-C++ Dialects}. -mtune-ctrl=@var{feature-list} -mdump-tune-features -mno-default @gol -mfpmath=@var{unit} @gol -masm=@var{dialect} -mno-fancy-math-387 @gol --mcopyrelocs @gol -mno-fp-ret-in-387 -msoft-float @gol -mno-wide-multiply -mrtd -malign-double @gol -mpreferred-stack-boundary=@var{num} @gol @@ -840,7 +840,7 @@ Objective-C and Objective-C++ Dialects}. @emph{MSP430 Options} @gccoptlist{-msim -masm-hex -mmcu= -mcpu= -mlarge -msmall -mrelax @gol --mhwmult=} +-mhwmult= -minrt} @emph{NDS32 Options} @gccoptlist{-mbig-endian -mlittle-endian @gol @@ -1091,7 +1091,7 @@ See S/390 and zSeries Options. -finstrument-functions-exclude-function-list=@var{sym},@var{sym},@dots{} @gol -finstrument-functions-exclude-file-list=@var{file},@var{file},@dots{} @gol -fno-common -fno-ident @gol --fpcc-struct-return -fpic -fPIC -fpie -fPIE @gol +-fpcc-struct-return -fpic -fPIC -fpie -fPIE -fno-plt @gol -fno-jump-tables @gol -frecord-gcc-switches @gol -freg-struct-return -fshort-enums @gol @@ -5426,6 +5426,11 @@ more details. The run-time behavior can be influenced using the @url{https://code.google.com/p/address-sanitizer/wiki/Flags#Run-time_flags} for a list of supported options. +@item -fsanitize=kernel-address +@opindex fsanitize=kernel-address +Enable AddressSanitizer for Linux kernel. +See @uref{http://code.google.com/p/address-sanitizer/wiki/AddressSanitizerForKernel} for more details. + @item -fsanitize=thread @opindex fsanitize=thread Enable ThreadSanitizer, a fast data race detector. @@ -7536,6 +7541,16 @@ registers after writing to their lower 32-bit half. Enabled for Alpha, AArch64 and x86 at levels @option{-O2}, @option{-O3}, @option{-Os}. +@item -fno-lifetime-dse +@opindex fno-lifetime-dse +In C++ the value of an object is only affected by changes within its +lifetime: when the constructor begins, the object has an indeterminate +value, and any changes during the lifetime of the object are dead when +the object is destroyed. Normally dead store elimination will take +advantage of this; if your code relies on the value of the object +storage persisting beyond the lifetime of the object, you can use this +flag to disable this optimization. + @item -flive-range-shrinkage @opindex flive-range-shrinkage Attempt to decrease register pressure through register live range @@ -9461,6 +9476,15 @@ You cannot use @code{gprof} on all systems if you specify this option, and you may have problems with debugging if you specify both this option and @option{-g}. +@item -ffunction-attribute-list +@opindex ffunction-attribute-list +List of function name patterns that will be applied specified attribute. +For example, the following command line will add "cold" attribute to +functions that has "ErrorMessage" in its name. +@smallexample +gcc -ffunction-atribute-list=cold:ErrorMessage -c foo.c +@end smallexample + @item -fbranch-target-load-optimize @opindex fbranch-target-load-optimize Perform branch target register load optimization before prologue / epilogue @@ -10412,6 +10436,12 @@ is enabled by default when using @option{-fsanitize=address} option. To disable use-after-return detection use @option{--param asan-use-after-return=0}. +@item asan-instrumentation-with-call-threshold +If number of memory accesses in function being instrumented +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}. + @end table @end table @@ -10578,6 +10608,11 @@ These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified. +@item -no-pie +@opindex no-pie +Produce a position dependent executable. This is the negative of option +@option{-pie} which produces a position independent executable. + @item -nostdlib @opindex nostdlib Do not use the standard system startup files or libraries when linking. @@ -12576,8 +12611,8 @@ architecture together with the optional CRC32 extensions. @option{-march=native} causes the compiler to auto-detect the architecture of the build computer. At present, this feature is only supported on -Linux, and not all architectures are recognized. If the auto-detect is -unsuccessful the option has no effect. +GNU/Linux, and not all architectures are recognized. If the auto-detect +is unsuccessful the option has no effect. @item -mtune=@var{name} @opindex mtune @@ -12628,7 +12663,7 @@ this option may change in future GCC versions as CPU models come and go. @option{-mtune=native} causes the compiler to auto-detect the CPU of the build computer. At present, this feature is only supported on -Linux, and not all architectures are recognized. If the auto-detect is +GNU/Linux, and not all architectures are recognized. If the auto-detect is unsuccessful the option has no effect. @item -mcpu=@var{name} @@ -12649,8 +12684,8 @@ See @option{-mtune} for more information. @option{-mcpu=native} causes the compiler to auto-detect the CPU of the build computer. At present, this feature is only supported on -Linux, and not all architectures are recognized. If the auto-detect is -unsuccessful the option has no effect. +GNU/Linux, and not all architectures are recognized. If the auto-detect +is unsuccessful the option has no effect. @item -mfpu=@var{name} @opindex mfpu @@ -15307,15 +15342,6 @@ Control whether or not the compiler uses IEEE floating-point comparisons. These correctly handle the case where the result of a comparison is unordered. -@item -mcopyrelocs -@itemx -mno-copyrelocs -@opindex mcopyrelocs -@opindex mno-copyrelocs -With @option{-fpie} and @option{fPIE}, copy relocations support allows the -compiler to assume that all symbol references are local. This allows the -compiler to skip the GOT for global accesses and this applies only to the -x86-64 architecture. - @item -msoft-float @opindex msoft-float Generate output containing library calls for floating point. @@ -18626,6 +18652,13 @@ The hardware multiply routines disable interrupts whilst running and restore the previous interrupt state when they finish. This makes them safe to use inside interrupt handlers as well as in normal code. +@item -minrt +@opindex minrt +Enable the use of a minimum runtime environment - no static +initializers or constructors. This is intended for memory-constrained +devices. The compiler will include special symbols in some objects +that tell the linker and runtime which code fragments are required. + @end table @node NDS32 Options @@ -21437,8 +21470,8 @@ the rules of the ABI@. Set the instruction set, register set, and instruction scheduling parameters for machine type @var{cpu_type}. Supported values for @var{cpu_type} are @samp{v7}, @samp{cypress}, @samp{v8}, @samp{supersparc}, @samp{hypersparc}, -@samp{leon}, @samp{leon3}, @samp{sparclite}, @samp{f930}, @samp{f934}, -@samp{sparclite86x}, @samp{sparclet}, @samp{tsc701}, @samp{v9}, +@samp{leon}, @samp{leon3}, @samp{leon3v7}, @samp{sparclite}, @samp{f930}, +@samp{f934}, @samp{sparclite86x}, @samp{sparclet}, @samp{tsc701}, @samp{v9}, @samp{ultrasparc}, @samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, @samp{niagara3} and @samp{niagara4}. @@ -21456,7 +21489,7 @@ implementations. @table @asis @item v7 -cypress +cypress, leon3v7 @item v8 supersparc, hypersparc, leon, leon3 @@ -21521,11 +21554,11 @@ option @option{-mcpu=@var{cpu_type}} does. The same values for @option{-mcpu=@var{cpu_type}} can be used for @option{-mtune=@var{cpu_type}}, but the only useful values are those that select a particular CPU implementation. Those are @samp{cypress}, -@samp{supersparc}, @samp{hypersparc}, @samp{leon}, @samp{leon3}, @samp{f930}, -@samp{f934}, @samp{sparclite86x}, @samp{tsc701}, @samp{ultrasparc}, -@samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, @samp{niagara3} and -@samp{niagara4}. With native Solaris and GNU/Linux toolchains, @samp{native} -can also be used. +@samp{supersparc}, @samp{hypersparc}, @samp{leon}, @samp{leon3}, +@samp{leon3v7}, @samp{f930}, @samp{f934}, @samp{sparclite86x}, @samp{tsc701}, +@samp{ultrasparc}, @samp{ultrasparc3}, @samp{niagara}, @samp{niagara2}, +@samp{niagara3} and @samp{niagara4}. With native Solaris and GNU/Linux +toolchains, @samp{native} can also be used. @item -mv8plus @itemx -mno-v8plus @@ -22695,6 +22728,24 @@ used during linking. @code{__pie__} and @code{__PIE__}. The macros have the value 1 for @option{-fpie} and 2 for @option{-fPIE}. +@item -fno-plt +@opindex fno-plt +Do not use PLT for external function calls in position-independent code. +Instead, load callee address at call site from GOT and branch to it. +This leads to more efficient code by eliminating PLT stubs and exposing +GOT load to optimizations. On architectures such as 32-bit x86 where +PLT stubs expect GOT pointer in a specific register, this gives more +register allocation freedom to the compiler. Lazy binding requires PLT: +with @option{-fno-plt} all external symbols are resolved at load time. + +Alternatively, function attribute @code{noplt} can be used to avoid PLT +for calls to specific external functions by marking those functions with +this attribute. + +Additionally, a few targets also convert calls to those functions that are +marked to not use the PLT to use the GOT instead for non-position independent +code. + @item -fno-jump-tables @opindex fno-jump-tables Do not use jump tables for switch statements even where it would be diff --git a/gcc-4.9/gcc/doc/md.texi b/gcc-4.9/gcc/doc/md.texi index 60ca79986..b210655f2 100644 --- a/gcc-4.9/gcc/doc/md.texi +++ b/gcc-4.9/gcc/doc/md.texi @@ -8418,9 +8418,9 @@ must be a @code{label_ref}. @cindex @code{pc} and attributes @item (pc) -This refers to the address of the @emph{current} insn. It might have -been more consistent with other usage to make this the address of the -@emph{next} insn but this would be confusing because the length of the +For non-branch instructions and backward branch instructions, this refers +to the address of the current insn. But for forward branch instructions, +this refers to the address of the next insn, because the length of the current insn is to be computed. @end table diff --git a/gcc-4.9/gcc/doc/sourcebuild.texi b/gcc-4.9/gcc/doc/sourcebuild.texi index 39152df27..6e3be1dc6 100644 --- a/gcc-4.9/gcc/doc/sourcebuild.texi +++ b/gcc-4.9/gcc/doc/sourcebuild.texi @@ -1714,6 +1714,9 @@ or @code{EM_SPARCV9} executables. @item vect_cmdline_needed 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. @end table @subsubsection Environment attributes diff --git a/gcc-4.9/gcc/doc/tm.texi b/gcc-4.9/gcc/doc/tm.texi index d512ebb92..2f3845ce0 100644 --- a/gcc-4.9/gcc/doc/tm.texi +++ b/gcc-4.9/gcc/doc/tm.texi @@ -3801,6 +3801,10 @@ fixed register. See @code{FIXED_REGISTERS} for more information. Default return value is @code{false}. @end deftypefn +@deftypefn {Target Hook} bool TARGET_CAN_OMIT_LEAF_FRAME_POINTER (void) +This target hook will return @code{true} if a function is a leaf function and +its frame pointer can be omitted on the target. +@end deftypefn @findex get_frame_size @defmac INITIAL_FRAME_POINTER_OFFSET (@var{depth-var}) @@ -4441,10 +4445,6 @@ to return a nonzero value when it is required, the compiler will run out of spill registers and print a fatal error message. @end deftypefn -@deftypevr {Target Hook} {unsigned int} TARGET_FLAGS_REGNUM -If the target has a dedicated flags register, and it needs to use the post-reload comparison elimination pass, then this value should be set appropriately. -@end deftypevr - @node Scalar Return @subsection How Scalar Function Values Are Returned @cindex return values in registers @@ -6047,10 +6047,11 @@ for comparisons whose argument is a @code{plus}: @smallexample #define SELECT_CC_MODE(OP,X,Y) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ - : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ - || GET_CODE (X) == NEG) \ + (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ + ? ((OP == LT || OP == LE || OP == GT || OP == GE) \ + ? CCFPEmode : CCFPmode) \ + : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ + || GET_CODE (X) == NEG || GET_CODE (x) == ASHIFT) \ ? CC_NOOVmode : CCmode)) @end smallexample @@ -6093,10 +6094,11 @@ then @code{REVERSIBLE_CC_MODE (@var{mode})} must be zero. You need not define this macro if it would always returns zero or if the floating-point format is anything other than @code{IEEE_FLOAT_FORMAT}. For example, here is the definition used on the SPARC, where floating-point -inequality comparisons are always given @code{CCFPEmode}: +inequality comparisons are given either @code{CCFPEmode} or @code{CCFPmode}: @smallexample -#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode) +#define REVERSIBLE_CC_MODE(MODE) \ + ((MODE) != CCFPEmode && (MODE) != CCFPmode) @end smallexample @end defmac @@ -6106,7 +6108,7 @@ comparison done in CC_MODE @var{mode}. The macro is used only in case @code{REVERSIBLE_CC_MODE (@var{mode})} is nonzero. Define this macro in case machine has some non-standard way how to reverse certain conditionals. For instance in case all floating point conditions are non-trapping, compiler may -freely convert unordered compares to ordered one. Then definition may look +freely convert unordered compares to ordered ones. Then definition may look like: @smallexample @@ -6144,6 +6146,10 @@ same. If they are, it returns that mode. If they are different, it returns @code{VOIDmode}. @end deftypefn +@deftypevr {Target Hook} {unsigned int} TARGET_FLAGS_REGNUM +If the target has a dedicated flags register, and it needs to use the post-reload comparison elimination pass, then this value should be set appropriately. +@end deftypevr + @node Costs @section Describing Relative Costs of Operations @cindex costs of instructions @@ -9521,6 +9527,10 @@ True if sched2 is not to be run at its normal place. This usually means it will True if vartrack is not to be run at its normal place. This usually means it will be run as part of machine-specific reorg. @end deftypevr +@deftypevr {Target Hook} bool TARGET_STRICT_ALIGN +True if it is beneficial to try stricter function or loop alignment on the target. +@end deftypevr + @defmac ASM_OUTPUT_DWARF_DELTA (@var{stream}, @var{size}, @var{label1}, @var{label2}) A C statement to issue assembly directives that create a difference @var{lab1} minus @var{lab2}, using an integer of the given @var{size}. @@ -11314,16 +11324,6 @@ routine for target specific customizations of the system printf and scanf formatter settings. @end defmac -@deftypevr {Target Hook} bool TARGET_RELAXED_ORDERING -If set to @code{true}, means that the target's memory model does not -guarantee that loads which do not depend on one another will access -main memory in the order of the instruction stream; if ordering is -important, an explicit memory barrier must be used. This is true of -many recent processors which implement a policy of ``relaxed,'' -``weak,'' or ``release'' memory consistency, such as Alpha, PowerPC, -and ia64. The default is @code{false}. -@end deftypevr - @deftypefn {Target Hook} {const char *} TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN (const_tree @var{typelist}, const_tree @var{funcdecl}, const_tree @var{val}) If defined, this macro returns the diagnostic message when it is illegal to pass argument @var{val} to function @var{funcdecl} @@ -11447,6 +11447,12 @@ Address Sanitizer shadow memory address. NULL if Address Sanitizer is not supported by the target. @end deftypefn +@deftypefn {Target Hook} rtx TARGET_SET_FP_INSN (void) +When flag_shrink_wrap_frame_pointer is true, fp setting insn should +be generated inside function body. The insertion is done after CFA +information is known. +@end deftypefn + @deftypefn {Target Hook} {unsigned HOST_WIDE_INT} TARGET_MEMMODEL_CHECK (unsigned HOST_WIDE_INT @var{val}) Validate target specific memory model mask bits. When NULL no target specific memory model bits are allowed. diff --git a/gcc-4.9/gcc/doc/tm.texi.in b/gcc-4.9/gcc/doc/tm.texi.in index fc040f5a9..3e9d2fbdc 100644 --- a/gcc-4.9/gcc/doc/tm.texi.in +++ b/gcc-4.9/gcc/doc/tm.texi.in @@ -3367,6 +3367,7 @@ defined and 0 otherwise. This is about eliminating the frame pointer and arg pointer. @hook TARGET_FRAME_POINTER_REQUIRED +@hook TARGET_CAN_OMIT_LEAF_FRAME_POINTER @findex get_frame_size @defmac INITIAL_FRAME_POINTER_OFFSET (@var{depth-var}) @@ -3714,8 +3715,6 @@ stack. @hook TARGET_SMALL_REGISTER_CLASSES_FOR_MODE_P -@hook TARGET_FLAGS_REGNUM - @node Scalar Return @subsection How Scalar Function Values Are Returned @cindex return values in registers @@ -4631,10 +4630,11 @@ for comparisons whose argument is a @code{plus}: @smallexample #define SELECT_CC_MODE(OP,X,Y) \ - (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ - ? ((OP == EQ || OP == NE) ? CCFPmode : CCFPEmode) \ - : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ - || GET_CODE (X) == NEG) \ + (GET_MODE_CLASS (GET_MODE (X)) == MODE_FLOAT \ + ? ((OP == LT || OP == LE || OP == GT || OP == GE) \ + ? CCFPEmode : CCFPmode) \ + : ((GET_CODE (X) == PLUS || GET_CODE (X) == MINUS \ + || GET_CODE (X) == NEG || GET_CODE (x) == ASHIFT) \ ? CC_NOOVmode : CCmode)) @end smallexample @@ -4657,10 +4657,11 @@ then @code{REVERSIBLE_CC_MODE (@var{mode})} must be zero. You need not define this macro if it would always returns zero or if the floating-point format is anything other than @code{IEEE_FLOAT_FORMAT}. For example, here is the definition used on the SPARC, where floating-point -inequality comparisons are always given @code{CCFPEmode}: +inequality comparisons are given either @code{CCFPEmode} or @code{CCFPmode}: @smallexample -#define REVERSIBLE_CC_MODE(MODE) ((MODE) != CCFPEmode) +#define REVERSIBLE_CC_MODE(MODE) \ + ((MODE) != CCFPEmode && (MODE) != CCFPmode) @end smallexample @end defmac @@ -4670,7 +4671,7 @@ comparison done in CC_MODE @var{mode}. The macro is used only in case @code{REVERSIBLE_CC_MODE (@var{mode})} is nonzero. Define this macro in case machine has some non-standard way how to reverse certain conditionals. For instance in case all floating point conditions are non-trapping, compiler may -freely convert unordered compares to ordered one. Then definition may look +freely convert unordered compares to ordered ones. Then definition may look like: @smallexample @@ -4684,6 +4685,8 @@ like: @hook TARGET_CC_MODES_COMPATIBLE +@hook TARGET_FLAGS_REGNUM + @node Costs @section Describing Relative Costs of Operations @cindex costs of instructions @@ -7188,6 +7191,8 @@ tables, and hence is desirable if it works. @hook TARGET_DELAY_VARTRACK +@hook TARGET_STRICT_ALIGN + @defmac ASM_OUTPUT_DWARF_DELTA (@var{stream}, @var{size}, @var{label1}, @var{label2}) A C statement to issue assembly directives that create a difference @var{lab1} minus @var{lab2}, using an integer of the given @var{size}. @@ -8405,8 +8410,6 @@ routine for target specific customizations of the system printf and scanf formatter settings. @end defmac -@hook TARGET_RELAXED_ORDERING - @hook TARGET_INVALID_ARG_FOR_UNPROTOTYPED_FN @hook TARGET_INVALID_CONVERSION @@ -8451,6 +8454,8 @@ and the associated definitions of those functions. @hook TARGET_ASAN_SHADOW_OFFSET +@hook TARGET_SET_FP_INSN + @hook TARGET_MEMMODEL_CHECK @hook TARGET_ATOMIC_TEST_AND_SET_TRUEVAL diff --git a/gcc-4.9/gcc/dse.c b/gcc-4.9/gcc/dse.c index 09dc5df6e..878fedcec 100644 --- a/gcc-4.9/gcc/dse.c +++ b/gcc-4.9/gcc/dse.c @@ -1549,6 +1549,10 @@ record_store (rtx body, bb_info_t bb_info) = rtx_group_vec[group_id]; mem_addr = group->canon_base_addr; } + /* get_addr can only handle VALUE but cannot handle expr like: + VALUE + OFFSET, so call get_addr to get original addr for + mem_addr before plus_constant. */ + mem_addr = get_addr (mem_addr); if (offset) mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); } @@ -2166,6 +2170,10 @@ check_mem_read_rtx (rtx *loc, void *data) = rtx_group_vec[group_id]; mem_addr = group->canon_base_addr; } + /* get_addr can only handle VALUE but cannot handle expr like: + VALUE + OFFSET, so call get_addr to get original addr for + mem_addr before plus_constant. */ + mem_addr = get_addr (mem_addr); if (offset) mem_addr = plus_constant (get_address_mode (mem), mem_addr, offset); } diff --git a/gcc-4.9/gcc/dwarf2out.c b/gcc-4.9/gcc/dwarf2out.c index ca4bd16e0..edcb553f1 100644 --- a/gcc-4.9/gcc/dwarf2out.c +++ b/gcc-4.9/gcc/dwarf2out.c @@ -2552,6 +2552,8 @@ typedef struct GTY(()) dw_line_info_table_struct { unsigned int line_num; unsigned int column_num; int discrim_num; + unsigned int subprog_num; + unsigned int context; bool is_stmt; bool in_use; @@ -12565,7 +12567,7 @@ mem_loc_descriptor (rtx rtl, enum machine_mode mode, op1 = mem_loc_descriptor (XEXP (rtl, 1), mode, mem_mode, VAR_INIT_STATUS_INITIALIZED); if (op1 == 0) - break; + return NULL; add_loc_descr (&mem_loc_result, op1); add_loc_descr (&mem_loc_result, new_loc_descr (DW_OP_plus, 0, 0)); @@ -14227,6 +14229,10 @@ loc_list_from_tree (tree loc, int want_address) have_address = 1; break; + case TARGET_MEM_REF: + case SSA_NAME: + return NULL; + case COMPOUND_EXPR: return loc_list_from_tree (TREE_OPERAND (loc, 1), want_address); @@ -17773,6 +17779,9 @@ dwarf2out_abstract_function (tree decl) int old_call_site_count, old_tail_call_site_count; struct call_arg_loc_node *old_call_arg_locations; + if (debug_line_tables_only) + return; + /* Make sure we have the actual abstract inline, not a clone. */ decl = DECL_ORIGIN (decl); @@ -20712,6 +20721,9 @@ dwarf2out_decl (tree decl) { dw_die_ref context_die; + if (debug_line_tables_only) + return; + /* In LIPO mode, we may output some functions whose type is defined in another function that will not be output. This can result in undefined location list symbols in the debug type info. @@ -20891,6 +20903,10 @@ dwarf2out_function_decl (tree decl) htab_empty (cached_dw_loc_list_table); } +/* For two-level line tables, we need to remember which block we're in. */ + +static vec block_stack; + /* Output a marker (i.e. a label) for the beginning of the generated code for a lexical block. */ @@ -20900,6 +20916,8 @@ dwarf2out_begin_block (unsigned int line ATTRIBUTE_UNUSED, { switch_to_section (current_function_section ()); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_BEGIN_LABEL, blocknum); + if (flag_two_level_line_tables && DWARF2_ASM_LINE_DEBUG_INFO) + block_stack.safe_push (blocknum); } /* Output a marker (i.e. a label) for the end of the generated code for a @@ -20910,6 +20928,8 @@ dwarf2out_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum) { switch_to_section (current_function_section ()); ASM_OUTPUT_DEBUG_LABEL (asm_out_file, BLOCK_END_LABEL, blocknum); + if (flag_two_level_line_tables && DWARF2_ASM_LINE_DEBUG_INFO) + block_stack.pop (); } /* Returns nonzero if it is appropriate not to emit any debugging @@ -21164,6 +21184,9 @@ dwarf2out_var_location (rtx loc_note) tree decl; bool var_loc_p; + if (debug_line_tables_only) + return; + if (!NOTE_P (loc_note)) { if (CALL_P (loc_note)) @@ -21376,6 +21399,8 @@ new_line_info_table (void) table = ggc_alloc_cleared_dw_line_info_table_struct (); table->file_num = 1; table->line_num = 1; + table->subprog_num = 0; + table->context = 0; table->is_stmt = DWARF_LINE_DEFAULT_IS_STMT_START; return table; @@ -21432,6 +21457,256 @@ set_cur_line_info_table (section *sec) cur_line_info_table = table; } +/* For two-level line tables, a table of subprograms, keyed by + the function decl node. We number each subprogram when we + output the .subprog opcode. */ + +struct subprog_entry +{ + tree decl; + bool is_inlined; + unsigned int subprog_num; +}; + +struct subprog_hasher : typed_free_remove +{ + typedef subprog_entry value_type; + typedef tree_node compare_type; + static hashval_t hash (const value_type *); + static bool equal (const value_type *, const compare_type *); +}; + +inline hashval_t +subprog_hasher::hash (const value_type *p) +{ + return DECL_UID (p->decl); +} + +inline bool +subprog_hasher::equal (const value_type *p1, const compare_type *p2) +{ + return p1->decl == p2; +} + +static hash_table *subprog_table; +static unsigned int last_subprog_num = 0; + +static subprog_entry * +add_subprog_entry (tree decl, bool is_inlined) +{ + subprog_entry **slot; + subprog_entry *entry; + + slot = subprog_table->find_slot_with_hash (decl, DECL_UID (decl), INSERT); + if (*slot == HTAB_EMPTY_ENTRY) + { + entry = XCNEW (struct subprog_entry); + entry->decl = decl; + entry->is_inlined = is_inlined; + entry->subprog_num = 0; + *slot = entry; + } + else if (is_inlined && !(*slot)->is_inlined) + { + /* If we've already output this subprogram entry as a non-inlined + subprogram, make sure it gets output again, so that we include + its linkage name. */ + (*slot)->is_inlined = true; + (*slot)->subprog_num = 0; + } + return *slot; +} + +/* For two-level line tables, a map from block number to an + inlined call chain. */ + +struct block_entry +{ + unsigned int block_num; + struct subprog_entry *subprog; + struct block_entry *caller; + location_t caller_loc; +}; + +struct block_hasher : typed_free_remove +{ + typedef block_entry value_type; + typedef unsigned int compare_type; + static hashval_t hash (const value_type *); + static bool equal (const value_type *, const compare_type *); +}; + +inline hashval_t +block_hasher::hash (const value_type *p) +{ + return (hashval_t) p->block_num; +} + +inline bool +block_hasher::equal (const value_type *p1, const compare_type *p2) +{ + return p1->block_num == *p2; +} + +static hash_table *block_table; + +/* For two-level line tables, a table of logical statements. + We number each logical statement when we output the .lloc opcode. */ + +struct logical_entry +{ + unsigned int file_num; + unsigned int line_num; + int discrim; + unsigned int subprog_num; + logical_entry *context; + unsigned int logical_num; +}; + +struct logical_hasher : typed_free_remove +{ + typedef logical_entry value_type; + typedef logical_entry compare_type; + static hashval_t hash (const value_type *); + static bool equal (const value_type *, const compare_type *); +}; + +inline hashval_t +logical_hasher::hash (const value_type *p) +{ + hashval_t h = p->file_num; + h = iterative_hash_object (p->line_num, h); + h = iterative_hash_object (p->discrim, h); + h = iterative_hash_object (p->subprog_num, h); + h = iterative_hash_object (p->context, h); + return h; +} + +inline bool +logical_hasher::equal (const value_type *p1, const compare_type *p2) +{ + return (p1->file_num == p2->file_num + && p1->line_num == p2->line_num + && p1->discrim == p2->discrim + && p1->subprog_num == p2->subprog_num + && p1->context == p2->context); +} + +static hash_table *logical_table; +static unsigned int last_logical_num = 0; + +/* Map BLOCK to the SUBPROG it belongs to, adding a block entry to block_table. + If BLOCK has been inlined, CALLER points to the block entry for the calling + context, and CALLER_LOC is the source location for the call. Process all + the subblocks recursively, so that we can map each block in a function to + the call chain leading to it. */ + +static void +scan_blocks_for_inlined_calls (tree block, subprog_entry *subprog, + block_entry *caller, location_t caller_loc) +{ + unsigned int block_num; + block_entry **slot; + block_entry *entry; + tree subblock; +#ifdef DEBUG_TWO_LEVEL + static unsigned int level = 0; +#endif + + if (block == NULL) + return; + +#ifdef DEBUG_TWO_LEVEL + if (level < 6) + { + unsigned int i; + + for (i = 0; i < level; i++) + fprintf(stderr, " "); + fprintf (stderr, "SCAN: [%p] block %d, subprog %s", + (void *) block, + BLOCK_NUMBER (block), + dwarf2_name (subprog->decl, 0)); + if (caller != NULL) + { + expanded_location loc = expand_location (caller_loc); + fprintf (stderr, ", caller %d (file %s line %d discrim %d)", + caller->block_num, loc.file, loc.line, + get_discriminator_from_locus (caller_loc)); + } + fprintf (stderr, "\n"); + } +#endif + + block_num = BLOCK_NUMBER (block); + slot = block_table->find_slot_with_hash (&block_num, (hashval_t) block_num, INSERT); + if (*slot != HTAB_EMPTY_ENTRY) + return; + entry = XCNEW (struct block_entry); + entry->block_num = block_num; + entry->subprog = subprog; + entry->caller = caller; + entry->caller_loc = caller_loc; + *slot = entry; + +#ifdef DEBUG_TWO_LEVEL + level++; +#endif + + for (subblock = BLOCK_SUBBLOCKS (block); + subblock != NULL; + subblock = BLOCK_CHAIN (subblock)) + { + if (! BLOCK_ABSTRACT (subblock) + && inlined_function_outer_scope_p (subblock)) + { + tree origin = block_ultimate_origin (subblock); + location_t loc = LOCATION_LOCUS (BLOCK_SOURCE_LOCATION (subblock)); + + scan_blocks_for_inlined_calls (subblock, + add_subprog_entry (origin, true), + entry, loc); + } + else + scan_blocks_for_inlined_calls (subblock, subprog, caller, caller_loc); + } + +#ifdef DEBUG_TWO_LEVEL + level--; +#endif + + for (subblock = BLOCK_FRAGMENT_CHAIN (block); + subblock != NULL; + subblock = BLOCK_FRAGMENT_CHAIN (subblock)) + { +#ifdef DEBUG_TWO_LEVEL + if (level < 6) + { + unsigned int i; + + for (i = 0; i < level; i++) + fprintf(stderr, " "); + fprintf (stderr, "SCAN: [%p] block frag %d, origin %d\n", + (void *) subblock, + BLOCK_NUMBER (subblock), + (BLOCK_FRAGMENT_ORIGIN (subblock) + ? BLOCK_NUMBER (BLOCK_FRAGMENT_ORIGIN (subblock)) + : -1)); + } +#endif + block_num = BLOCK_NUMBER (subblock); + slot = block_table->find_slot_with_hash (&block_num, (hashval_t) block_num, INSERT); + if (*slot == HTAB_EMPTY_ENTRY) + { + entry = XCNEW (struct block_entry); + entry->block_num = block_num; + entry->subprog = subprog; + entry->caller = caller; + entry->caller_loc = caller_loc; + *slot = entry; + } + } +} /* We need to reset the locations at the beginning of each function. We can't do this in the end_function hook, because the @@ -21460,6 +21735,20 @@ dwarf2out_begin_function (tree fun) tail_call_site_count = 0; set_cur_line_info_table (sec); + + if (flag_two_level_line_tables && DWARF2_ASM_LINE_DEBUG_INFO) + { + subprog_entry *subprog; + + block_table->empty (); + logical_table->empty (); +#ifdef DEBUG_TWO_LEVEL + fprintf (stderr, "Begin function %s\n", dwarf2_name (fun, 0)); +#endif + subprog = add_subprog_entry (fun, false); + scan_blocks_for_inlined_calls (DECL_INITIAL (fun), subprog, + NULL, UNKNOWN_LOCATION); + } } /* Helper function of dwarf2out_end_function, called only after emitting @@ -21527,6 +21816,165 @@ push_dw_line_info_entry (dw_line_info_table *table, vec_safe_push (table->entries, e); } +/* Two-level line tables: Output a .subprog directive. */ + +static void +out_subprog_directive (subprog_entry *subprog) +{ + tree decl = subprog->decl; + tree decl_name = DECL_NAME (decl); + tree origin = NULL_TREE; + const char *name = NULL; + unsigned int file_num = 0; + unsigned int line_num = 0; + + if (decl_name == NULL || IDENTIFIER_POINTER (decl_name) == NULL) + return; + + origin = decl_ultimate_origin (decl); + if (origin == NULL_TREE) + origin = decl; + + /* For inlined subroutines, use the linkage name. + If -ftwo-level-all-subprogs is set, use the linkage name + for all subroutines. */ + if (subprog->is_inlined || flag_two_level_all_subprogs) + { + if (DECL_ASSEMBLER_NAME (origin)) + { + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (origin)); + if (name[0] == '*') + name++; + } + else + name = dwarf2_name (origin, 0); + } + else + { + /* To save space, we don't emit the name for non-inlined + subroutines, whose linkage names are available from the + object file's symbol table. */ + name = ""; + } + + if (LOCATION_LOCUS (DECL_SOURCE_LOCATION (decl)) != UNKNOWN_LOCATION) + { + expanded_location s; + + s = expand_location (DECL_SOURCE_LOCATION (decl)); + file_num = maybe_emit_file (lookup_filename (s.file)); + line_num = s.line; + } + + subprog->subprog_num = ++last_subprog_num; + fprintf (asm_out_file, "\t.subprog %d \"%s\" %d %d\n", + subprog->subprog_num, name, file_num, line_num); +} + +/* Two-level line tables: Look for an entry in logical_table for a + logical row with the given attributes. Insert a new entry if not + present, recursively adding entries for caller contexts as necessary. + Output any necessary .lloc directives. */ + +static logical_entry * +out_logical_entry (dw_line_info_table *table, unsigned int file_num, + unsigned int line_num, int discriminator, + block_entry *block, bool is_stmt, bool is_context) +{ + subprog_entry *subprog = NULL; + unsigned int subprog_num = 0; + logical_entry probe; + logical_entry **slot; + logical_entry *entry; + logical_entry *context = NULL; + + /* Find the logical statement for the calling context, generating a new one + if necessary. */ + if (block != NULL && block->caller != NULL) + { + expanded_location s = expand_location (block->caller_loc); + unsigned int caller_file_num = maybe_emit_file (lookup_filename (s.file)); + int caller_discrim = get_discriminator_from_locus (block->caller_loc); + + context = out_logical_entry (table, caller_file_num, s.line, + caller_discrim, block->caller, + is_stmt, true); + } + + /* Declare the subprogram if it hasn't already been declared. */ + if (block != NULL) + subprog = block->subprog; + if (subprog != NULL && subprog->subprog_num == 0) + out_subprog_directive (subprog); + if (subprog != NULL) + subprog_num = subprog->subprog_num; + + probe.file_num = file_num; + probe.line_num = line_num; + probe.discrim = discriminator; + probe.subprog_num = subprog_num; + probe.context = context; + probe.logical_num = 0; + slot = logical_table->find_slot (&probe, INSERT); + + if (*slot == HTAB_EMPTY_ENTRY) + { + entry = XCNEW (struct logical_entry); + *entry = probe; + entry->logical_num = ++last_logical_num; + *slot = entry; + + /* Declare a new logical statement. */ + fputs ("\t.lloc ", asm_out_file); + fprint_ul (asm_out_file, entry->logical_num); + putc (' ', asm_out_file); + fprint_ul (asm_out_file, file_num); + putc (' ', asm_out_file); + fprint_ul (asm_out_file, line_num); + if (discriminator > 0) + { + fputs (" discriminator ", asm_out_file); + fprint_ul (asm_out_file, (unsigned long) discriminator); + } + if (subprog_num != 0) + { + fputs (" subprog ", asm_out_file); + fprint_ul (asm_out_file, subprog_num); + } + if (context != NULL) + { + fputs (" context ", asm_out_file); + fprint_ul (asm_out_file, context->logical_num); + } + if (is_stmt != table->is_stmt) + { + fputs (" is_stmt ", asm_out_file); + putc (is_stmt ? '1' : '0', asm_out_file); + table->is_stmt = is_stmt; + } + putc ('\n', asm_out_file); + } + else + { + entry = *slot; + + /* Switch to a previously-defined logical statement. */ + if (!is_context) + { + fputs ("\t.lloc ", asm_out_file); + fprint_ul (asm_out_file, entry->logical_num); + putc ('\n', asm_out_file); + } + } + + table->file_num = file_num; + table->line_num = line_num; + table->discrim_num = discriminator; + table->in_use = true; + + return entry; +} + /* Output a label to mark the beginning of a source code line entry and record information relating to this source line, in 'line_info_table' for later output of the .debug_line section. */ @@ -21576,6 +22024,28 @@ dwarf2out_source_line (unsigned int line, const char *filename, if (flag_debug_asm) fprintf (asm_out_file, "\t%s %s:%d\n", ASM_COMMENT_START, filename, line); + /* Two-level line tables. */ + if (flag_two_level_line_tables && DWARF2_ASM_LINE_DEBUG_INFO) + { + unsigned int block_num = 0; + block_entry **slot; + block_entry *block = NULL; + + /* Find the block_entry we created in the begin_function hook, + and get the subprogram and caller info. */ + if (!block_stack.is_empty ()) + block_num = block_stack.last (); + slot = block_table->find_slot_with_hash (&block_num, + (hashval_t) block_num, + NO_INSERT); + if (slot != NULL) + block = *slot; + + out_logical_entry (table, file_num, line, discriminator, block, is_stmt, + false); + return; + } + if (DWARF2_ASM_LINE_DEBUG_INFO) { /* Emit the .loc directive understood by GNU as. */ @@ -22156,6 +22626,17 @@ dwarf2out_init (const char *filename ATTRIBUTE_UNUSED) vec_alloc (used_rtx_array, 32); + /* Allocate the subprogram table and block-to-logical map. */ + if (flag_two_level_line_tables && DWARF2_ASM_LINE_DEBUG_INFO) + { + subprog_table = new hash_table (); + subprog_table->create (10); + block_table = new hash_table (); + block_table->create (10); + logical_table = new hash_table (); + logical_table->create (10); + } + if (!dwarf_split_debug_info) { debug_info_section = get_section (DEBUG_INFO_SECTION, @@ -24345,8 +24826,8 @@ dwarf2out_finish (const char *filename) } /* 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); + or .debug_macro will be emitted or if -gline-tables-only is set. */ + output_comp_unit (comp_unit_die (), have_macinfo || debug_line_tables_only); if (dwarf_split_debug_info && info_section_emitted) output_skeleton_debug_sections (main_comp_unit_die); @@ -24375,7 +24856,7 @@ dwarf2out_finish (const char *filename) to put in it. This because the consumer has no way to tell the difference between an empty table that we omitted and failure to generate a table that would have contained data. */ - if (info_section_emitted) + if (info_section_emitted && !debug_line_tables_only) { unsigned long aranges_length = size_of_aranges (); diff --git a/gcc-4.9/gcc/expmed.c b/gcc-4.9/gcc/expmed.c index 6e9975df3..0124a213b 100644 --- a/gcc-4.9/gcc/expmed.c +++ b/gcc-4.9/gcc/expmed.c @@ -463,7 +463,7 @@ strict_volatile_bitfield_p (rtx op0, unsigned HOST_WIDE_INT bitsize, /* Check for cases where the C++ memory model applies. */ if (bitregion_end != 0 && (bitnum - bitnum % modesize < bitregion_start - || bitnum - bitnum % modesize + modesize > bitregion_end)) + || bitnum - bitnum % modesize + modesize - 1 > bitregion_end)) return false; return true; @@ -679,28 +679,13 @@ store_bit_field_1 (rtx str_rtx, unsigned HOST_WIDE_INT bitsize, || (bitsize % BITS_PER_WORD == 0 && bitnum % BITS_PER_WORD == 0))) { /* Use the subreg machinery either to narrow OP0 to the required - words or to cope with mode punning between equal-sized modes. - In the latter case, use subreg on the rhs side, not lhs. */ - rtx sub; - - if (bitsize == GET_MODE_BITSIZE (GET_MODE (op0))) - { - sub = simplify_gen_subreg (GET_MODE (op0), value, fieldmode, 0); - if (sub) - { - emit_move_insn (op0, sub); - return true; - } - } - else - { - sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0), + words or to cope with mode punning between equal-sized modes. */ + rtx sub = simplify_gen_subreg (fieldmode, op0, GET_MODE (op0), bitnum / BITS_PER_UNIT); - if (sub) - { - emit_move_insn (sub, value); - return true; - } + if (sub) + { + emit_move_insn (sub, value); + return true; } } @@ -3321,6 +3306,9 @@ expand_widening_mult (enum machine_mode mode, rtx op0, rtx op1, rtx target, enum mult_variant variant; struct algorithm algorithm; + if (coeff == 0) + return CONST0_RTX (mode); + /* Special case powers of two. */ if (EXACT_POWER_OF_2_OR_ZERO_P (coeff)) { diff --git a/gcc-4.9/gcc/expr.c b/gcc-4.9/gcc/expr.c index ad8c05a90..8559d5146 100644 --- a/gcc-4.9/gcc/expr.c +++ b/gcc-4.9/gcc/expr.c @@ -7630,11 +7630,13 @@ expand_expr_addr_expr_1 (tree exp, rtx target, enum machine_mode tmode, break; case COMPOUND_LITERAL_EXPR: - /* Allow COMPOUND_LITERAL_EXPR in initializers, if e.g. - rtl_for_decl_init is called on DECL_INITIAL with - COMPOUNT_LITERAL_EXPRs in it, they aren't gimplified. */ - if (modifier == EXPAND_INITIALIZER - && COMPOUND_LITERAL_EXPR_DECL (exp)) + /* Allow COMPOUND_LITERAL_EXPR in initializers or coming from + initializers, if e.g. rtl_for_decl_init is called on DECL_INITIAL + with COMPOUND_LITERAL_EXPRs in it, or ARRAY_REF on a const static + array with address of COMPOUND_LITERAL_EXPR in DECL_INITIAL; + the initializers aren't gimplified. */ + if (COMPOUND_LITERAL_EXPR_DECL (exp) + && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp))) return expand_expr_addr_expr_1 (COMPOUND_LITERAL_EXPR_DECL (exp), target, tmode, modifier, as); /* FALLTHRU */ @@ -10004,7 +10006,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, tree tem = get_inner_reference (exp, &bitsize, &bitpos, &offset, &mode1, &unsignedp, &volatilep, true); rtx orig_op0, memloc; - bool mem_attrs_from_type = false; + bool clear_mem_expr = false; /* If we got back the original object, something is wrong. Perhaps we are evaluating an expression too early. In any event, don't @@ -10100,7 +10102,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, memloc = assign_temp (TREE_TYPE (tem), 1, 1); emit_move_insn (memloc, op0); op0 = memloc; - mem_attrs_from_type = true; + clear_mem_expr = true; } if (offset) @@ -10285,17 +10287,17 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, if (op0 == orig_op0) op0 = copy_rtx (op0); - /* If op0 is a temporary because of forcing to memory, pass only the - type to set_mem_attributes so that the original expression is never - marked as ADDRESSABLE through MEM_EXPR of the temporary. */ - if (mem_attrs_from_type) - set_mem_attributes (op0, type, 0); - else - set_mem_attributes (op0, exp, 0); + set_mem_attributes (op0, exp, 0); if (REG_P (XEXP (op0, 0))) mark_reg_pointer (XEXP (op0, 0), MEM_ALIGN (op0)); + /* If op0 is a temporary because the original expressions was forced + to memory, clear MEM_EXPR so that the original expression cannot + be marked as addressable through MEM_EXPR of the temporary. */ + if (clear_mem_expr) + set_mem_expr (op0, NULL_TREE); + MEM_VOLATILE_P (op0) |= volatilep; if (mode == mode1 || mode1 == BLKmode || mode1 == tmode || modifier == EXPAND_CONST_ADDRESS @@ -10681,7 +10683,7 @@ is_aligning_offset (const_tree offset, const_tree exp) || !tree_fits_uhwi_p (TREE_OPERAND (offset, 1)) || compare_tree_int (TREE_OPERAND (offset, 1), BIGGEST_ALIGNMENT / BITS_PER_UNIT) <= 0 - || !exact_log2 (tree_to_uhwi (TREE_OPERAND (offset, 1)) + 1) < 0) + || exact_log2 (tree_to_uhwi (TREE_OPERAND (offset, 1)) + 1) < 0) return 0; /* Look at the first operand of BIT_AND_EXPR and strip any conversion. diff --git a/gcc-4.9/gcc/final.c b/gcc-4.9/gcc/final.c index 38c90b281..3bf3fdb67 100644 --- a/gcc-4.9/gcc/final.c +++ b/gcc-4.9/gcc/final.c @@ -789,6 +789,15 @@ compute_alignments (void) max_log = log; max_skip = targetm.asm_out.loop_align_max_skip (label); } + /* For small size loop, let them align more strictly. */ + if (targetm.strict_align + && bb->loop_father->num + && (bb->loop_father->ninsns + <= PARAM_VALUE (PARAM_ALIGN_LOOP_SIZE))) + { + max_log = max_log + 1; + max_skip = max_skip * 2; + } } LABEL_TO_ALIGNMENT (label) = max_log; LABEL_TO_MAX_SKIP (label) = max_skip; @@ -1793,18 +1802,6 @@ final_start_function (rtx first, FILE *file, profile_function (file); } - /* If debugging, assign block numbers to all of the blocks in this - function. */ - if (write_symbols) - { - reemit_insn_block_notes (); - number_blocks (current_function_decl); - /* We never actually put out begin/end notes for the top-level - block in the function. But, conceptually, that block is - always needed. */ - TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1; - } - if (warn_frame_larger_than && get_frame_size () > frame_larger_than_size) { @@ -2174,10 +2171,16 @@ final_scan_insn (rtx insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, suffixing "cold" to the original function's name. */ if (in_cold_section_p) { - tree cold_function_name + cold_function_name = clone_function_name (current_function_decl, "cold"); +#ifdef ASM_DECLARE_FUNCTION_NAME + ASM_DECLARE_FUNCTION_NAME (asm_out_file, + IDENTIFIER_POINTER (cold_function_name), + current_function_decl); +#else ASM_OUTPUT_LABEL (asm_out_file, IDENTIFIER_POINTER (cold_function_name)); +#endif } has_cold_section_p = true; break; @@ -4489,6 +4492,18 @@ rest_of_handle_final (void) has_cold_section_p = false; + /* If debugging, assign block numbers to all of the blocks in this + function. */ + if (write_symbols) + { + reemit_insn_block_notes (); + number_blocks (current_function_decl); + /* We never actually put out begin/end notes for the top-level + block in the function. But, conceptually, that block is + always needed. */ + TREE_ASM_WRITTEN (DECL_INITIAL (current_function_decl)) = 1; + } + assemble_start_function (current_function_decl, fnname); final_start_function (get_insns (), asm_out_file, optimize); final (get_insns (), asm_out_file, optimize); @@ -4540,7 +4555,7 @@ rest_of_handle_final (void) /* With -fcallgraph-profiles-sections and -freorder-functions=, add ".gnu.callgraph.text" section for storing profiling information. */ if ((flag_reorder_functions > 1) - && flag_profile_use + && (flag_profile_use || flag_auto_profile) && cgraph_get_node (current_function_decl) != NULL && ((cgraph_get_node (current_function_decl))->callees != NULL || (cgraph_get_node (current_function_decl))->count > 0)) diff --git a/gcc-4.9/gcc/flag-types.h b/gcc-4.9/gcc/flag-types.h index ec16faa18..1dd1b3ea5 100644 --- a/gcc-4.9/gcc/flag-types.h +++ b/gcc-4.9/gcc/flag-types.h @@ -204,20 +204,22 @@ enum vect_cost_model { enum sanitize_code { /* AddressSanitizer. */ SANITIZE_ADDRESS = 1 << 0, + SANITIZE_USER_ADDRESS = 1 << 1, + SANITIZE_KERNEL_ADDRESS = 1 << 2, /* ThreadSanitizer. */ - SANITIZE_THREAD = 1 << 1, + SANITIZE_THREAD = 1 << 3, /* LeakSanitizer. */ - SANITIZE_LEAK = 1 << 2, + SANITIZE_LEAK = 1 << 4, /* UndefinedBehaviorSanitizer. */ - SANITIZE_SHIFT = 1 << 3, - SANITIZE_DIVIDE = 1 << 4, - SANITIZE_UNREACHABLE = 1 << 5, - SANITIZE_VLA = 1 << 6, - SANITIZE_NULL = 1 << 7, - SANITIZE_RETURN = 1 << 8, - SANITIZE_SI_OVERFLOW = 1 << 9, - SANITIZE_BOOL = 1 << 10, - SANITIZE_ENUM = 1 << 11, + SANITIZE_SHIFT = 1 << 5, + SANITIZE_DIVIDE = 1 << 6, + SANITIZE_UNREACHABLE = 1 << 7, + SANITIZE_VLA = 1 << 8, + SANITIZE_NULL = 1 << 9, + SANITIZE_RETURN = 1 << 10, + SANITIZE_SI_OVERFLOW = 1 << 11, + SANITIZE_BOOL = 1 << 12, + SANITIZE_ENUM = 1 << 13, SANITIZE_UNDEFINED = SANITIZE_SHIFT | SANITIZE_DIVIDE | SANITIZE_UNREACHABLE | SANITIZE_VLA | SANITIZE_NULL | SANITIZE_RETURN | SANITIZE_SI_OVERFLOW | SANITIZE_BOOL | SANITIZE_ENUM diff --git a/gcc-4.9/gcc/fold-const.c b/gcc-4.9/gcc/fold-const.c index 11f3d0c1e..1f0d1988d 100644 --- a/gcc-4.9/gcc/fold-const.c +++ b/gcc-4.9/gcc/fold-const.c @@ -9097,7 +9097,8 @@ fold_comparison (location_t loc, enum tree_code code, tree type, /* If the constant operation overflowed this can be simplified as a comparison against INT_MAX/INT_MIN. */ if (TREE_CODE (lhs) == INTEGER_CST - && TREE_OVERFLOW (lhs)) + && TREE_OVERFLOW (lhs) + && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (arg0))) { int const1_sgn = tree_int_cst_sgn (const1); enum tree_code code2 = code; @@ -13368,7 +13369,7 @@ fold_binary_loc_1 (location_t loc, tree itype = TREE_TYPE (arg00); if (TREE_INT_CST_HIGH (arg01) == 0 && TREE_INT_CST_LOW (arg01) - == (unsigned HOST_WIDE_INT) (TYPE_PRECISION (itype) - 1)) + == (unsigned HOST_WIDE_INT) (element_precision (itype) - 1)) { if (TYPE_UNSIGNED (itype)) { diff --git a/gcc-4.9/gcc/fortran/ChangeLog b/gcc-4.9/gcc/fortran/ChangeLog index 9f4bec74e..3828f1ab1 100644 --- a/gcc-4.9/gcc/fortran/ChangeLog +++ b/gcc-4.9/gcc/fortran/ChangeLog @@ -1,3 +1,68 @@ +2015-01-14 Jakub Jelinek + + Backported from mainline + 2015-01-13 Jakub Jelinek + + PR fortran/64528 + * trans-decl.c (create_function_arglist): Don't set TREE_READONLY + on dummy args with VALUE attribute. + +2015-01-12 Janus Weil + + Backport from mainline + PR fortran/63733 + * interface.c (gfc_extend_expr): Look for type-bound operators before + non-typebound ones. + +2015-01-08 Thomas Koenig + + Backport from trunk + PR fortran/56867 + * trans-array.c (gfc_conv_resolve_dependencies): Also check + dependencies when there may be substrings of character arrays. + +2014-12-23 Janus Weil + + Backport from mainline + PR fortran/64244 + * resolve.c (resolve_typebound_call): New argument to pass out the + non-overridable attribute of the specific procedure. + (resolve_typebound_subroutine): Get overridable flag from + resolve_typebound_call. + +2014-11-28 Jakub Jelinek + + Backported from mainline + 2014-11-24 Jakub Jelinek + + PR fortran/63938 + * trans-openmp.c (gfc_trans_omp_atomic): Make sure lhsaddr is + simple enough for goa_lhs_expr_p. + +2014-10-30 Release Manager + + * GCC 4.9.2 released. + +2014-10-10 Jakub Jelinek + + PR fortran/59488 + * trans-openmp.c (gfc_omp_predetermined_sharing): Return + OMP_CLAUSE_DEFAULT_SHARED for parameters or vtables. + +2014-09-03 Marek Polacek + + Backport from trunk + PR fortran/62270 + * interface.c (compare_parameter): Fix condition. + * trans-expr.c (gfc_conv_procedure_call): Likewise. + +2014-08-29 Jeffrey Armstrong + + Backport from trunk + PR fortran/62215 + * module.c (gfc_dump_module): Unlink old module file before + renaming new one. + 2014-08-21 Thomas Koenig Backport from trunk diff --git a/gcc-4.9/gcc/fortran/interface.c b/gcc-4.9/gcc/fortran/interface.c index 67548c062..f24641c1e 100644 --- a/gcc-4.9/gcc/fortran/interface.c +++ b/gcc-4.9/gcc/fortran/interface.c @@ -2014,7 +2014,7 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual, if (formal->ts.type == BT_CLASS && formal->attr.class_ok && actual->expr_type != EXPR_NULL && ((CLASS_DATA (formal)->attr.class_pointer - && !formal->attr.intent == INTENT_IN) + && formal->attr.intent != INTENT_IN) || CLASS_DATA (formal)->attr.allocatable)) { if (actual->ts.type != BT_CLASS) @@ -3675,6 +3675,8 @@ gfc_extend_expr (gfc_expr *e) gfc_user_op *uop; gfc_intrinsic_op i; const char *gname; + gfc_typebound_proc* tbo; + gfc_expr* tb_base; sym = NULL; @@ -3691,6 +3693,48 @@ gfc_extend_expr (gfc_expr *e) i = fold_unary_intrinsic (e->value.op.op); + /* See if we find a matching type-bound operator. */ + if (i == INTRINSIC_USER) + tbo = matching_typebound_op (&tb_base, actual, + i, e->value.op.uop->name, &gname); + else + switch (i) + { +#define CHECK_OS_COMPARISON(comp) \ + case INTRINSIC_##comp: \ + case INTRINSIC_##comp##_OS: \ + tbo = matching_typebound_op (&tb_base, actual, \ + INTRINSIC_##comp, NULL, &gname); \ + if (!tbo) \ + tbo = matching_typebound_op (&tb_base, actual, \ + INTRINSIC_##comp##_OS, NULL, &gname); \ + break; + CHECK_OS_COMPARISON(EQ) + CHECK_OS_COMPARISON(NE) + CHECK_OS_COMPARISON(GT) + CHECK_OS_COMPARISON(GE) + CHECK_OS_COMPARISON(LT) + CHECK_OS_COMPARISON(LE) +#undef CHECK_OS_COMPARISON + + default: + tbo = matching_typebound_op (&tb_base, actual, i, NULL, &gname); + break; + } + + /* If there is a matching typebound-operator, replace the expression with + a call to it and succeed. */ + if (tbo) + { + gcc_assert (tb_base); + build_compcall_for_operator (e, actual, tb_base, tbo, gname); + + if (!gfc_resolve_expr (e)) + return MATCH_ERROR; + else + return MATCH_YES; + } + if (i == INTRINSIC_USER) { for (ns = gfc_current_ns; ns; ns = ns->parent) @@ -3741,58 +3785,9 @@ gfc_extend_expr (gfc_expr *e) if (sym == NULL) { - gfc_typebound_proc* tbo; - gfc_expr* tb_base; - - /* See if we find a matching type-bound operator. */ - if (i == INTRINSIC_USER) - tbo = matching_typebound_op (&tb_base, actual, - i, e->value.op.uop->name, &gname); - else - switch (i) - { -#define CHECK_OS_COMPARISON(comp) \ - case INTRINSIC_##comp: \ - case INTRINSIC_##comp##_OS: \ - tbo = matching_typebound_op (&tb_base, actual, \ - INTRINSIC_##comp, NULL, &gname); \ - if (!tbo) \ - tbo = matching_typebound_op (&tb_base, actual, \ - INTRINSIC_##comp##_OS, NULL, &gname); \ - break; - CHECK_OS_COMPARISON(EQ) - CHECK_OS_COMPARISON(NE) - CHECK_OS_COMPARISON(GT) - CHECK_OS_COMPARISON(GE) - CHECK_OS_COMPARISON(LT) - CHECK_OS_COMPARISON(LE) -#undef CHECK_OS_COMPARISON - - default: - tbo = matching_typebound_op (&tb_base, actual, i, NULL, &gname); - break; - } - - /* If there is a matching typebound-operator, replace the expression with - a call to it and succeed. */ - if (tbo) - { - bool result; - - gcc_assert (tb_base); - build_compcall_for_operator (e, actual, tb_base, tbo, gname); - - result = gfc_resolve_expr (e); - if (!result) - return MATCH_ERROR; - - return MATCH_YES; - } - /* Don't use gfc_free_actual_arglist(). */ free (actual->next); free (actual); - return MATCH_NO; } diff --git a/gcc-4.9/gcc/fortran/module.c b/gcc-4.9/gcc/fortran/module.c index 2bfe17784..f50c5b740 100644 --- a/gcc-4.9/gcc/fortran/module.c +++ b/gcc-4.9/gcc/fortran/module.c @@ -6072,7 +6072,10 @@ gfc_dump_module (const char *name, int dump_flag) || crc_old != crc) { /* Module file have changed, replace the old one. */ - if (rename (filename_tmp, filename)) + if (unlink (filename) && errno != ENOENT) + gfc_fatal_error ("Can't delete module file '%s': %s", filename, + xstrerror (errno)); + if (rename (filename_tmp, filename)) gfc_fatal_error ("Can't rename module file '%s' to '%s': %s", filename_tmp, filename, xstrerror (errno)); } diff --git a/gcc-4.9/gcc/fortran/resolve.c b/gcc-4.9/gcc/fortran/resolve.c index c959f5d95..a23f6d44c 100644 --- a/gcc-4.9/gcc/fortran/resolve.c +++ b/gcc-4.9/gcc/fortran/resolve.c @@ -5590,7 +5590,7 @@ success: /* Resolve a call to a type-bound subroutine. */ static bool -resolve_typebound_call (gfc_code* c, const char **name) +resolve_typebound_call (gfc_code* c, const char **name, bool *overridable) { gfc_actual_arglist* newactual; gfc_symtree* target; @@ -5614,6 +5614,10 @@ resolve_typebound_call (gfc_code* c, const char **name) if (!resolve_typebound_generic_call (c->expr1, name)) return false; + /* Pass along the NON_OVERRIDABLE attribute of the specific TBP. */ + if (overridable) + *overridable = !c->expr1->value.compcall.tbp->non_overridable; + /* Transform into an ordinary EXEC_CALL for now. */ if (!resolve_typebound_static (c->expr1, &target, &newactual)) @@ -5873,7 +5877,7 @@ resolve_typebound_subroutine (gfc_code *code) if (c->ts.u.derived == NULL) c->ts.u.derived = gfc_find_derived_vtab (declared); - if (!resolve_typebound_call (code, &name)) + if (!resolve_typebound_call (code, &name, NULL)) return false; /* Use the generic name if it is there. */ @@ -5905,7 +5909,7 @@ resolve_typebound_subroutine (gfc_code *code) } if (st == NULL) - return resolve_typebound_call (code, NULL); + return resolve_typebound_call (code, NULL, NULL); if (!resolve_ref (code->expr1)) return false; @@ -5918,10 +5922,10 @@ resolve_typebound_subroutine (gfc_code *code) || (!class_ref && st->n.sym->ts.type != BT_CLASS)) { gfc_free_ref_list (new_ref); - return resolve_typebound_call (code, NULL); + return resolve_typebound_call (code, NULL, NULL); } - if (!resolve_typebound_call (code, &name)) + if (!resolve_typebound_call (code, &name, &overridable)) { gfc_free_ref_list (new_ref); return false; diff --git a/gcc-4.9/gcc/fortran/trans-array.c b/gcc-4.9/gcc/fortran/trans-array.c index a36db45c0..8e5bea191 100644 --- a/gcc-4.9/gcc/fortran/trans-array.c +++ b/gcc-4.9/gcc/fortran/trans-array.c @@ -4350,6 +4350,13 @@ gfc_conv_resolve_dependencies (gfc_loopinfo * loop, gfc_ss * dest, && ss_expr->rank) nDepend = gfc_check_dependency (dest_expr, ss_expr, true); + /* Check for cases like c(:)(1:2) = c(2)(2:3) */ + if (!nDepend && dest_expr->rank > 0 + && dest_expr->ts.type == BT_CHARACTER + && ss_expr->expr_type == EXPR_VARIABLE) + + nDepend = gfc_check_dependency (dest_expr, ss_expr, false); + continue; } diff --git a/gcc-4.9/gcc/fortran/trans-decl.c b/gcc-4.9/gcc/fortran/trans-decl.c index 2b0667960..4b3e89b79 100644 --- a/gcc-4.9/gcc/fortran/trans-decl.c +++ b/gcc-4.9/gcc/fortran/trans-decl.c @@ -2262,8 +2262,9 @@ create_function_arglist (gfc_symbol * sym) /* Fill in arg stuff. */ DECL_CONTEXT (parm) = fndecl; DECL_ARG_TYPE (parm) = TREE_VALUE (typelist); - /* All implementation args are read-only. */ - TREE_READONLY (parm) = 1; + /* All implementation args except for VALUE are read-only. */ + if (!f->sym->attr.value) + TREE_READONLY (parm) = 1; if (POINTER_TYPE_P (type) && (!f->sym->attr.proc_pointer && f->sym->attr.flavor != FL_PROCEDURE)) diff --git a/gcc-4.9/gcc/fortran/trans-expr.c b/gcc-4.9/gcc/fortran/trans-expr.c index 824ab785b..2b06304cb 100644 --- a/gcc-4.9/gcc/fortran/trans-expr.c +++ b/gcc-4.9/gcc/fortran/trans-expr.c @@ -4409,7 +4409,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym, && e->expr_type == EXPR_VARIABLE && (!e->ref || (e->ref->type == REF_ARRAY - && !e->ref->u.ar.type != AR_FULL)) + && e->ref->u.ar.type != AR_FULL)) && e->symtree->n.sym->attr.optional) { tmp = fold_build3_loc (input_location, COND_EXPR, diff --git a/gcc-4.9/gcc/fortran/trans-openmp.c b/gcc-4.9/gcc/fortran/trans-openmp.c index 548b5d3a4..3b0e6e9e9 100644 --- a/gcc-4.9/gcc/fortran/trans-openmp.c +++ b/gcc-4.9/gcc/fortran/trans-openmp.c @@ -135,6 +135,16 @@ gfc_omp_predetermined_sharing (tree decl) if (GFC_DECL_RESULT (decl) && ! DECL_HAS_VALUE_EXPR_P (decl)) return OMP_CLAUSE_DEFAULT_SHARED; + /* These are either array or derived parameters, or vtables. + In the former cases, the OpenMP standard doesn't consider them to be + variables at all (they can't be redefined), but they can nevertheless appear + in parallel/task regions and for default(none) purposes treat them as shared. + For vtables likely the same handling is desirable. */ + if (TREE_CODE (decl) == VAR_DECL + && TREE_READONLY (decl) + && TREE_STATIC (decl)) + return OMP_CLAUSE_DEFAULT_SHARED; + return OMP_CLAUSE_DEFAULT_UNSPECIFIED; } @@ -2673,6 +2683,18 @@ gfc_trans_omp_atomic (gfc_code *code) } lhsaddr = save_expr (lhsaddr); + if (TREE_CODE (lhsaddr) != SAVE_EXPR + && (TREE_CODE (lhsaddr) != ADDR_EXPR + || TREE_CODE (TREE_OPERAND (lhsaddr, 0)) != VAR_DECL)) + { + /* Make sure LHS is simple enough so that goa_lhs_expr_p can recognize + it even after unsharing function body. */ + tree var = create_tmp_var_raw (TREE_TYPE (lhsaddr), NULL); + DECL_CONTEXT (var) = current_function_decl; + lhsaddr = build4 (TARGET_EXPR, TREE_TYPE (lhsaddr), var, lhsaddr, + NULL_TREE, NULL_TREE); + } + rhs = gfc_evaluate_now (rse.expr, &block); if (((atomic_code->ext.omp_atomic & GFC_OMP_ATOMIC_MASK) diff --git a/gcc-4.9/gcc/function.c b/gcc-4.9/gcc/function.c index e41d3d7a4..2dcf2060f 100644 --- a/gcc-4.9/gcc/function.c +++ b/gcc-4.9/gcc/function.c @@ -64,6 +64,8 @@ along with GCC; see the file COPYING3. If not see #include "l-ipo.h" #include "params.h" #include "bb-reorder.h" +#include "domwalk.h" +#include "dbgcnt.h" /* So we can assign to cfun in this file. */ #undef cfun @@ -5598,6 +5600,14 @@ prepare_shrink_wrap (basic_block entry_block) if (REG_P (x) && HARD_REGISTER_P (x)) SET_HARD_REG_BIT (uses, REGNO (x)); } + + /* If frame_pointer_partially_needed, compiler will + implicitly insert frame pointer setting insn + before call after prologue is generated. So + assume an implicit def immediately before any + call insn. */ + if (frame_pointer_partially_needed && CALL_P (insn)) + SET_HARD_REG_BIT (defs, HARD_FRAME_POINTER_REGNUM); } } @@ -5856,6 +5866,698 @@ emit_return_for_exit (edge exit_fallthru_edge, bool simple_p) } #endif +struct bb_fpset +{ + basic_block bb; + /* There is call in this bb and there is no fp def or use + between the call and bb entry. */ + bool has_orig_upexposed_fpset; + /* If it is needed to insert fpset on the entry of bb, + we tend to insert it before the original call. */ + rtx place_for_upexposed_fpset; + /* There is call in this bb, it is not bb upward exposed and + there is no fp def and use between the call and bb exit. */ + bool has_orig_downexposed_fpset; + + /* fpset from bbs below could be moved across the current bb + to its dominator. There are two cases when transparent is + false: + 1. There is any fp reference in current bb. + 2. fp is in the live-out set of current bb. */ + bool transparent; + /* There is any fp reference in current bb. Only for dumping. */ + bool has_fp_ref; + + /* If there is fp setting insn moved to here from other bb. */ + bool moved_to_here; + + /* If a fp setting insn to be moved here, insert it + in the bb as early as possible. place_to_move is the place + to moved to. It is trying not to break the macrofusion of + cond and jump. */ + rtx place_to_move; + + /* The target bb set the fp setting in current bb could move + to, .i.e, any path between target bb and current bb has no + fp def or use. */ + sbitmap can_move_to; + + /* The list connecting child bbs having upward exposed fp + setting which are possible promotion candidates. */ + struct bb_fpset *next, *end; +}; + +/* The object containing information about fpsetting insns inside + a bb. fp setting insns are those insns saving frame address to + fp. */ +static struct bb_fpset *bb_fpsets; + +/* Dump the link list connecting all the promotion candidates below + the current bb. */ +DEBUG_FUNCTION static void +dump_fpset_list (FILE *file, struct bb_fpset *fpset) +{ + struct bb_fpset *subnode; + + fprintf (file, "bb%d contains link list:\n", fpset->bb->index); + subnode = fpset->next; + while (subnode) + { + fprintf (file, "-> bb%d", subnode->bb->index); +#ifdef ENABLE_CHECKING + gcc_assert(subnode->end == NULL); + if (!subnode->next) + gcc_assert(fpset->end == subnode); +#endif + subnode = subnode->next; + } + fprintf (file, "\n"); +} + +/* For a link list, only starting node have non-NULL next and end fields. + the end field should point to the last node in the link list. For the + nodes except the starting one, their end field should be NULL. */ +DEBUG_FUNCTION static void +fpset_list_sanity_check (struct bb_fpset *fpset) +{ + struct bb_fpset *subnode; + subnode = fpset->next; + if (!subnode) + gcc_assert (!fpset->end); + else + { + while (subnode) + { + gcc_assert(subnode->end == NULL); + if (!subnode->next) + gcc_assert(fpset->end == subnode); + subnode = subnode->next; + } + } +} + +/* Dump the status of shrinkwrapping contained in FPSET. */ +static void +dump_bb_fpset (FILE *file, struct bb_fpset *fpset) +{ + int place_for_upexposed_fpset = fpset->place_for_upexposed_fpset ? + INSN_UID (fpset->place_for_upexposed_fpset) + : -1; + int place_to_move = fpset->place_to_move ? INSN_UID (fpset->place_to_move) + : -1; + fprintf(file, + "bb[%d]: upexposed_fpset: %d, place for upexposed_fpset: %d\n" + " downexposed_fpset: %d, transparent: %d\n" + " moved_to_here: %d, has_fp_ref: %d\n" + " place_to_move: %d\n", + fpset->bb->index, fpset->has_orig_upexposed_fpset, + place_for_upexposed_fpset, + fpset->has_orig_downexposed_fpset, fpset->transparent, + fpset->moved_to_here, fpset->has_fp_ref, place_to_move); + fprintf(file, " "); + dump_bitmap_file (file, fpset->can_move_to); +} + +/* For each bb, initialize the bb_fpset structure for it. struct bb_fpset + is the central data structure used in shrinkwrapping. LOCAL_INSERTS + record the places where we need a fp setting locally inside bb + without the need to move it. CALLS are the call insns needing a + reg use note at the end of shrinkwrapping. The reg use notes are + used to make sure DCE not to delete inserted fp settings. */ +static void +bb_fpset_local_init (vec *local_inserts, vec *calls) +{ + basic_block bb; + rtx insn, insert_before = NULL; + rtx place_to_move = NULL; + bool place_to_move_set = false; + + if (dump_file) + fprintf(dump_file, "\nfpset dump after init:\n"); + + any_fp_def = false; + FOR_EACH_BB_FN (bb, cfun) + { + bb_fpsets[bb->index].bb = bb; + bb_fpsets[bb->index].can_move_to = + sbitmap_alloc (last_basic_block_for_fn (cfun)); + bitmap_clear (bb_fpsets[bb->index].can_move_to); + bb_fpsets[bb->index].transparent = true; + insert_before = NULL; + place_to_move = NULL; + place_to_move_set = false; + + FOR_BB_INSNS_REVERSE (bb, insn) + { + bool fp_def_use = false; + + if (CALL_P (insn)) + { + /* Check whether fp is explicitly used in call target, + like, call *fp. */ + HARD_REG_SET used; + CLEAR_HARD_REG_SET (used); + note_uses (&PATTERN (insn), record_hard_reg_uses, + &used); + if (TEST_HARD_REG_BIT (used, HARD_FRAME_POINTER_REGNUM)) + fp_def_use = true; + calls->safe_push (insn); + } + + /* fp is in DF_INSN_DEFS or DF_INSN_USES of call insn in + order not to move other normal fp def/use insn across call. + For fp setting movement, those DEFS and USES should be + neglected. */ + if (NONDEBUG_INSN_P (insn) && !CALL_P (insn)) + { + df_ref *df_rec; + for (df_rec = DF_INSN_DEFS (insn); *df_rec; df_rec++) + { + rtx reg = DF_REF_REG (*df_rec); + + if (REG_P (reg) + && REGNO (reg) == HARD_FRAME_POINTER_REGNUM) + { + fp_def_use = true; + any_fp_def = true; + } + } + + for (df_rec = DF_INSN_USES (insn); *df_rec; df_rec++) + { + rtx reg = DF_REF_REG (*df_rec); + + if (REG_P (reg) + && REGNO (reg) == HARD_FRAME_POINTER_REGNUM) + fp_def_use = true; + } + } + + if (fp_def_use) + { + /* Record place_to_move when the bottom fp reference is seen. */ + if (!place_to_move_set) + { + bb_fpsets[bb->index].place_to_move = place_to_move; + place_to_move_set = true; + } + + if (insert_before) + { + /* When fp_def_use is seen, fpset should be inserted for + the last seen call. Add the call to local_inserts. */ + local_inserts->safe_push (insert_before); + insert_before = NULL; + } + bb_fpsets[bb->index].transparent = false; + bb_fpsets[bb->index].has_fp_ref = true; + } + + /* Record the insn just below the bottom fp reference in the bb. + If there is fpset moved from other bbs, the fpset could be placed + before place_to_move. */ + if (!place_to_move_set && NONDEBUG_INSN_P (insn)) + place_to_move = insn; + + if (CALL_P (insn)) + { + /* The latest place to insert fp setting. */ + insert_before = insn; + /* No fp def or use below this call, so we have downward exposed + fpset. */ + if (!bb_fpsets[bb->index].has_fp_ref) + bb_fpsets[bb->index].has_orig_downexposed_fpset = true; + } + } + + /* If there is no fp_def_use in bb, place_to_move will be the first + insn in the bb. before place_to_move is the place to insert fpset + moved from other bbs. */ + if (!place_to_move_set) + bb_fpsets[bb->index].place_to_move = place_to_move; + + if (insert_before) + { + bb_fpsets[bb->index].has_orig_upexposed_fpset = true; + bb_fpsets[bb->index].place_for_upexposed_fpset = insert_before; + } + + /* For bb without explicit fp def/use, but it is in a fp live range, + it is impossible to move fpset to this bb or across this bb. */ + if (bitmap_bit_p (df_get_live_out (bb), HARD_FRAME_POINTER_REGNUM)) + { + bb_fpsets[bb->index].transparent = false; + bb_fpsets[bb->index].place_to_move = NULL; + } + + if (dump_file) + dump_bb_fpset (dump_file, &bb_fpsets[bb->index]); + } +} + +/* Set bb_fpsets[bb->index].can_move_to, which indicates the bb set to + which fp setting from bb could be moved. + Suppose there is a fp setting in BB1, if there is not non-transparent + BB on any path from BB2 to BB1, BB2 is the BB that the fp setting in BB1 + could be moved to. + + The dataflow equation is like this: + Initialization before dataflow iterating: + For any bb, availin[bb] = {0, 0, ...} + availin[bb] = {1, 1, ...} + Iterating: + availin[bb] = AND (availout[pred]) + availout[bb] = availloc OR (availin[bb] AND trans). + + After the iterating completes, availin[bb] contains the bitmap of the + target bbs, which the fp insns in the bb are allowed to move to. */ +static void +set_bbs_move_to () +{ + basic_block bb; + sbitmap *availin, *availout, availloc, trans; + vec worklist; + + availloc = sbitmap_alloc (last_basic_block_for_fn (cfun)); + trans = sbitmap_alloc (last_basic_block_for_fn (cfun)); + availin = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), + last_basic_block_for_fn (cfun)); + availout = sbitmap_vector_alloc (last_basic_block_for_fn (cfun), + last_basic_block_for_fn (cfun)); + bitmap_clear (trans); + bitmap_vector_clear (availin, last_basic_block_for_fn (cfun)); + bitmap_vector_clear (availout, last_basic_block_for_fn (cfun)); + worklist.create (0); + + FOR_EACH_BB_FN (bb, cfun) + { + bb->aux = bb; + worklist.safe_push (bb); + bitmap_ones (availout[bb->index]); + } + + while (!worklist.is_empty ()) + { + int bb_index; + edge_iterator ei; + edge e; + + bb = worklist.pop (); + bb_index = bb->index; + bb->aux = NULL; + bitmap_intersection_of_preds (availin[bb_index], + availout, bb); + if (!bb_fpsets[bb_index].transparent) + bitmap_clear (trans); + else + bitmap_ones (trans); + bitmap_clear (availloc); + /* If no place_to_move, it is impossible for fpsets from + other bbs to be moved to here. An example of place_to_move + being NULL is when fp is in the live out set of bb. */ + if (bb_fpsets[bb_index].place_to_move) + bitmap_set_bit (availloc, bb_index); + + if (bitmap_or_and (availout[bb_index], availloc, + availin[bb_index], trans)) + FOR_EACH_EDGE (e, ei, bb->succs) + { + if (!e->dest->aux) + { + e->dest->aux = e->dest; + worklist.safe_insert (0, e->dest); + } + } + } + + FOR_EACH_BB_FN (bb, cfun) + bitmap_copy (bb_fpsets[bb->index].can_move_to, availin[bb->index]); + + clear_aux_for_blocks (); + sbitmap_free (availloc); + sbitmap_vector_free (availin); + sbitmap_vector_free (availout); +} + +class promote_fpset_dom_walker : public dom_walker +{ +public: + promote_fpset_dom_walker (cdi_direction direction) + : dom_walker (direction) {} + virtual void after_dom_children (basic_block); +}; + +/* Try to promote fp settings from the bbs in the dominator tree + to its root if the promote_cost is less than non_promote_cost. + If fp settings move to BBi is decided, bb_fpsets[i].move_to_here + will be set to true. */ +void +promote_fpset_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED) +{ + unsigned j; + vec children; + basic_block child; + int non_promote_cost, promote_cost; + int bb_index = bb->index; + float promote_fraction; + + /* For entry bb, there is nothing to promote. */ + if (bb_index == 0) + return; + /* For leaf bb, there is nothing to promote. */ + children = get_dominated_by (CDI_DOMINATORS, bb); + if (children.is_empty ()) + return; + + if (bb_fpsets[bb_index].has_orig_downexposed_fpset + || (bb_fpsets[bb_index].has_orig_upexposed_fpset + && bb_fpsets[bb_index].transparent)) + non_promote_cost = bb->frequency * 10 + (!bb->frequency ? 1 : 0); + else + non_promote_cost = 0; + promote_cost = bb->frequency * 10 + (!bb->frequency ? 1 : 0); + + /* Compute promote_cost and non_promote_cost of all the bbs dominated + by current bb. */ + FOR_EACH_VEC_ELT (children, j, child) + { + int index = child->index; + struct bb_fpset *fpset = &bb_fpsets[index]; + + /* In the following case, fpset cannot be promoted to + bb anyway. No need to involve the child into cost + evaluation. */ + if ((!fpset->transparent && !fpset->has_orig_upexposed_fpset) + || !bitmap_bit_p (fpset->can_move_to, bb_index)) + continue; + + /* If subtree computation didn't choose to move fp setting to + its root. */ + if (!fpset->moved_to_here) + { + struct bb_fpset *subnode = fpset->next; + + /* For leaf node on dom tree, its moved_to_here is false, + but it may has_orig_upexposed_fpset. + For non-leaf node, suppose has_orig_upexposed_fpset is + true. If it is non-transparent, we only have a fpset upward + exposed. If it is transparent, moved_to_here has to be true + the program will not take this branch. */ + if (fpset->has_orig_upexposed_fpset) + { + non_promote_cost += child->frequency * 10 + + (!child->frequency ? 1 : 0); + continue; + } + + while (subnode) + { + non_promote_cost += subnode->bb->frequency * 10 + + (!subnode->bb->frequency ? 1 : 0); + subnode = subnode->next; + } + } + else + non_promote_cost += child->frequency * 10 + + (!child->frequency ? 1 : 0); + } + + /* If promote is beneficial, mark that a fp setting to be moved to + current bb, and remove upexposed fp settings or fp setting link + list from its children. + If promote will cost too much, don't move fp settings to current + bb, but connect those scattered fp setting with a link list in + the bb_fpset of current bb. + + If not-to-promote is chosen, there could be multiple fp setting + insns scattered instead of one fp setting insn merged. It means + larger code size. Introduce PARAM_FPSET_PROMOTE_FRACTION to find + a balance between performance improvement and code size increase. */ + + if (profile_status_for_fn (cfun) == PROFILE_READ) + promote_fraction = 1; + else + promote_fraction = 1 + PARAM_VALUE (PARAM_FPSET_PROMOTE_FRACTION) * 0.1; + + if ((promote_cost <= (non_promote_cost * promote_fraction) + && bb_fpsets[bb_index].place_to_move) + || bb_fpsets[bb_index].has_orig_downexposed_fpset) + { + /* move fp set to bb. */ + FOR_EACH_VEC_ELT (children, j, child) + { + int index = child->index; + struct bb_fpset *fpset = &bb_fpsets[index]; + struct bb_fpset *subnode = fpset->next; + + /* In the following case, fpsets cannot be promoted to + bb. Leave those fpsets unchanged. */ + if ((!fpset->transparent && !fpset->has_orig_upexposed_fpset) + || !bitmap_bit_p (fpset->can_move_to, bb_index)) + continue; + + while (subnode) + { + struct bb_fpset *next = subnode->next; + /* Reset the subnode. */ + subnode->next = subnode->end = NULL; + subnode->moved_to_here = false; + subnode->has_orig_upexposed_fpset = false; + subnode = next; + } + + fpset->next = fpset->end = NULL; + fpset->moved_to_here = false; + fpset->has_orig_upexposed_fpset = false; + } + + /* If bb has_orig_downexposed_fpset, there will already be a + fpset inserted by local_inserts, so don't set moved_to_here. */ + if (!bb_fpsets[bb_index].has_orig_downexposed_fpset) + bb_fpsets[bb_index].moved_to_here = true; + } + else + { + /* Connect all the link lists from children and set + bb_fpsets[bb_index].next to the head of it. */ + FOR_EACH_VEC_ELT (children, j, child) + { + int index = child->index; + struct bb_fpset *fpset = &bb_fpsets[index]; + if ((!fpset->transparent && !fpset->has_orig_upexposed_fpset) + || !bitmap_bit_p (fpset->can_move_to, bb_index)) + continue; + if ((fpset->moved_to_here && fpset->transparent) + || fpset->has_orig_upexposed_fpset) + { + /* Only the child has to be added to the bb's link list. */ + struct bb_fpset *tmp; + tmp = bb_fpsets[bb_index].next; + bb_fpsets[bb_index].next = fpset; + fpset->next = tmp; + if (!bb_fpsets[bb_index].end) + bb_fpsets[bb_index].end = fpset; + fpset->end = NULL; +#ifdef ENABLE_CHECKING + fpset_list_sanity_check (&bb_fpsets[bb_index]); +#endif + } + else if (!fpset->moved_to_here) + { + /* The link list of the child should be added to the + bb's link list. */ + + /* If fpset contains an empty link list, nothing has + to be done. */ + if (!fpset->next) + { + gcc_assert (!fpset->end); + continue; + } + fpset->end->next = bb_fpsets[bb_index].next; + bb_fpsets[bb_index].next = fpset->next; + if (!bb_fpsets[bb_index].end) + bb_fpsets[bb_index].end = fpset->end; + fpset->next = fpset->end = NULL; +#ifdef ENABLE_CHECKING + fpset_list_sanity_check (&bb_fpsets[bb_index]); +#endif + } + } + } +} + +/* Choose places to move fp settings. fp settings will be moved + to places before insns saved in GLOBAL_INSERTS. */ +static void +choose_places (vec *global_inserts) +{ + basic_block bb; + basic_block prologue_bb = single_succ (ENTRY_BLOCK_PTR_FOR_FN (cfun)); + bool prologue_bb_trans = bb_fpsets[prologue_bb->index].transparent; + fpset_needed_in_prologue = false; + + set_bbs_move_to (); + + /* Iterate dominator tree from bottom to top and try to move + fp settings upwards. */ + calculate_dominance_info (CDI_DOMINATORS); + promote_fpset_dom_walker (CDI_DOMINATORS) + .walk (cfun->cfg->x_entry_block_ptr); + free_dominance_info (CDI_DOMINATORS); + + if (dump_file) + { + fprintf(dump_file, "\nfpset dump after choose places:\n"); + FOR_EACH_BB_FN (bb, cfun) + dump_bb_fpset (dump_file, &bb_fpsets[bb->index]); + } + + calculate_dominance_info (CDI_POST_DOMINATORS); + /* Save the places to move fp setting in global_inserts vector. */ + FOR_EACH_BB_FN (bb, cfun) + { + bool postponed_to_prologue = false; + struct bb_fpset *fpset = &bb_fpsets[bb->index]; + /* If a fp setting insn needs to be inserted in a bb equivalent with + prologue bb on dominator tree, and the prologue bb is transparent, + and prologue bb is in the can_move_to set of the target bb, replace + the fp setting insn with "mov sp fp" in prologue. This is to reduce + code size. It will postpone the insertion of move fp setting insn + until prologue generation. */ + if (prologue_bb_trans + && (bb == prologue_bb + || (dominated_by_p (CDI_POST_DOMINATORS, + prologue_bb, bb) + && bitmap_bit_p (fpset->can_move_to, + prologue_bb->index)))) + postponed_to_prologue = true; + if (fpset->moved_to_here && !fpset->transparent) + { + gcc_assert (fpset->place_to_move); + global_inserts->safe_push (fpset->place_to_move); + } + else if (fpset->moved_to_here && fpset->transparent + && !fpset->has_orig_upexposed_fpset) + { + gcc_assert (fpset->place_to_move); + if (postponed_to_prologue) + fpset_needed_in_prologue |= postponed_to_prologue; + else + global_inserts->safe_push (fpset->place_to_move); + } + + if (fpset->has_orig_upexposed_fpset) + { + if (postponed_to_prologue) + fpset_needed_in_prologue |= postponed_to_prologue; + else + global_inserts->safe_push (fpset->place_for_upexposed_fpset); + } + } + free_dominance_info (CDI_POST_DOMINATORS); +} + +/* Insert frame pointer setting insns before the places specified + in LOCAL_INSERTS and GLOBAL_INSERTS. */ + +void +insert_fp_setting (vec *local_inserts, vec *global_inserts, + vec *calls) +{ + bool any_insert = false; + rtx seq_end, seq_start, dup, insert_before; + + start_sequence (); + targetm.set_fp_insn (); + seq_start = get_insns (); + seq_end = get_last_insn (); + end_sequence (); + + if (!seq_start) + return; + + while (!local_inserts->is_empty ()) + { + insert_before = local_inserts->pop (); + if (dbg_cnt (fpset_insert)) + { + start_sequence (); + duplicate_insn_chain (seq_start, seq_end); + dup = get_insns (); + end_sequence (); + emit_insn_before (dup, insert_before); + any_insert = true; + } + } + + while (!global_inserts->is_empty ()) + { + insert_before = global_inserts->pop (); + if (dbg_cnt (fpset_insert)) + { + start_sequence (); + duplicate_insn_chain (seq_start, seq_end); + dup = get_insns (); + end_sequence (); + emit_insn_before (dup, insert_before); + any_insert = true; + } + } + + /* If there is any fpsetting inserted, add fp use note in every + call. This is to avoid DCE to delete fp setting inserted here. */ + if (any_insert || fpset_needed_in_prologue) + while (!calls->is_empty ()) + { + rtx *call_fusage, call; + call = calls->pop(); + call_fusage = &CALL_INSN_FUNCTION_USAGE (call); + use_reg_mode (call_fusage, hard_frame_pointer_rtx, + GET_MODE (hard_frame_pointer_rtx)); + CALL_INSN_FUNCTION_USAGE (call) = *call_fusage; + } +} + +/* FP shrinkwrapping. + Initially it is assumed that every call needs a fp setting + immediately before it to save the caller's frame address. fp + shrinkwrapping will try to promote those fp settings from its + original bb to its dominator if it is legal and beneficial. + The promotion process is a bottom-up traversal of dominator + tree. */ + +static void +move_fp_settings () +{ + /* local_inserts save places to insert local fp settings which + could not be promoted outside its original bb. global_inserts + save places to insert the rest of fp settings. calls save call + insns for which we need to add reg use note. */ + vec local_inserts, global_inserts, calls; + + local_inserts.create(0); + global_inserts.create(0); + calls.create(0); + bb_fpsets = XNEWVEC (struct bb_fpset, last_basic_block_for_fn (cfun)); + memset (&bb_fpsets[0], 0, + sizeof (struct bb_fpset) * last_basic_block_for_fn (cfun)); + + bb_fpset_local_init (&local_inserts, &calls); + choose_places (&global_inserts); + insert_fp_setting (&local_inserts, &global_inserts, &calls); + + /* After we insert fp setting and do fp shrinkwrapping, fp will not be + invalidated by call implicitly. */ + if (frame_pointer_partially_needed) + CLEAR_HARD_REG_BIT (regs_invalidated_by_call, HARD_FRAME_POINTER_REGNUM); + + local_inserts.release (); + global_inserts.release (); + calls.release (); + free (bb_fpsets); + df_analyze (); +} /* Generate the prologue and epilogue RTL if the machine supports it. Thread this into place with notes indicating where the prologue ends and where @@ -5957,6 +6659,10 @@ thread_prologue_and_epilogue_insns (void) #endif } + /* Insert frame pointer setting insns before calls. */ + if (frame_pointer_partially_needed) + move_fp_settings (); + prologue_seq = NULL_RTX; #ifdef HAVE_prologue if (HAVE_prologue) @@ -6050,7 +6756,7 @@ thread_prologue_and_epilogue_insns (void) add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, STACK_POINTER_REGNUM); add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, ARG_POINTER_REGNUM); - if (frame_pointer_needed) + if (frame_pointer_needed || frame_pointer_partially_needed) add_to_hard_reg_set (&set_up_by_prologue.set, Pmode, HARD_FRAME_POINTER_REGNUM); if (pic_offset_table_rtx) diff --git a/gcc-4.9/gcc/function.h b/gcc-4.9/gcc/function.h index f2c348f28..ccd5e6681 100644 --- a/gcc-4.9/gcc/function.h +++ b/gcc-4.9/gcc/function.h @@ -391,6 +391,15 @@ struct GTY(()) rtl_data { on the stack there. */ bool frame_pointer_needed; + /* Nonzero if hard frame pointer reg will be used as both a caller + saved register and the register to pass frame base address from + caller to callee. */ + bool frame_pointer_partially_needed; + /* Nonzero if sp->bp mov insn is needed in prologue. */ + bool fpset_needed_in_prologue; + /* Nonzero if no fp defined in function body except prologue/epilogue. */ + bool any_fp_def; + /* When set, expand should optimize for speed. */ bool maybe_hot_insn_p; @@ -474,6 +483,9 @@ struct GTY(()) rtl_data { #define temp_slot_level (crtl->x_temp_slot_level) #define nonlocal_goto_handler_labels (crtl->x_nonlocal_goto_handler_labels) #define frame_pointer_needed (crtl->frame_pointer_needed) +#define frame_pointer_partially_needed (crtl->frame_pointer_partially_needed) +#define fpset_needed_in_prologue (crtl->fpset_needed_in_prologue) +#define any_fp_def (crtl->any_fp_def) #define stack_realign_fp (crtl->stack_realign_needed && !crtl->need_drap) #define stack_realign_drap (crtl->stack_realign_needed && crtl->need_drap) diff --git a/gcc-4.9/gcc/gcc.c b/gcc-4.9/gcc/gcc.c index 297d985f4..e187cd19c 100644 --- a/gcc-4.9/gcc/gcc.c +++ b/gcc-4.9/gcc/gcc.c @@ -576,15 +576,21 @@ proper position among the other output files. */ #ifndef LIBLSAN_SPEC #define STATIC_LIBLSAN_LIBS \ " %{static-liblsan:%:include(libsanitizer.spec)%(link_liblsan)}" -#ifdef HAVE_LD_STATIC_DYNAMIC -#define LIBLSAN_SPEC "%{!shared:%{static-liblsan:" LD_STATIC_OPTION \ +#ifdef LIBLSAN_EARLY_SPEC +#define LIBLSAN_SPEC STATIC_LIBLSAN_LIBS +#elif defined(HAVE_LD_STATIC_DYNAMIC) +#define LIBLSAN_SPEC "%{static-liblsan:" LD_STATIC_OPTION \ "} -llsan %{static-liblsan:" LD_DYNAMIC_OPTION "}" \ - STATIC_LIBLSAN_LIBS "}" + STATIC_LIBLSAN_LIBS #else -#define LIBLSAN_SPEC "%{!shared:-llsan" STATIC_LIBLSAN_LIBS "}" +#define LIBLSAN_SPEC "-llsan" STATIC_LIBLSAN_LIBS #endif #endif +#ifndef LIBLSAN_EARLY_SPEC +#define LIBLSAN_EARLY_SPEC "" +#endif + #ifndef LIBUBSAN_SPEC #define STATIC_LIBUBSAN_LIBS \ " %{static-libubsan:%:include(libsanitizer.spec)%(link_libubsan)}" @@ -672,9 +678,9 @@ proper position among the other output files. */ #ifndef LINK_PIE_SPEC #ifdef HAVE_LD_PIE -#define LINK_PIE_SPEC "%{pie:-pie} " +#define LINK_PIE_SPEC "%{pie:-pie} %{no-pie:}" #else -#define LINK_PIE_SPEC "%{pie:} " +#define LINK_PIE_SPEC "%{pie:} %{no-pie:}" #endif #endif @@ -720,15 +726,15 @@ proper position among the other output files. */ #ifndef SANITIZER_EARLY_SPEC #define SANITIZER_EARLY_SPEC "\ %{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_EARLY_SPEC "} \ - %{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "}}}" + %{%:sanitize(thread):" LIBTSAN_EARLY_SPEC "} \ + %{%:sanitize(leak):" LIBLSAN_EARLY_SPEC "}}}" #endif /* Linker command line options for -fsanitize= late on the command line. */ #ifndef SANITIZER_SPEC #define SANITIZER_SPEC "\ %{!nostdlib:%{!nodefaultlibs:%{%:sanitize(address):" LIBASAN_SPEC "\ - %{static:%ecannot specify -static with -fsanitize=address}\ - %{%:sanitize(thread):%e-fsanitize=address is incompatible with -fsanitize=thread}}\ + %{static:%ecannot specify -static with -fsanitize=address}}\ %{%:sanitize(thread):" LIBTSAN_SPEC "\ %{!pie:%{!shared:%e-fsanitize=thread linking must be done with -pie or -shared}}}\ %{%:sanitize(undefined):" LIBUBSAN_SPEC "}\ @@ -763,7 +769,7 @@ proper position among the other output files. */ -plugin %(func_reorder_linker_plugin_file) \ -plugin-opt=%(func_reorder_linker_plugin_opt)}" \ "%{flto|flto=*:% Place the output into \n"), stdout); fputs (_(" -pie Create a position independent executable\n"), stdout); + fputs (_(" -no-pie Create a position dependent executable\n"), stdout); fputs (_(" -shared Create a shared library\n"), stdout); fputs (_("\ -x Specify the language of the following input files\n\ @@ -8236,7 +8243,9 @@ sanitize_spec_function (int argc, const char **argv) return NULL; if (strcmp (argv[0], "address") == 0) - return (flag_sanitize & SANITIZE_ADDRESS) ? "" : NULL; + return (flag_sanitize & SANITIZE_USER_ADDRESS) ? "" : NULL; + if (strcmp (argv[0], "kernel-address") == 0) + return (flag_sanitize & SANITIZE_KERNEL_ADDRESS) ? "" : NULL; if (strcmp (argv[0], "thread") == 0) return (flag_sanitize & SANITIZE_THREAD) ? "" : NULL; if (strcmp (argv[0], "undefined") == 0) diff --git a/gcc-4.9/gcc/gcov-dump.c b/gcc-4.9/gcc/gcov-dump.c index 7df649466..bb1fd3378 100644 --- a/gcc-4.9/gcc/gcov-dump.c +++ b/gcc-4.9/gcc/gcov-dump.c @@ -42,6 +42,8 @@ static void tag_summary (const char *, unsigned, unsigned); static void tag_module_info (const char *, unsigned, unsigned); static void dump_working_sets (const char *filename ATTRIBUTE_UNUSED, const struct gcov_ctr_summary *summary); +static void tag_zero_fixup (const char *, unsigned, unsigned); +static void tag_build_info (const char *, unsigned, unsigned); extern int main (int, char **); typedef struct tag_format @@ -56,6 +58,9 @@ static int flag_dump_positions = 0; static int flag_dump_aux_modules_only = 0; static int flag_dump_working_sets = 0; +static unsigned num_fn_info; +static int *zero_fixup_flags = NULL; + static const struct option options[] = { { "help", no_argument, NULL, 'h' }, @@ -78,6 +83,8 @@ static const tag_format_t tag_table[] = {GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary}, {GCOV_TAG_PROGRAM_SUMMARY, "PROGRAM_SUMMARY", tag_summary}, {GCOV_TAG_MODULE_INFO, "MODULE INFO", tag_module_info}, + {GCOV_TAG_COMDAT_ZERO_FIXUP, "ZERO FIXUP", tag_zero_fixup}, + {GCOV_TAG_BUILD_INFO, "BUILD INFO", tag_build_info}, {0, NULL, NULL} }; @@ -272,6 +279,8 @@ dump_gcov_file (const char *filename) printf ("%s:stamp %lu\n", filename, (unsigned long)stamp); } + num_fn_info = 0; + while (1) { gcov_position_t base, position = gcov_position (); @@ -339,6 +348,7 @@ dump_gcov_file (const char *filename) break; } } + free (zero_fixup_flags); gcov_close (); } @@ -352,7 +362,9 @@ tag_function (const char *filename ATTRIBUTE_UNUSED, printf (" placeholder"); else { - printf (" ident=%u", gcov_read_unsigned ()); + int had_fixup = zero_fixup_flags && zero_fixup_flags[num_fn_info]; + printf (" ident=%u%s", gcov_read_unsigned (), + had_fixup ? " (Was 0-count COMDAT)" : ""); printf (", lineno_checksum=0x%08x", gcov_read_unsigned ()); printf (", cfg_checksum=0x%08x", gcov_read_unsigned ()); @@ -367,6 +379,7 @@ tag_function (const char *filename ATTRIBUTE_UNUSED, printf (":%u", gcov_read_unsigned ()); } } + num_fn_info++; } static void @@ -597,6 +610,54 @@ tag_module_info (const char *filename ATTRIBUTE_UNUSED, } } +static void +tag_zero_fixup (const char *filename, + unsigned tag ATTRIBUTE_UNUSED, unsigned length) +{ + gcov_unsigned_t num_fns = 0; + zero_fixup_flags = gcov_read_comdat_zero_fixup (length, &num_fns); + if (!zero_fixup_flags) + { + printf ("%s:error reading zero fixup flags\n", filename); + return; + } + printf (" num_fns=%u", num_fns); + for (unsigned i = 0; i < num_fns; i++) + { + if (!(i % 32)) + { + printf ("\n"); + print_prefix (filename, 0, 0); + printf ("\t\t"); + } + if (!(i % 8)) + printf ("%s%4u:", (i%32)?" ":"", i); + printf ("%u", zero_fixup_flags[i]); + } +} + +static void +tag_build_info (const char *filename, + unsigned tag ATTRIBUTE_UNUSED, unsigned length) +{ + gcov_unsigned_t num_strings = 0; + char **build_info_strings = gcov_read_build_info (length, &num_strings); + if (!build_info_strings) + { + printf ("%s:error reading build info\n", filename); + return; + } + printf (" num_strings=%u", num_strings); + for (unsigned i = 0; i < num_strings; i++) + { + printf ("\n"); + print_prefix (filename, 0, 0); + printf ("\t\t%s", build_info_strings[i]); + free (build_info_strings[i]); + } + free (build_info_strings); +} + static void dump_working_sets (const char *filename ATTRIBUTE_UNUSED, const struct gcov_ctr_summary *summary) diff --git a/gcc-4.9/gcc/gcov-io.c b/gcc-4.9/gcc/gcov-io.c index f226cbf0e..fc5e32e63 100644 --- a/gcc-4.9/gcc/gcov-io.c +++ b/gcc-4.9/gcc/gcov-io.c @@ -41,7 +41,7 @@ static void gcov_allocate (unsigned); GCOV_LINKAGE struct gcov_var { - FILE *file; + _GCOV_FILE *file; gcov_position_t start; /* Position of first byte of block */ unsigned offset; /* Read/write position within the block. */ unsigned length; /* Read limit in the block. */ @@ -94,7 +94,7 @@ gcov_rewrite (void) gcov_var.mode = -1; gcov_var.start = 0; gcov_var.offset = 0; - fseek (gcov_var.file, 0L, SEEK_SET); + _GCOV_fseek (gcov_var.file, 0L, SEEK_SET); } #endif @@ -120,6 +120,7 @@ static inline gcov_unsigned_t from_file (gcov_unsigned_t value) Return zero on failure, >0 on opening an existing file and <0 on creating a new one. */ +#ifndef __KERNEL__ GCOV_LINKAGE int #if IN_LIBGCOV gcov_open (const char *name) @@ -190,7 +191,7 @@ gcov_open (const char *name, int mode) if (fstat (fd, &st) < 0) { - fclose (gcov_var.file); + _GCOV_fclose (gcov_var.file); gcov_var.file = 0; return 0; } @@ -203,13 +204,13 @@ gcov_open (const char *name, int mode) gcov_var.mode = mode * 2 + 1; #else if (mode >= 0) - gcov_var.file = fopen (name, (mode > 0) ? "rb" : "r+b"); + gcov_var.file = _GCOV_fopen (name, (mode > 0) ? "rb" : "r+b"); if (gcov_var.file) gcov_var.mode = 1; else if (mode <= 0) { - gcov_var.file = fopen (name, "w+b"); + gcov_var.file = _GCOV_fopen (name, "w+b"); if (gcov_var.file) gcov_var.mode = mode * 2 + 1; } @@ -221,6 +222,24 @@ gcov_open (const char *name, int mode) return 1; } +#else /* __KERNEL__ */ + +extern _GCOV_FILE *gcov_current_file; + +GCOV_LINKAGE int +gcov_open (const char *name) +{ + gcov_var.start = 0; + gcov_var.offset = gcov_var.length = 0; + gcov_var.overread = -1u; + gcov_var.error = 0; + gcov_var.file = gcov_current_file; + gcov_var.mode = 1; + + return 1; +} +#endif /* __KERNEL__ */ + /* Close the current gcov file. Flushes data to disk. Returns nonzero on failure or error flag set. */ @@ -234,7 +253,7 @@ gcov_close (void) if (gcov_var.offset && gcov_var.mode < 0) gcov_write_block (gcov_var.offset); #endif - fclose (gcov_var.file); + _GCOV_fclose (gcov_var.file); gcov_var.file = 0; gcov_var.length = 0; } @@ -290,7 +309,7 @@ gcov_allocate (unsigned length) static void gcov_write_block (unsigned size) { - if (fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1) + if (_GCOV_fwrite (gcov_var.buffer, size << 2, 1, gcov_var.file) != 1) gcov_var.error = 1; gcov_var.start += size; gcov_var.offset -= size; @@ -336,6 +355,47 @@ gcov_write_unsigned (gcov_unsigned_t value) buffer[0] = value; } +/* Compute the total length in words required to write NUM_STRINGS + in STRING_ARRAY as unsigned. */ + +GCOV_LINKAGE gcov_unsigned_t +gcov_compute_string_array_len (char **string_array, + gcov_unsigned_t num_strings) +{ + gcov_unsigned_t len = 0, i; + for (i = 0; i < num_strings; i++) + { + gcov_unsigned_t string_len + = (strlen (string_array[i]) + sizeof (gcov_unsigned_t)) + / sizeof (gcov_unsigned_t); + len += string_len; + len += 1; /* Each string is lead by a length. */ + } + return len; +} + +/* Write NUM_STRINGS in STRING_ARRAY as unsigned. */ + +GCOV_LINKAGE void +gcov_write_string_array (char **string_array, gcov_unsigned_t num_strings) +{ + gcov_unsigned_t i, j; + for (j = 0; j < num_strings; j++) + { + gcov_unsigned_t *aligned_string; + gcov_unsigned_t string_len = + (strlen (string_array[j]) + sizeof (gcov_unsigned_t)) / + sizeof (gcov_unsigned_t); + aligned_string = (gcov_unsigned_t *) + alloca ((string_len + 1) * sizeof (gcov_unsigned_t)); + memset (aligned_string, 0, (string_len + 1) * sizeof (gcov_unsigned_t)); + aligned_string[0] = string_len; + strcpy ((char*) (aligned_string + 1), string_array[j]); + for (i = 0; i < (string_len + 1); i++) + gcov_write_unsigned (aligned_string[i]); + } +} + /* Write counter VALUE to coverage file. Sets error flag appropriately. */ @@ -517,7 +577,7 @@ gcov_read_words (unsigned words) gcov_allocate (gcov_var.length + words); excess = gcov_var.alloc - gcov_var.length; #endif - excess = fread (gcov_var.buffer + gcov_var.length, + excess = _GCOV_fread (gcov_var.buffer + gcov_var.length, 1, excess << 2, gcov_var.file) >> 2; gcov_var.length += excess; if (gcov_var.length < words) @@ -586,6 +646,20 @@ gcov_read_string (void) } #endif +#ifdef __KERNEL__ +static int +k_popcountll (long long x) +{ + int c = 0; + while (x) + { + c++; + x &= (x-1); + } + return c; +} +#endif + GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *summary) { @@ -612,7 +686,11 @@ gcov_read_summary (struct gcov_summary *summary) hwint.h (where popcount_hwi is declared). However, libgcov.a is built by the bootstrapped compiler and therefore the builtins are always available. */ +#ifndef __KERNEL__ h_cnt += __builtin_popcount (histo_bitvector[bv_ix]); +#else + h_cnt += k_popcountll (histo_bitvector[bv_ix]); +#endif #else h_cnt += popcount_hwi (histo_bitvector[bv_ix]); #endif @@ -650,6 +728,78 @@ gcov_read_summary (struct gcov_summary *summary) } } +/* Read LENGTH words (unsigned type) from a zero profile fixup record with the + number of function flags saved in NUM_FNS. Returns the int flag array, which + should be deallocated by caller, or NULL on error. */ + +GCOV_LINKAGE int * +gcov_read_comdat_zero_fixup (gcov_unsigned_t length, + gcov_unsigned_t *num_fns) +{ +#ifndef __KERNEL__ + unsigned ix, f_ix; + gcov_unsigned_t num = gcov_read_unsigned (); + /* The length consists of 1 word to hold the number of functions, + plus enough 32-bit words to hold 1 bit/function. */ + gcc_assert ((num + 31) / 32 + 1 == length); + int *zero_fixup_flags = (int *) xcalloc (num, sizeof (int)); + for (ix = 0; ix < length - 1; ix++) + { + gcov_unsigned_t bitvector = gcov_read_unsigned (); + f_ix = ix * 32; + while (bitvector) + { + if (bitvector & 0x1) + zero_fixup_flags[f_ix] = 1; + f_ix++; + bitvector >>= 1; + } + } + *num_fns = num; + return zero_fixup_flags; +#else + return NULL; +#endif +} + +/* Read NUM_STRINGS strings (as an unsigned array) in STRING_ARRAY, and return + the number of words read. */ + +GCOV_LINKAGE gcov_unsigned_t +gcov_read_string_array (char **string_array, gcov_unsigned_t num_strings) +{ + gcov_unsigned_t i, j, len = 0; + + for (j = 0; j < num_strings; j++) + { + gcov_unsigned_t string_len = gcov_read_unsigned (); + string_array[j] = + (char *) xmalloc (string_len * sizeof (gcov_unsigned_t)); + for (i = 0; i < string_len; i++) + ((gcov_unsigned_t *) string_array[j])[i] = gcov_read_unsigned (); + len += (string_len + 1); + } + return len; +} + +/* Read LENGTH words (unsigned type) from a build info record with the number + of strings read saved in NUM_STRINGS. Returns the string array, which + should be deallocated by caller, or NULL on error. */ + +GCOV_LINKAGE char ** +gcov_read_build_info (gcov_unsigned_t length, gcov_unsigned_t *num_strings) +{ + gcov_unsigned_t num = gcov_read_unsigned (); + char **build_info_strings = (char **) + xmalloc (sizeof (char *) * num); + gcov_unsigned_t len = gcov_read_string_array (build_info_strings, + num); + if (len != length - 1) + return NULL; + *num_strings = num; + return build_info_strings; +} + #if (!IN_LIBGCOV && IN_GCOV != 1) || defined (IN_GCOV_TOOL) /* Read LEN words (unsigned type) and construct MOD_INFO. */ @@ -657,7 +807,7 @@ GCOV_LINKAGE void gcov_read_module_info (struct gcov_module_info *mod_info, gcov_unsigned_t len) { - gcov_unsigned_t src_filename_len, filename_len, i, j, num_strings; + gcov_unsigned_t src_filename_len, filename_len, i, num_strings; mod_info->ident = gcov_read_unsigned (); mod_info->is_primary = gcov_read_unsigned (); mod_info->flags = gcov_read_unsigned (); @@ -689,16 +839,7 @@ gcov_read_module_info (struct gcov_module_info *mod_info, + mod_info->num_system_paths + mod_info->num_cpp_defines + mod_info->num_cpp_includes + mod_info->num_cl_args; - for (j = 0; j < num_strings; j++) - { - gcov_unsigned_t string_len = gcov_read_unsigned (); - mod_info->string_array[j] = - (char *) xmalloc (string_len * sizeof (gcov_unsigned_t)); - for (i = 0; i < string_len; i++) - ((gcov_unsigned_t *) mod_info->string_array[j])[i] = - gcov_read_unsigned (); - len -= (string_len + 1); - } + len -= gcov_read_string_array (mod_info->string_array, num_strings); gcc_assert (!len); } #endif @@ -719,8 +860,8 @@ gcov_sync (gcov_position_t base, gcov_unsigned_t length) else { gcov_var.offset = gcov_var.length = 0; - fseek (gcov_var.file, base << 2, SEEK_SET); - gcov_var.start = ftell (gcov_var.file) >> 2; + _GCOV_fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = _GCOV_ftell (gcov_var.file) >> 2; } } #endif @@ -734,8 +875,8 @@ gcov_seek (gcov_position_t base) gcc_assert (gcov_var.mode < 0); if (gcov_var.offset) gcov_write_block (gcov_var.offset); - fseek (gcov_var.file, base << 2, SEEK_SET); - gcov_var.start = ftell (gcov_var.file) >> 2; + _GCOV_fseek (gcov_var.file, base << 2, SEEK_SET); + gcov_var.start = _GCOV_ftell (gcov_var.file) >> 2; } /* Truncate the gcov file at the current position. */ @@ -743,15 +884,19 @@ gcov_seek (gcov_position_t base) GCOV_LINKAGE void gcov_truncate (void) { +#ifdef __KERNEL__ + gcc_assert (0); +#else long offs; int filenum; gcc_assert (gcov_var.mode < 0); if (gcov_var.offset) gcov_write_block (gcov_var.offset); - offs = ftell (gcov_var.file); + offs = _GCOV_ftell (gcov_var.file); filenum = fileno (gcov_var.file); - if (offs == -1 || filenum == -1 || ftruncate (filenum, offs)) + if (offs == -1 || filenum == -1 || _GCOV_ftruncate (filenum, offs)) gcov_var.error = 1; +#endif /* __KERNEL__ */ } #endif diff --git a/gcc-4.9/gcc/gcov-io.h b/gcc-4.9/gcc/gcov-io.h index 50ffa557a..e67bce4ea 100644 --- a/gcc-4.9/gcc/gcov-io.h +++ b/gcc-4.9/gcc/gcov-io.h @@ -129,7 +129,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see blocks they are for. The data file contains the following records. - data: {unit summary:object summary:program* function-data*}* + data: {unit summary:program* build_info zero_fixup function-data*}* unit: header int32:checksum function-data: announce_function present counts announce_function: header int32:ident @@ -141,6 +141,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see int64:max int64:sum_max histogram histogram: {int32:bitvector}8 histogram-buckets* histogram-buckets: int32:num int64:min int64:sum + build_info: string:info* + zero_fixup: int32:num int32:bitvector* The ANNOUNCE_FUNCTION record is the same as that in the note file, but without the source location. The COUNTS gives the @@ -152,6 +154,17 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see zero. Note that the data file might contain information from several runs concatenated, or the data might be merged. + BUILD_INFO record contains a list of strings that is used + to include in the data file information about the profile generate + build. For example, it can be used to include source revision + information that is useful in diagnosing profile mis-matches. + + ZERO_FIXUP record contains a count of functions in the gcda file + and an array of bitvectors indexed by the function index's in the + function-data section. Each bit flags whether the function was a + COMDAT that had all-zero profiles that was fixed up by dyn-ipa + using profiles from functions with matching checksums in other modules. + This file is included by both the compiler, gcov tools and the runtime support library libgcov. IN_LIBGCOV and IN_GCOV are used to distinguish which case is which. If IN_LIBGCOV is nonzero, @@ -164,6 +177,18 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #ifndef GCC_GCOV_IO_H #define GCC_GCOV_IO_H +#ifndef __KERNEL__ +# define _GCOV_FILE FILE +# define _GCOV_fclose fclose +# define _GCOV_ftell ftell +# define _GCOV_fseek fseek +# define _GCOV_ftruncate ftruncate +# define _GCOV_fread fread +# define _GCOV_fwrite fwrite +# define _GCOV_fread fread +# define _GCOV_fileno fileno +#endif + #ifndef IN_LIBGCOV /* About the host */ @@ -255,8 +280,12 @@ typedef unsigned HOST_WIDEST_INT gcov_type_unsigned; #define GCOV_TAG_COUNTER_NUM(LENGTH) ((LENGTH) / 2) #define GCOV_TAG_OBJECT_SUMMARY ((gcov_unsigned_t)0xa1000000) /* Obsolete */ #define GCOV_TAG_PROGRAM_SUMMARY ((gcov_unsigned_t)0xa3000000) +#define GCOV_TAG_COMDAT_ZERO_FIXUP ((gcov_unsigned_t)0xa9000000) +/* Ceiling divide by 32 bit word size, plus one word to hold NUM. */ +#define GCOV_TAG_COMDAT_ZERO_FIXUP_LENGTH(NUM) (1 + (NUM + 31) / 32) #define GCOV_TAG_SUMMARY_LENGTH(NUM) \ (1 + GCOV_COUNTERS_SUMMABLE * (10 + 3 * 2) + (NUM) * 5) +#define GCOV_TAG_BUILD_INFO ((gcov_unsigned_t)0xa7000000) #define GCOV_TAG_MODULE_INFO ((gcov_unsigned_t)0xab000000) #define GCOV_TAG_AFDO_FILE_NAMES ((gcov_unsigned_t)0xaa000000) #define GCOV_TAG_AFDO_FUNCTION ((gcov_unsigned_t)0xac000000) @@ -434,9 +463,16 @@ GCOV_LINKAGE int gcov_close (void) ATTRIBUTE_HIDDEN; GCOV_LINKAGE gcov_unsigned_t gcov_read_unsigned (void) ATTRIBUTE_HIDDEN; GCOV_LINKAGE gcov_type gcov_read_counter (void) ATTRIBUTE_HIDDEN; GCOV_LINKAGE void gcov_read_summary (struct gcov_summary *) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE int *gcov_read_comdat_zero_fixup (gcov_unsigned_t, + gcov_unsigned_t *) + ATTRIBUTE_HIDDEN; +GCOV_LINKAGE char **gcov_read_build_info (gcov_unsigned_t, gcov_unsigned_t *) + ATTRIBUTE_HIDDEN; GCOV_LINKAGE const char *gcov_read_string (void); GCOV_LINKAGE void gcov_sync (gcov_position_t /*base*/, gcov_unsigned_t /*length */); +GCOV_LINKAGE gcov_unsigned_t gcov_read_string_array (char **, gcov_unsigned_t) + ATTRIBUTE_HIDDEN; #if !IN_LIBGCOV && IN_GCOV != 1 @@ -447,6 +483,11 @@ GCOV_LINKAGE void gcov_read_module_info (struct gcov_module_info *mod_info, #if !IN_GCOV /* Available outside gcov */ GCOV_LINKAGE void gcov_write_unsigned (gcov_unsigned_t) ATTRIBUTE_HIDDEN; +GCOV_LINKAGE gcov_unsigned_t gcov_compute_string_array_len (char **, + gcov_unsigned_t) + ATTRIBUTE_HIDDEN; +GCOV_LINKAGE void gcov_write_string_array (char **, gcov_unsigned_t) + ATTRIBUTE_HIDDEN; #endif #if !IN_GCOV && !IN_LIBGCOV diff --git a/gcc-4.9/gcc/gcov-tool.c b/gcc-4.9/gcc/gcov-tool.c index 37d15620d..df2e6b252 100644 --- a/gcc-4.9/gcc/gcov-tool.c +++ b/gcc-4.9/gcc/gcov-tool.c @@ -44,6 +44,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see #include extern int gcov_profile_merge (struct gcov_info*, struct gcov_info*, int, int); +extern int gcov_profile_overlap (struct gcov_info*, struct gcov_info*); extern int gcov_profile_normalize (struct gcov_info*, gcov_type); extern int gcov_profile_scale (struct gcov_info*, float, int, int); extern struct gcov_info* gcov_read_profile_dir (const char*, int); @@ -611,6 +612,121 @@ do_rewrite (int argc, char **argv) return ret; } +/* Driver function to computer the overlap score b/w profile D1 and D2. + Return 1 on error and 0 if OK. */ + +static int +profile_overlap (const char *d1, const char *d2) +{ + struct gcov_info *d1_profile; + struct gcov_info *d2_profile; + + d1_profile = gcov_read_profile_dir (d1, 0); + if (!d1_profile) + return 1; + + if (d2) + { + d2_profile = gcov_read_profile_dir (d2, 0); + if (!d2_profile) + return 1; + + return gcov_profile_overlap (d1_profile, d2_profile); + } + + return 1; +} + +/* Usage message for profile overlap. */ + +static void +print_overlap_usage_message (int error_p) +{ + FILE *file = error_p ? stderr : stdout; + + fnotice (file, " overlap [options] Compute the overlap of two profiles\n"); + fnotice (file, " -v, --verbose Verbose mode\n"); + fnotice (file, " -h, --hotonly Only print info for hot objects/functions\n"); + fnotice (file, " -f, --function Print function level info\n"); + fnotice (file, " -F, --fullname Print full filename\n"); + fnotice (file, " -o, --object Print object level info\n"); + fnotice (file, " -t , --hot_threshold Set the threshold for hotness\n"); + +} + +static const struct option overlap_options[] = +{ + { "verbose", no_argument, NULL, 'v' }, + { "function", no_argument, NULL, 'f' }, + { "fullname", no_argument, NULL, 'F' }, + { "object", no_argument, NULL, 'o' }, + { "hotonly", no_argument, NULL, 'h' }, + { "hot_threshold", required_argument, NULL, 't' }, + { 0, 0, 0, 0 } +}; + +/* Print overlap usage and exit. */ + +static void +overlap_usage (void) +{ + fnotice (stderr, "Overlap subcomand usage:"); + print_overlap_usage_message (true); + exit (FATAL_EXIT_CODE); +} + +int overlap_func_level; +int overlap_obj_level; +int overlap_hot_only; +int overlap_use_fullname; +double overlap_hot_threshold = 0.005; + +/* Driver for profile overlap sub-command. */ + +static int +do_overlap (int argc, char **argv) +{ + int opt; + int ret; + + optind = 0; + while ((opt = getopt_long (argc, argv, "vfFoht:", overlap_options, NULL)) != -1) + { + switch (opt) + { + case 'v': + verbose = true; + gcov_set_verbose (); + break; + case 'f': + overlap_func_level = 1; + break; + case 'F': + overlap_use_fullname = 1; + break; + case 'o': + overlap_obj_level = 1; + break; + case 'h': + overlap_hot_only = 1; + break; + case 't': + overlap_hot_threshold = atof (optarg); + break; + default: + overlap_usage (); + } + } + + if (argc - optind == 2) + ret = profile_overlap (argv[optind], argv[optind+1]); + else + overlap_usage (); + + return ret; +} + + /* Print a usage message and exit. If ERROR_P is nonzero, this is an error, otherwise the output of --help. */ @@ -637,6 +753,7 @@ print_usage (int error_p) fnotice (file, "\n"); print_merge_usage_message (error_p); print_rewrite_usage_message (error_p); + print_overlap_usage_message (error_p); fnotice (file, "\nFor bug reporting instructions, please see:\n%s.\n", bug_report_url); exit (status); @@ -682,7 +799,7 @@ process_args (int argc, char **argv) int opt; int ret; - while ((opt = getopt_long (argc, argv, "+hvA:EWC:M:R:S:DP", options, NULL)) != -1) + while ((opt = getopt_long (argc, argv, "+hvA:EWC:M:R:S:DPF:", options, NULL)) != -1) { switch (opt) { @@ -773,7 +890,7 @@ set_lipo_default_params (void) __gcov_lipo_merge_modu_edges = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_MERGE_MODU_EDGES); __gcov_lipo_weak_inclusion = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_WEAK_INCLUSION); __gcov_lipo_max_mem = GET_DEFAULT_PARAM_VALUE (PARAM_MAX_LIPO_MEMORY); - __gcov_lipo_comdat_algorithm = 0 /* GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_COMDAT_ALGORITHM)*/; + __gcov_lipo_comdat_algorithm = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_COMDAT_ALGORITHM); __gcov_lipo_random_group_size = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_RANDOM_GROUP_SIZE); __gcov_lipo_cutoff = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_CUTOFF); __gcov_lipo_random_seed = GET_DEFAULT_PARAM_VALUE (PARAM_LIPO_RANDOM_SEED); @@ -821,6 +938,8 @@ main (int argc, char **argv) return do_merge (argc - optind, argv + optind); else if (!strcmp (sub_command, "rewrite")) return do_rewrite (argc - optind, argv + optind); + else if (!strcmp (sub_command, "overlap")) + return do_overlap (argc - optind, argv + optind); print_usage (true); } diff --git a/gcc-4.9/gcc/gcov.c b/gcc-4.9/gcc/gcov.c index 07c2f3706..52016d3b4 100644 --- a/gcc-4.9/gcc/gcov.c +++ b/gcc-4.9/gcc/gcov.c @@ -1432,6 +1432,21 @@ read_count_file (function_t *fns) object_runs += summary.ctrs[GCOV_COUNTER_ARCS].runs; program_count++; } + else if (tag == GCOV_TAG_BUILD_INFO) + { + gcov_unsigned_t num_strings; + char **build_info_strings = gcov_read_build_info (length, + &num_strings); + for (unsigned i = 0; i < num_strings; i++) + free (build_info_strings[i]); + free (build_info_strings); + } + else if (tag == GCOV_TAG_COMDAT_ZERO_FIXUP) + { + gcov_unsigned_t num_fn; + int *zero_fixup_flags = gcov_read_comdat_zero_fixup (length, &num_fn); + free (zero_fixup_flags); + } else if (tag == GCOV_TAG_FUNCTION && !length) ; /* placeholder */ else if (tag == GCOV_TAG_FUNCTION && length == GCOV_TAG_FUNCTION_LENGTH) diff --git a/gcc-4.9/gcc/gimple-fold.c b/gcc-4.9/gcc/gimple-fold.c index ab38bde7c..35feeccad 100644 --- a/gcc-4.9/gcc/gimple-fold.c +++ b/gcc-4.9/gcc/gimple-fold.c @@ -148,7 +148,8 @@ can_refer_decl_in_current_unit_p (tree decl, tree from_decl) The second is important when devirtualization happens during final compilation stage when making a new reference no longer makes callee to be compiled. */ - if (!node || !node->definition || node->global.inlined_to) + if (!node || !node->definition + || DECL_EXTERNAL (decl) || node->global.inlined_to) { gcc_checking_assert (!TREE_ASM_WRITTEN (decl)); return false; diff --git a/gcc-4.9/gcc/gimple.c b/gcc-4.9/gcc/gimple.c index d48134647..b55d7c4e3 100644 --- a/gcc-4.9/gcc/gimple.c +++ b/gcc-4.9/gcc/gimple.c @@ -1330,11 +1330,14 @@ gimple_call_flags (const_gimple stmt) /* Return the "fn spec" string for call STMT. */ -static tree +static const_tree gimple_call_fnspec (const_gimple stmt) { tree type, attr; + if (gimple_call_internal_p (stmt)) + return internal_fn_fnspec (gimple_call_internal_fn (stmt)); + type = gimple_call_fntype (stmt); if (!type) return NULL_TREE; @@ -1351,7 +1354,7 @@ gimple_call_fnspec (const_gimple stmt) int gimple_call_arg_flags (const_gimple stmt, unsigned arg) { - tree attr = gimple_call_fnspec (stmt); + const_tree attr = gimple_call_fnspec (stmt); if (!attr || 1 + arg >= (unsigned) TREE_STRING_LENGTH (attr)) return 0; @@ -1385,7 +1388,7 @@ gimple_call_arg_flags (const_gimple stmt, unsigned arg) int gimple_call_return_flags (const_gimple stmt) { - tree attr; + const_tree attr; if (gimple_call_flags (stmt) & ECF_MALLOC) return ERF_NOALIAS; diff --git a/gcc-4.9/gcc/go/ChangeLog b/gcc-4.9/gcc/go/ChangeLog index 1af11e486..cb51027f3 100644 --- a/gcc-4.9/gcc/go/ChangeLog +++ b/gcc-4.9/gcc/go/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-16 Release Manager * GCC 4.9.1 released. diff --git a/gcc-4.9/gcc/go/gofrontend/expressions.cc b/gcc-4.9/gcc/go/gofrontend/expressions.cc index f45b4a227..b0b8e39e9 100644 --- a/gcc-4.9/gcc/go/gofrontend/expressions.cc +++ b/gcc-4.9/gcc/go/gofrontend/expressions.cc @@ -5341,10 +5341,13 @@ Binary_expression::do_lower(Gogo* gogo, Named_object*, // Lower struct, array, and some interface comparisons. if (op == OPERATOR_EQEQ || op == OPERATOR_NOTEQ) { - if (left->type()->struct_type() != NULL) + if (left->type()->struct_type() != NULL + && right->type()->struct_type() != NULL) return this->lower_struct_comparison(gogo, inserter); else if (left->type()->array_type() != NULL - && !left->type()->is_slice_type()) + && !left->type()->is_slice_type() + && right->type()->array_type() != NULL + && !right->type()->is_slice_type()) return this->lower_array_comparison(gogo, inserter); else if ((left->type()->interface_type() != NULL && right->type()->interface_type() == NULL) diff --git a/gcc-4.9/gcc/go/gofrontend/gogo.cc b/gcc-4.9/gcc/go/gofrontend/gogo.cc index 9739f289f..f042f64d4 100644 --- a/gcc-4.9/gcc/go/gofrontend/gogo.cc +++ b/gcc-4.9/gcc/go/gofrontend/gogo.cc @@ -255,10 +255,7 @@ Gogo::pkgpath_for_symbol(const std::string& pkgpath) char c = s[i]; if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') - || (c >= '0' && c <= '9') - || c == '_' - || c == '.' - || c == '$') + || (c >= '0' && c <= '9')) ; else s[i] = '_'; diff --git a/gcc-4.9/gcc/go/gofrontend/import-archive.cc b/gcc-4.9/gcc/go/gofrontend/import-archive.cc index 34fb528ab..a902cfaaf 100644 --- a/gcc-4.9/gcc/go/gofrontend/import-archive.cc +++ b/gcc-4.9/gcc/go/gofrontend/import-archive.cc @@ -295,6 +295,15 @@ Archive_file::interpret_header(const Archive_header* hdr, off_t off, // This is the symbol table. pname->clear(); } + else if (hdr->ar_name[1] == 'S' && hdr->ar_name[2] == 'Y' + && hdr->ar_name[3] == 'M' && hdr->ar_name[4] == '6' + && hdr->ar_name[5] == '4' && hdr->ar_name[6] == '/' + && hdr->ar_name[7] == ' ' + ) + { + // 64-bit symbol table. + pname->clear(); + } else if (hdr->ar_name[1] == '/') { // This is the extended name table. diff --git a/gcc-4.9/gcc/graphite-clast-to-gimple.c b/gcc-4.9/gcc/graphite-clast-to-gimple.c index fc60845d8..134388c14 100644 --- a/gcc-4.9/gcc/graphite-clast-to-gimple.c +++ b/gcc-4.9/gcc/graphite-clast-to-gimple.c @@ -30,6 +30,11 @@ along with GCC; see the file COPYING3. If not see #include #include #include +#ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE +#include +#include +#include +#endif #endif #include "system.h" diff --git a/gcc-4.9/gcc/graphite-interchange.c b/gcc-4.9/gcc/graphite-interchange.c index 55e3fab89..2e625c127 100644 --- a/gcc-4.9/gcc/graphite-interchange.c +++ b/gcc-4.9/gcc/graphite-interchange.c @@ -31,6 +31,12 @@ along with GCC; see the file COPYING3. If not see #include #include #include +#ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE +#include +#include +#include +#include +#endif #endif #include "system.h" diff --git a/gcc-4.9/gcc/graphite-optimize-isl.c b/gcc-4.9/gcc/graphite-optimize-isl.c index 88d6d6cc2..fc12eebbf 100644 --- a/gcc-4.9/gcc/graphite-optimize-isl.c +++ b/gcc-4.9/gcc/graphite-optimize-isl.c @@ -28,6 +28,10 @@ along with GCC; see the file COPYING3. If not see #include #include #include +#ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE +#include +#include +#endif #endif #include "system.h" @@ -373,7 +377,11 @@ getScheduleForBandList (isl_band_list *BandList) { for (i = ScheduleDimensions - 1 ; i >= 0 ; i--) { +#ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE + if (isl_band_member_is_coincident (Band, i)) +#else if (isl_band_member_is_zero_distance (Band, i)) +#endif { isl_map *TileMap; isl_union_map *TileUMap; diff --git a/gcc-4.9/gcc/graphite-poly.c b/gcc-4.9/gcc/graphite-poly.c index 4ca62f9af..fccc2ec6d 100644 --- a/gcc-4.9/gcc/graphite-poly.c +++ b/gcc-4.9/gcc/graphite-poly.c @@ -30,6 +30,10 @@ along with GCC; see the file COPYING3. If not see #include #include #include +#ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE +#include +#include +#endif #endif #include "system.h" diff --git a/gcc-4.9/gcc/graphite-sese-to-poly.c b/gcc-4.9/gcc/graphite-sese-to-poly.c index 28447e4b6..059c10dbb 100644 --- a/gcc-4.9/gcc/graphite-sese-to-poly.c +++ b/gcc-4.9/gcc/graphite-sese-to-poly.c @@ -29,6 +29,11 @@ along with GCC; see the file COPYING3. If not see #include #include #include +#ifdef HAVE_ISL_SCHED_CONSTRAINTS_COMPUTE_SCHEDULE +#include +#include +#include +#endif #endif #include "system.h" diff --git a/gcc-4.9/gcc/haifa-sched.c b/gcc-4.9/gcc/haifa-sched.c index 653cb8272..e437e0a42 100644 --- a/gcc-4.9/gcc/haifa-sched.c +++ b/gcc-4.9/gcc/haifa-sched.c @@ -6368,7 +6368,7 @@ schedule_block (basic_block *target_bb, state_t init_state) if (ls.modulo_epilogue) success = true; end_schedule: - if (!ls.first_cycle_insn_p) + if (!ls.first_cycle_insn_p || advance) advance_one_cycle (); perform_replacements_new_cycle (); if (modulo_ii > 0) diff --git a/gcc-4.9/gcc/ifcvt.c b/gcc-4.9/gcc/ifcvt.c index 49ff85c7f..2097de682 100644 --- a/gcc-4.9/gcc/ifcvt.c +++ b/gcc-4.9/gcc/ifcvt.c @@ -4337,6 +4337,9 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb, old_dest = JUMP_LABEL (jump); if (other_bb != new_dest) { + if (!any_condjump_p (jump)) + goto cancel; + if (JUMP_P (BB_END (dest_edge->src))) new_dest_label = JUMP_LABEL (BB_END (dest_edge->src)); else if (new_dest == EXIT_BLOCK_PTR_FOR_FN (cfun)) @@ -4387,17 +4390,14 @@ dead_or_predicable (basic_block test_bb, basic_block merge_bb, insn = head; do { - rtx note, set; + rtx note; if (! INSN_P (insn)) continue; note = find_reg_note (insn, REG_EQUAL, NULL_RTX); if (! note) continue; - set = single_set (insn); - if (!set || !function_invariant_p (SET_SRC (set)) - || !function_invariant_p (XEXP (note, 0))) - remove_note (insn, note); + remove_note (insn, note); } while (insn != end && (insn = NEXT_INSN (insn))); /* PR46315: when moving insns above a conditional branch, the REG_EQUAL diff --git a/gcc-4.9/gcc/internal-fn.c b/gcc-4.9/gcc/internal-fn.c index 1062ea847..d64e20da6 100644 --- a/gcc-4.9/gcc/internal-fn.c +++ b/gcc-4.9/gcc/internal-fn.c @@ -40,7 +40,7 @@ along with GCC; see the file COPYING3. If not see /* The names of each internal function, indexed by function number. */ const char *const internal_fn_name_array[] = { -#define DEF_INTERNAL_FN(CODE, FLAGS) #CODE, +#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) #CODE, #include "internal-fn.def" #undef DEF_INTERNAL_FN "" @@ -48,12 +48,26 @@ const char *const internal_fn_name_array[] = { /* The ECF_* flags of each internal function, indexed by function number. */ const int internal_fn_flags_array[] = { -#define DEF_INTERNAL_FN(CODE, FLAGS) FLAGS, +#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) FLAGS, #include "internal-fn.def" #undef DEF_INTERNAL_FN 0 }; +/* Fnspec of each internal function, indexed by function number. */ +const_tree internal_fn_fnspec_array[IFN_LAST + 1]; + +void +init_internal_fns () +{ +#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) \ + if (FNSPEC) internal_fn_fnspec_array[IFN_##CODE] = \ + build_string ((int) sizeof (FNSPEC), FNSPEC ? FNSPEC : ""); +#include "internal-fn.def" +#undef DEF_INTERNAL_FN + internal_fn_fnspec_array[IFN_LAST] = 0; +} + /* ARRAY_TYPE is an array of vector modes. Return the associated insn for load-lanes-style optab OPTAB. The insn must exist. */ @@ -159,6 +173,14 @@ expand_UBSAN_NULL (gimple stmt ATTRIBUTE_UNUSED) gcc_unreachable (); } +/* This should get expanded in the sanopt pass. */ + +static void +expand_ASAN_CHECK (gimple stmt ATTRIBUTE_UNUSED) +{ + gcc_unreachable (); +} + /* Add sub/add overflow checking to the statement STMT. CODE says whether the operation is +, or -. */ @@ -891,7 +913,7 @@ expand_BUILTIN_EXPECT (gimple stmt) where STMT is the statement that performs the call. */ static void (*const internal_fn_expanders[]) (gimple) = { -#define DEF_INTERNAL_FN(CODE, FLAGS) expand_##CODE, +#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) expand_##CODE, #include "internal-fn.def" #undef DEF_INTERNAL_FN 0 diff --git a/gcc-4.9/gcc/internal-fn.def b/gcc-4.9/gcc/internal-fn.def index 31dc4c9ca..2156e24ec 100644 --- a/gcc-4.9/gcc/internal-fn.def +++ b/gcc-4.9/gcc/internal-fn.def @@ -28,28 +28,30 @@ along with GCC; see the file COPYING3. If not see Each entry in this file has the form: - DEF_INTERNAL_FN (NAME, FLAGS) + DEF_INTERNAL_FN (NAME, FLAGS, FNSPEC) - where NAME is the name of the function and FLAGS is a set of - ECF_* flags. Each entry must have a corresponding expander - of the form: + where NAME is the name of the function, FLAGS is a set of + ECF_* flags and FNSPEC is a string describing functions fnspec. + + Each entry must have a corresponding expander of the form: void expand_NAME (gimple stmt) where STMT is the statement that performs the call. */ -DEF_INTERNAL_FN (LOAD_LANES, ECF_CONST | ECF_LEAF) -DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF) -DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW) -DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW) -DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW) -DEF_INTERNAL_FN (LOOP_VECTORIZED, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW) -DEF_INTERNAL_FN (MASK_LOAD, ECF_PURE | ECF_LEAF) -DEF_INTERNAL_FN (MASK_STORE, ECF_LEAF) -DEF_INTERNAL_FN (ANNOTATE, ECF_CONST | ECF_LEAF | ECF_NOTHROW) -DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW) -DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW) -DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW) -DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | ECF_LEAF | ECF_NOTHROW) -DEF_INTERNAL_FN (ABNORMAL_DISPATCHER, ECF_NORETURN) -DEF_INTERNAL_FN (BUILTIN_EXPECT, ECF_CONST | ECF_LEAF | ECF_NOTHROW) +DEF_INTERNAL_FN (LOAD_LANES, ECF_CONST | ECF_LEAF, NULL) +DEF_INTERNAL_FN (STORE_LANES, ECF_CONST | ECF_LEAF, NULL) +DEF_INTERNAL_FN (GOMP_SIMD_LANE, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL) +DEF_INTERNAL_FN (GOMP_SIMD_VF, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) +DEF_INTERNAL_FN (GOMP_SIMD_LAST_LANE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) +DEF_INTERNAL_FN (LOOP_VECTORIZED, ECF_NOVOPS | ECF_LEAF | ECF_NOTHROW, NULL) +DEF_INTERNAL_FN (MASK_LOAD, ECF_PURE | ECF_LEAF, NULL) +DEF_INTERNAL_FN (MASK_STORE, ECF_LEAF, NULL) +DEF_INTERNAL_FN (ANNOTATE, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) +DEF_INTERNAL_FN (UBSAN_NULL, ECF_LEAF | ECF_NOTHROW, ".W.") +DEF_INTERNAL_FN (UBSAN_CHECK_ADD, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) +DEF_INTERNAL_FN (UBSAN_CHECK_SUB, ECF_CONST | ECF_LEAF | ECF_NOTHROW, NULL) +DEF_INTERNAL_FN (UBSAN_CHECK_MUL, ECF_CONST | 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, ".W..") diff --git a/gcc-4.9/gcc/internal-fn.h b/gcc-4.9/gcc/internal-fn.h index 9c3215f3d..af93e154a 100644 --- a/gcc-4.9/gcc/internal-fn.h +++ b/gcc-4.9/gcc/internal-fn.h @@ -21,12 +21,16 @@ along with GCC; see the file COPYING3. If not see #define GCC_INTERNAL_FN_H enum internal_fn { -#define DEF_INTERNAL_FN(CODE, FLAGS) IFN_##CODE, +#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) IFN_##CODE, #include "internal-fn.def" #undef DEF_INTERNAL_FN IFN_LAST }; +/* Initialize internal function tables. */ + +extern void init_internal_fns (); + /* Return the name of internal function FN. The name is only meaningful for dumps; it has no linkage. */ @@ -48,6 +52,16 @@ internal_fn_flags (enum internal_fn fn) return internal_fn_flags_array[(int) fn]; } +/* Return fnspec for function FN. */ + +extern GTY(()) const_tree internal_fn_fnspec_array[IFN_LAST + 1]; + +static inline const_tree +internal_fn_fnspec (enum internal_fn fn) +{ + return internal_fn_fnspec_array[(int) fn]; +} + extern void expand_internal_call (gimple); #endif diff --git a/gcc-4.9/gcc/ipa-cp.c b/gcc-4.9/gcc/ipa-cp.c index 16c629d55..b3c0c881f 100644 --- a/gcc-4.9/gcc/ipa-cp.c +++ b/gcc-4.9/gcc/ipa-cp.c @@ -3036,6 +3036,11 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, intersect_with_agg_replacements (cs->caller, src_idx, &inter, 0); } + else + { + inter.release (); + return vNULL; + } } else { @@ -3051,6 +3056,11 @@ intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, else intersect_with_plats (src_plats, &inter, 0); } + else + { + inter.release (); + return vNULL; + } } } else if (jfunc->type == IPA_JF_ANCESTOR @@ -3134,7 +3144,8 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node, vec callers) { struct ipa_node_params *dest_info = IPA_NODE_REF (node); - struct ipa_agg_replacement_value *res = NULL; + struct ipa_agg_replacement_value *res; + struct ipa_agg_replacement_value **tail = &res; struct cgraph_edge *cs; int i, j, count = ipa_get_param_count (dest_info); @@ -3178,14 +3189,15 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node, v->offset = item->offset; v->value = item->value; v->by_ref = plats->aggs_by_ref; - v->next = res; - res = v; + *tail = v; + tail = &v->next; } next_param: if (inter.exists ()) inter.release (); } + *tail = NULL; return res; } @@ -3194,7 +3206,8 @@ find_aggregate_values_for_callers_subset (struct cgraph_node *node, static struct ipa_agg_replacement_value * known_aggs_to_agg_replacement_list (vec known_aggs) { - struct ipa_agg_replacement_value *res = NULL; + struct ipa_agg_replacement_value *res; + struct ipa_agg_replacement_value **tail = &res; struct ipa_agg_jump_function *aggjf; struct ipa_agg_jf_item *item; int i, j; @@ -3208,9 +3221,10 @@ known_aggs_to_agg_replacement_list (vec known_aggs) v->offset = item->offset; v->value = item->value; v->by_ref = aggjf->by_ref; - v->next = res; - res = v; + *tail = v; + tail = &v->next; } + *tail = NULL; return res; } diff --git a/gcc-4.9/gcc/ipa-devirt.c b/gcc-4.9/gcc/ipa-devirt.c index 43e904ce7..bb4b4168e 100644 --- a/gcc-4.9/gcc/ipa-devirt.c +++ b/gcc-4.9/gcc/ipa-devirt.c @@ -177,7 +177,10 @@ static inline bool polymorphic_type_binfo_p (tree binfo) { /* See if BINFO's type has an virtual table associtated with it. */ - return BINFO_VTABLE (TYPE_BINFO (BINFO_TYPE (binfo))); + tree type_binfo = TYPE_BINFO (BINFO_TYPE (binfo)); + if (L_IPO_COMP_MODE && !type_binfo) + return false; + return BINFO_VTABLE (type_binfo); } /* One Definition Rule hashtable helpers. */ @@ -1019,7 +1022,8 @@ give_up: if ((TREE_CODE (type) != RECORD_TYPE || !TYPE_BINFO (type) || !polymorphic_type_binfo_p (TYPE_BINFO (type))) - && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST + && (!TYPE_SIZE (type) + || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST || (offset + tree_to_uhwi (TYPE_SIZE (expected_type)) <= tree_to_uhwi (TYPE_SIZE (type))))) return true; @@ -1895,8 +1899,7 @@ ipa_devirt (void) /* Don't use an implicitly-declared destructor (c++/58678). */ struct cgraph_node *non_thunk_target = cgraph_function_node (likely_target); - if (DECL_ARTIFICIAL (non_thunk_target->decl) - && DECL_COMDAT (non_thunk_target->decl)) + if (DECL_ARTIFICIAL (non_thunk_target->decl)) { if (dump_file) fprintf (dump_file, "Target is artificial\n\n"); diff --git a/gcc-4.9/gcc/ipa-inline-analysis.c b/gcc-4.9/gcc/ipa-inline-analysis.c index 23c83a8b0..904a52192 100644 --- a/gcc-4.9/gcc/ipa-inline-analysis.c +++ b/gcc-4.9/gcc/ipa-inline-analysis.c @@ -861,9 +861,19 @@ evaluate_conditions_for_known_args (struct cgraph_node *node, } if (c->code == IS_NOT_CONSTANT || c->code == CHANGED) continue; - res = fold_binary_to_constant (c->code, boolean_type_node, val, c->val); - if (res && integer_zerop (res)) - continue; + + if (operand_equal_p (TYPE_SIZE (TREE_TYPE (c->val)), + TYPE_SIZE (TREE_TYPE (val)), 0)) + { + val = fold_unary (VIEW_CONVERT_EXPR, TREE_TYPE (c->val), val); + + res = val + ? fold_binary_to_constant (c->code, boolean_type_node, val, c->val) + : NULL; + + if (res && integer_zerop (res)) + continue; + } clause |= 1 << (i + predicate_first_dynamic_condition); } return clause; diff --git a/gcc-4.9/gcc/ipa-inline-transform.c b/gcc-4.9/gcc/ipa-inline-transform.c index 69598b3c8..f221eecac 100644 --- a/gcc-4.9/gcc/ipa-inline-transform.c +++ b/gcc-4.9/gcc/ipa-inline-transform.c @@ -94,7 +94,6 @@ can_remove_node_now_p_1 (struct cgraph_node *node) the callgraph so references can point to it. */ return (!node->address_taken && !ipa_ref_has_aliases_p (&node->ref_list) - && !node->used_as_abstract_origin && cgraph_can_remove_if_no_direct_calls_p (node) /* Inlining might enable more devirtualizing, so we want to remove those only after all devirtualizable virtual calls are processed. @@ -207,6 +206,7 @@ clone_inlined_nodes (struct cgraph_edge *e, bool duplicate, MIN(e->count, e->callee->count), freq_scale, update_original, vNULL, true, inlining_into, NULL); + n->used_as_abstract_origin = e->callee->used_as_abstract_origin; cgraph_redirect_edge_callee (e, n); } } diff --git a/gcc-4.9/gcc/ipa-inline.c b/gcc-4.9/gcc/ipa-inline.c index 29c76b88e..c116f740f 100644 --- a/gcc-4.9/gcc/ipa-inline.c +++ b/gcc-4.9/gcc/ipa-inline.c @@ -501,7 +501,7 @@ want_early_inline_function_p (struct cgraph_edge *e) growth); want_inline = false; } - else if (DECL_COMDAT (callee->decl) + else if (!flag_auto_profile && DECL_COMDAT (callee->decl) && growth <= PARAM_VALUE (PARAM_EARLY_INLINING_INSNS_COMDAT)) ; else if ((n = num_calls (callee)) != 0 @@ -728,13 +728,25 @@ want_inline_small_function_p (struct cgraph_edge *e, bool report) else if (!DECL_DECLARED_INLINE_P (callee->decl) && !flag_inline_functions) { - /* growth_likely_positive is expensive, always test it last. */ - if (growth >= MAX_INLINE_INSNS_SINGLE - || growth_likely_positive (callee, growth)) - { + /* For functions not declared inline, if it has big_speedup + or has good hints for performance and the size growth is + small, they are profitable to inline. */ + if (big_speedup + || (hints & (INLINE_HINT_indirect_call + | INLINE_HINT_loop_iterations + | INLINE_HINT_array_index + | INLINE_HINT_loop_stride))) + { + if (growth >= MAX_GROWTH_AUTO_INLINE_FUNC) + want_inline = false; + } + /* growth_likely_positive is expensive, always test it last. */ + else if (growth >= MAX_INLINE_INSNS_SINGLE + || growth_likely_positive (callee, growth)) + { e->inline_failed = CIF_NOT_DECLARED_INLINED; - want_inline = false; - } + want_inline = false; + } } /* Apply MAX_INLINE_INSNS_AUTO limit for functions not declared inline Upgrade it to MAX_INLINE_INSNS_SINGLE when hints suggests that diff --git a/gcc-4.9/gcc/ipa-profile.c b/gcc-4.9/gcc/ipa-profile.c index 17de6876e..e9fba9801 100644 --- a/gcc-4.9/gcc/ipa-profile.c +++ b/gcc-4.9/gcc/ipa-profile.c @@ -557,8 +557,7 @@ ipa_profile (void) cumulated_time * 100.0 / overall_time, cumulated_size * 100.0 / overall_size); } - if (threshold > get_hot_bb_threshold () - || in_lto_p) + if (in_lto_p) { if (dump_file) fprintf (dump_file, "Threshold updated.\n"); diff --git a/gcc-4.9/gcc/ipa-pure-const.c b/gcc-4.9/gcc/ipa-pure-const.c index 948665e4a..5c49ac64d 100644 --- a/gcc-4.9/gcc/ipa-pure-const.c +++ b/gcc-4.9/gcc/ipa-pure-const.c @@ -1434,7 +1434,7 @@ propagate_nothrow (void) else if (e->can_throw_external && !TREE_NOTHROW (y->decl)) can_throw = true; } - for (ie = node->indirect_calls; ie; ie = ie->next_callee) + for (ie = w->indirect_calls; ie; ie = ie->next_callee) if (ie->can_throw_external) { can_throw = true; diff --git a/gcc-4.9/gcc/ipa-split.c b/gcc-4.9/gcc/ipa-split.c index 38bd88365..0d1495da0 100644 --- a/gcc-4.9/gcc/ipa-split.c +++ b/gcc-4.9/gcc/ipa-split.c @@ -167,7 +167,11 @@ test_nonssa_use (gimple, tree t, tree, void *data) || (TREE_CODE (t) == VAR_DECL && auto_var_in_fn_p (t, current_function_decl)) || TREE_CODE (t) == RESULT_DECL - || TREE_CODE (t) == LABEL_DECL) + /* Normal labels are part of CFG and will be handled gratefuly. + Forced labels however can be used directly by statements and + need to stay in one partition along with their uses. */ + || (TREE_CODE (t) == LABEL_DECL + && FORCED_LABEL (t))) return bitmap_bit_p ((bitmap)data, DECL_UID (t)); /* For DECL_BY_REFERENCE, the return value is actually a pointer. We want @@ -213,6 +217,7 @@ verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars, edge e; edge_iterator ei; bool ok = true; + basic_block bb; FOR_EACH_EDGE (e, ei, current->entry_bb->preds) if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun) @@ -225,8 +230,8 @@ verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars, while (!worklist.is_empty ()) { gimple_stmt_iterator bsi; - basic_block bb = worklist.pop (); + bb = worklist.pop (); FOR_EACH_EDGE (e, ei, bb->preds) if (e->src != ENTRY_BLOCK_PTR_FOR_FN (cfun) && bitmap_set_bit (seen, e->src->index)) @@ -250,10 +255,10 @@ verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars, if (gimple_code (stmt) == GIMPLE_LABEL && test_nonssa_use (stmt, gimple_label_label (stmt), NULL_TREE, non_ssa_vars)) - { - ok = false; - goto done; - } + { + ok = false; + goto done; + } } for (bsi = gsi_start_phis (bb); !gsi_end_p (bsi); gsi_next (&bsi)) { @@ -286,6 +291,27 @@ verify_non_ssa_vars (struct split_point *current, bitmap non_ssa_vars, } } } + + /* Verify that the rest of function does not define any label + used by the split part. */ + FOR_EACH_BB_FN (bb, cfun) + if (!bitmap_bit_p (current->split_bbs, bb->index) + && !bitmap_bit_p (seen, bb->index)) + { + gimple_stmt_iterator bsi; + for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi)) + if (gimple_code (gsi_stmt (bsi)) == GIMPLE_LABEL + && test_nonssa_use (gsi_stmt (bsi), + gimple_label_label (gsi_stmt (bsi)), + NULL_TREE, non_ssa_vars)) + { + ok = false; + goto done; + } + else if (gimple_code (gsi_stmt (bsi)) != GIMPLE_LABEL) + break; + } + done: BITMAP_FREE (seen); worklist.release (); @@ -734,7 +760,8 @@ mark_nonssa_use (gimple, tree t, tree, void *data) if ((TREE_CODE (t) == VAR_DECL && auto_var_in_fn_p (t, current_function_decl)) || TREE_CODE (t) == RESULT_DECL - || TREE_CODE (t) == LABEL_DECL) + || (TREE_CODE (t) == LABEL_DECL + && FORCED_LABEL (t))) bitmap_set_bit ((bitmap)data, DECL_UID (t)); /* For DECL_BY_REFERENCE, the return value is actually a pointer. We want diff --git a/gcc-4.9/gcc/ipa.c b/gcc-4.9/gcc/ipa.c index 5a0b199ff..5d2465c83 100644 --- a/gcc-4.9/gcc/ipa.c +++ b/gcc-4.9/gcc/ipa.c @@ -388,9 +388,17 @@ symtab_remove_unreachable_nodes (bool before_inlining_p, FILE *file) && DECL_ABSTRACT_ORIGIN (node->decl)) { struct cgraph_node *origin_node - = cgraph_get_create_node (DECL_ABSTRACT_ORIGIN (node->decl)); - origin_node->used_as_abstract_origin = true; - enqueue_node (origin_node, &first, reachable); + = cgraph_get_node (DECL_ABSTRACT_ORIGIN (node->decl)); + if (origin_node && !origin_node->used_as_abstract_origin) + { + origin_node->used_as_abstract_origin = true; + gcc_assert (!origin_node->prev_sibling_clone); + gcc_assert (!origin_node->next_sibling_clone); + for (cgraph_node *n = origin_node->clones; n; + n = n->next_sibling_clone) + if (n->decl == DECL_ABSTRACT_ORIGIN (node->decl)) + n->used_as_abstract_origin = true; + } } /* If any symbol in a comdat group is reachable, force all externally visible symbols in the same comdat @@ -1146,12 +1154,15 @@ function_and_variable_visibility (bool whole_program) if (node->callers && can_replace_by_local_alias (node)) { struct cgraph_node *alias = cgraph (symtab_nonoverwritable_alias (node)); + struct cgraph_edge *e, *next_caller; if (alias && alias != node) { - while (node->callers) + for (e = node->callers; e; e = next_caller) { - struct cgraph_edge *e = node->callers; + next_caller = e->next_caller; + if (L_IPO_COMP_MODE && cgraph_is_fake_indirect_call_edge (e)) + continue; cgraph_redirect_edge_callee (e, alias); if (gimple_has_body_p (e->caller->decl)) diff --git a/gcc-4.9/gcc/ira-build.c b/gcc-4.9/gcc/ira-build.c index 0396f379f..ab27cc64d 100644 --- a/gcc-4.9/gcc/ira-build.c +++ b/gcc-4.9/gcc/ira-build.c @@ -38,6 +38,7 @@ along with GCC; see the file COPYING3. If not see #include "sparseset.h" #include "ira-int.h" #include "emit-rtl.h" /* FIXME: Can go away once crtl is moved to rtl.h. */ +#include "hash-table.h" static ira_copy_t find_allocno_copy (ira_allocno_t, ira_allocno_t, rtx, ira_loop_tree_node_t); @@ -94,6 +95,26 @@ ira_copy_t *ira_copies; /* Size of the previous array. */ int ira_copies_num; +/* The information of using fp as a free register in a ira_loop_tree_node. */ +struct fpset_info +{ + /* If there is a call, we need to insert fp setting somewhere before it + to keep the stack frame chain. fpset_cost is the fpsetting cost in + current ira_loop_tree_node, not including those in its sub + ira_loop_tree_node. */ + int fpset_cost; + /* total_fpset_cost is the fpsetting cost in current ira_loop_tree_node + and all its sub ira_loop_tree_nodes. */ + int total_fpset_cost; + /* The frequency of the most frequent bb whose reg pressure is larger + than available hard registers. */ + int bbfreq_w_high_regpressure; + /* has_call indicates whether there is call inside current + ira_loop_tree_node and all its sub ira_loop_tree_nodes. */ + bool has_call; +}; + +#define FPSET_COST_BASE 10 /* LAST_BASIC_BLOCK before generating additional insns because of live @@ -1368,6 +1389,33 @@ static alloc_pool copy_pool; container of array ira_copies. */ static vec copy_vec; +struct ira_copy_hasher : typed_free_remove +{ + typedef ira_copy_t value_type; + typedef ira_copy_t compare_type; + static inline hashval_t hash (const value_type *); + static inline bool equal (const value_type *, const compare_type *); +}; + +inline hashval_t +ira_copy_hasher::hash (const value_type *item) +{ + return INSN_UID((*item)->insn); +} + +/* Equality function for ira_copy_hasher. A and B + point to the two hash table entries to compare. */ + +inline bool +ira_copy_hasher::equal (const value_type *a, const compare_type *b) +{ + return INSN_UID((*a)->insn) == INSN_UID((*b)->insn); +} + +/* Hash table mapping from insn to the list of ira_copy_t + generated from the insn. */ +static hash_table copy_list_table; + /* The function initializes data concerning allocno copies. */ static void initiate_copies (void) @@ -1375,6 +1423,7 @@ initiate_copies (void) copy_pool = create_alloc_pool ("copies", sizeof (struct ira_allocno_copy), 100); copy_vec.create (get_max_uid ()); + copy_list_table.create (get_max_uid ()); ira_copies = NULL; ira_copies_num = 0; } @@ -1424,6 +1473,7 @@ ira_create_copy (ira_allocno_t first, ira_allocno_t second, int freq, cp->second = second; cp->freq = freq; cp->constraint_p = constraint_p; + cp->copy_list = NULL; cp->insn = insn; cp->loop_tree_node = loop_tree_node; copy_vec.safe_push (cp); @@ -1437,6 +1487,7 @@ static void add_allocno_copy_to_list (ira_copy_t cp) { ira_allocno_t first = cp->first, second = cp->second; + ira_copy_t **slot; cp->prev_first_allocno_copy = NULL; cp->prev_second_allocno_copy = NULL; @@ -1458,6 +1509,20 @@ add_allocno_copy_to_list (ira_copy_t cp) } ALLOCNO_COPIES (first) = cp; ALLOCNO_COPIES (second) = cp; + + /* Add copy to corresponding list in copy_list_table. */ + slot = copy_list_table.find_slot_with_hash ( + &cp, INSN_UID (cp->insn), INSERT); + if ((*slot) == HTAB_EMPTY_ENTRY) + { + (*slot) = XNEW (ira_copy_t); + (**slot) = cp; + } + else + { + cp->copy_list = (**slot); + (**slot) = cp; + } } /* Make a copy CP a canonical copy where number of the @@ -1508,6 +1573,30 @@ ira_add_allocno_copy (ira_allocno_t first, ira_allocno_t second, int freq, return cp; } +/* For insn like "a = b * c", if b and c are dead immediately + after a, copy (a, b) and copy (a, c) are alternate copies + and a is the connecting allocno. If CP has alternate copy, + return the first one in copy_list_table connecting with CP + via CONNECT. */ +ira_copy_t +find_alternate_copy (ira_copy_t cp, ira_allocno_t connect) +{ + ira_copy_t list; + ira_copy_t *found = copy_list_table.find_with_hash (&cp, + INSN_UID (cp->insn)); + if (found == NULL) + return NULL; + list = (*found); + while (list) + { + if ((list->first == connect || list->second == connect) + && list != cp) + return list; + list = list->copy_list; + } + return NULL; +} + /* Print info about copy CP into file F. */ static void print_copy (FILE *f, ira_copy_t cp) @@ -1628,6 +1717,7 @@ finish_copies (void) FOR_EACH_COPY (cp, ci) finish_copy (cp); copy_vec.release (); + copy_list_table.dispose (); free_alloc_pool (copy_pool); } @@ -3408,6 +3498,388 @@ update_conflict_hard_reg_costs (void) } } +/* Return the frequency of the LOOP's preheader bb. */ +static int +get_preheader_freq (struct loop *lp) +{ + int preheader_freq = 0; + edge_iterator ei; + edge e; + + FOR_EACH_EDGE (e, ei, lp->header->preds) + if (!flow_bb_inside_loop_p (lp, e->src)) + preheader_freq += EDGE_FREQUENCY (e); + return preheader_freq; +} + +/* Collect fp setting information INFOS from LOOP_NODE and its + sub loops and bbs. LOOP_NODE which is not a bb will be saved in + SORTED_LOOPS. */ +static struct fpset_info +get_fpset_cost (ira_loop_tree_node_t loop_node, + ira_loop_tree_node_t *sorted_loops, + int *loop_num, + struct fpset_info *infos) +{ + int fpset_cost = 0, total_fpset_cost = 0, bbfreq_w_high_regpressure = 0; + struct fpset_info info = {0, 0, 0, false}; + loop_node->fp_is_free = false; + + if (loop_node->bb != NULL) + { + int call_num = 0; + rtx insn; + FOR_BB_INSNS (loop_node->bb, insn) + if (CALL_P (insn)) + call_num++; + /* Use a simple estimation here, assume there is a fp setting + before every call, which could be improved. */ + info.fpset_cost = call_num * loop_node->bb->frequency + * (PARAM_VALUE (PARAM_FPSET_COST_FRACTION) + / FPSET_COST_BASE); + info.total_fpset_cost = info.fpset_cost; + info.bbfreq_w_high_regpressure = + (loop_node->reg_pressure[GENERAL_REGS] + > ira_class_hard_regs_num[GENERAL_REGS]) + * loop_node->bb->frequency; + info.has_call = call_num > 0; + return info; + } + else + { + ira_loop_tree_node_t child_node; + gcc_assert ((loop_node == ira_loop_tree_root) + || !loop_node->to_remove_p); + /* This loop is to be sorted. */ + if (loop_node != ira_loop_tree_root) + sorted_loops[(*loop_num)++] = loop_node; + for (child_node = loop_node->children; child_node != NULL; + child_node = child_node->next) + { + int promoted_fpset_cost; + struct fpset_info child_info; + + child_info = get_fpset_cost (child_node, sorted_loops, + loop_num, infos); + if (child_node->bb != NULL) + { + /* For child_nodes which are bbs in current loop node. */ + fpset_cost += child_info.fpset_cost; + total_fpset_cost += child_info.total_fpset_cost; + bbfreq_w_high_regpressure = MAX (bbfreq_w_high_regpressure, + child_info.bbfreq_w_high_regpressure); + } else { + /* For loops which are independent regalloc regions. */ + int preheader_freq = get_preheader_freq (child_node->loop); + /* If the fp setting in child loop could be promoted, the + fp setting cost of the child loop will be computed + below as promoted_fpset_cost. We cannot know whether fp + setting could be promoted or not before reload complete, + so choose the smaller one between total_fpset_cost and + promoted_fpset_cost as the child loop cost. */ + promoted_fpset_cost = child_info.has_call + ? preheader_freq : 0; + total_fpset_cost += MIN (child_info.total_fpset_cost, + promoted_fpset_cost); + } + info.has_call = info.has_call || child_info.has_call; + } + + info.fpset_cost = fpset_cost; + info.total_fpset_cost = total_fpset_cost; + info.bbfreq_w_high_regpressure = bbfreq_w_high_regpressure; + infos[loop_node->loop_num] = info; + return info; + } +} + +/* Mark the loop node LP as fp_is_free if it is cost-effective. + Only if the loop is marked as fp_is_free, fp could be allocated to + the pseudos inside of it in IRA and LRA. After the loop is processed, + set the bitmap LOOP_IS_MARKED. INFOS contains fpset_info collected by + get_fpset_cost. + + The factors considered here: + 1. fpset_cost: if we cannot promote fp setting outside of current + loop, how much cost we gonna pay. + 2. spill_cost: if we cannot use fp as a free register, how much + spill cost we gonna pay. + 3. regmove_cost_fp_free_sub_not_free: + If current loop is set to use fp freely and it has high register + pressure while its subloop is set not use fp. how much cost we + gonna pay for the live range split on the subloop boundary. + regmove_cost_fp_not_free_sub_free: + If current loop is set not to use fp and its subloop is set to + use fp freely, ... + regmove_cost_fp_free_parent_not_free: + regmove_cost_fp_not_free_parent_free: + The same for current loop and its parent loop. + 4. any_sub_lp_use_fp: + If any subloop of current loop has been set to use fp freely, + and the subloop has high reg pressure, fp setting in current + loop cannot be promoted to its preheader anyway. Adjust the cost + accordingly in this case. + 5. compensate_cost: + If parent loop has been set to not use fp freely before current + loop is evaluated, it is assumed that fp setting in parent + loop could be shrinkwrapped. However, if current loop is set + to use fp freely and it has high reg pressure, the fp reference + in current loop will inhibit fp setting in its parent loop from + being promoted outside. Use compensate_cost to represent the + increased cost of the parent loop. */ +void +mark_loop_fp_free (ira_loop_tree_node_t lp, + sbitmap loop_is_marked, + struct fpset_info *infos, + FILE *ira_dump_file) +{ + int set_fp_free_cost = 0, set_fp_not_free_cost = 0; + int fpset_cost = 0; + int regmove_cost_fp_free, regmove_cost_fp_not_free; + int regmove_cost_fp_free_sub_not_free = 0; + int regmove_cost_fp_not_free_sub_free = 0; + int regmove_cost_fp_free_parent_not_free = 0; + int regmove_cost_fp_not_free_parent_free = 0; + int compensate_cost = 0, preheader_freq, promoted_fpset_cost; + ira_loop_tree_node_t sub_lp; + ira_loop_tree_node_t parent_lp = lp->parent; + /* Show is there any subloop using fp as a free register. */ + bool any_sub_lp_use_fp = false; + bool sub_lp_high_pressure, lp_high_pressure, parent_lp_high_pressure; + struct fpset_info *info = &infos[lp->loop_num]; + lp_high_pressure = info->bbfreq_w_high_regpressure > 0; + + for (sub_lp = lp->subloops; sub_lp != NULL; sub_lp = sub_lp->subloop_next) + { + struct fpset_info *sinfo = &infos[sub_lp->loop_num]; + preheader_freq = get_preheader_freq (sub_lp->loop); + promoted_fpset_cost = sinfo->has_call ? preheader_freq : 0; + sub_lp_high_pressure = sinfo->bbfreq_w_high_regpressure > 0; + /* If the subloop has been processed, add cost to current loop + if it chooses to set fp_is_free flag differently with the + subloop. */ + if (bitmap_bit_p (loop_is_marked, sub_lp->loop_num)) + { + fpset_cost += sub_lp->fp_is_free + ? sinfo->total_fpset_cost + : promoted_fpset_cost; + /* For current loop, if its fp_is_free is true and lp_high_pressure + is true, it is very likely fp will be used in current loop. + If adding that subloop's fp_is_free is false, there will be + live range split for fp on loop boarder. regmove_cost_fp_free + is the live range split cost for current loop to being marked as + fp_is_free. */ + regmove_cost_fp_free_sub_not_free += (!sub_lp->fp_is_free + && lp_high_pressure) + ? 2 * preheader_freq : 0; + /* For sub loop, if its fp_is_free is true and sub_lp_high_pressure + is true, it is very likely fp will be used in subloop. If current + loop's fp_is_free is false, there will be live range split + for fp on loop boarder. regmove_cost_fp_not_free is the live range + split cost. */ + regmove_cost_fp_not_free_sub_free += (sub_lp->fp_is_free + && sub_lp_high_pressure) + ? 2 * preheader_freq : 0; + /* If a subloop is marked as fp_is_free and it has high reg pressure, + it will probably use fp. */ + any_sub_lp_use_fp = any_sub_lp_use_fp + || (sub_lp_high_pressure && sub_lp->fp_is_free); + } + else + { + fpset_cost += MIN (sinfo->total_fpset_cost, + promoted_fpset_cost); + } + } + regmove_cost_fp_free = regmove_cost_fp_free_sub_not_free; + regmove_cost_fp_not_free = regmove_cost_fp_not_free_sub_free; + + preheader_freq = get_preheader_freq (lp->loop); + + if (bitmap_bit_p (loop_is_marked, parent_lp->loop_num)) + { + struct fpset_info *pinfo = &infos[parent_lp->loop_num]; + parent_lp_high_pressure = pinfo->bbfreq_w_high_regpressure > 0; + /* If parent loop and current loop have different choices of fp_is_free + setting, there will be register moves on loop region boarder. Calculate + such cost as regmove_cost_fp_free and regmove_cost_fp_not_free. */ + regmove_cost_fp_free_parent_not_free = (!parent_lp->fp_is_free + && lp_high_pressure) + ? 2 * preheader_freq : 0; + regmove_cost_fp_not_free_parent_free = (parent_lp->fp_is_free + && parent_lp_high_pressure) + ? 2 * preheader_freq : 0; + regmove_cost_fp_free += regmove_cost_fp_free_parent_not_free; + regmove_cost_fp_not_free += regmove_cost_fp_not_free_parent_free; + /* If parent loop has set not using fp freely and current loop plan + to use fp freely, which means the fp reference in current loop will + prevent fpsetting in parent loop from being promoted. Calculate + such cost as compensate_cost and add it to set_fp_free_cost of + current loop later. */ + if (!parent_lp->fp_is_free && (parent_lp != ira_loop_tree_root)) + compensate_cost = pinfo->total_fpset_cost; + } + + /* Add the fpset cost in the current loop. */ + fpset_cost += info->fpset_cost; + set_fp_free_cost = fpset_cost; + + /* If any subloop has been set to use fp freely, it is impossible + for current loop to promote any fpsetting to outerloop. So + set_fp_not_free_cost will have at least the same cost as + set_fp_free_cost. */ + if (any_sub_lp_use_fp) + set_fp_not_free_cost = set_fp_free_cost; + + /* Estimation of the spill cost saved by using fp freely. */ + if (lp_high_pressure) + set_fp_not_free_cost += 2 * info->bbfreq_w_high_regpressure; + + set_fp_free_cost += regmove_cost_fp_free + compensate_cost; + set_fp_not_free_cost += regmove_cost_fp_not_free; + + /* If set_fp_free_cost is less than set_fp_not_free_cost, which means + use fp freely will have less cost than not use fp, mark current loop + as fp_is_free. */ + if (set_fp_free_cost < set_fp_not_free_cost) + lp->fp_is_free = true; + bitmap_set_bit (loop_is_marked, lp->loop_num); + + if (ira_dump_file) + fprintf(ira_dump_file, " fpset_cost from subloops = %d\n" + " regmove_cost_fp_free_sub_not_free = %d\n" + " regmove_cost_fp_not_free_sub_free = %d\n" + " any_sub_lp_use_fp = %d\n" + " regmove_cost_fp_free_parent_not_free = %d\n" + " regmove_cost_fp_not_free_parent_free = %d\n" + " compensate_cost = %d\n" + " spill cost = %d\n" + " \n\n", + fpset_cost, + regmove_cost_fp_free_sub_not_free, + regmove_cost_fp_not_free_sub_free, + any_sub_lp_use_fp, + regmove_cost_fp_free_parent_not_free, + regmove_cost_fp_not_free_parent_free, + compensate_cost, + 2 * info->bbfreq_w_high_regpressure, + set_fp_free_cost, set_fp_not_free_cost); +} + +/* Sort loops for marking fp_is_free. We put most frequent loops first, + and then inner loops next. */ +static int +loop_fpset_compare_func (const void *v1p, const void *v2p) +{ + int diff; + ira_loop_tree_node_t l1 = *(const ira_loop_tree_node_t *) v1p; + ira_loop_tree_node_t l2 = *(const ira_loop_tree_node_t *) v2p; + + ira_assert (l1->parent != NULL && l2->parent != NULL); + if ((diff = l2->loop->header->frequency - l1->loop->header->frequency) != 0) + return diff; + if ((diff = (int) loop_depth (l2->loop) - (int) loop_depth (l1->loop)) != 0) + return diff; + /* Make sorting stable. */ + return l2->loop_num - l1->loop_num; +} + +/* Decide whether a loop region node should use fp freely or not based on + its reg pressure, calls frequencies inside the loop and those informations + from sub and parent loops of current loop. */ +void +decide_fp_use_in_loops (FILE *ira_dump_file) +{ + int i, n = 0; + ira_loop_tree_node_t *sorted_loops; + struct fpset_info *infos; + /* Record which loops have been marked. */ + sbitmap loop_is_marked; + basic_block bb; + + /* Initialize. */ + sorted_loops + = (ira_loop_tree_node_t *) ira_allocate (sizeof (ira_loop_tree_node_t) + * number_of_loops (cfun)); + memset (sorted_loops, 0, (sizeof (ira_loop_tree_node_t) + * number_of_loops (cfun))); + infos + = (struct fpset_info *) ira_allocate (sizeof (struct fpset_info) + * number_of_loops (cfun)); + memset (infos, 0, (sizeof (struct fpset_info) + * number_of_loops (cfun))); + get_fpset_cost (ira_loop_tree_root, sorted_loops, &n, infos); + loop_is_marked = sbitmap_alloc (number_of_loops (cfun)); + bitmap_clear (loop_is_marked); + ira_loop_tree_root->fp_is_free = true; + bitmap_set_bit (loop_is_marked, ira_loop_tree_root->loop_num); + + /* Sort loops according to loop importance. */ + qsort (sorted_loops, n, sizeof (ira_loop_tree_node_t), + loop_fpset_compare_func); + + /* mark_loop_fp_free set fp_is_free flags for different loops. The setting + for nested loops could affect each other, so we need to sort loops + and call mark_loop_fp_free for the most important loop first. */ + for (i = 0; i < n; i++) + { + if (ira_dump_file) + { + int loop_num = sorted_loops[i]->loop_num; + struct fpset_info *info = &infos[loop_num]; + bool lp_high_pressure = !low_pressure_loop_node_p (sorted_loops[i]); + fprintf(ira_dump_file, "mark loop[%d], header freq: %d," + " preheader freq: %d, seq: %d\n" + " fpset_cost: %d," + " total_fpset_cost: %d, has_call: %d\n" + " high pressure: %d\n", + sorted_loops[i]->loop_num, + sorted_loops[i]->loop->header->frequency, + get_preheader_freq (sorted_loops[i]->loop), + i, + info->fpset_cost, info->total_fpset_cost, + info->has_call, lp_high_pressure); + } + mark_loop_fp_free (sorted_loops[i], loop_is_marked, + infos, ira_dump_file); + } + + /* Set bb FP_IS_FREE flag according to loop's fp_is_free flag. */ + FOR_EACH_BB_FN (bb, cfun) + { + ira_loop_tree_node_t bb_node = IRA_BB_NODE (bb); + ira_loop_tree_node_t parent_node = bb_node->parent; + if (parent_node->fp_is_free) + bb->flags |= BB_FP_IS_FREE; + if (ira_dump_file) + fprintf(ira_dump_file, "bb%d [%s]\n", bb->index, + bb->flags & BB_FP_IS_FREE ? "fp" : ""); + } + + sbitmap_free (loop_is_marked); + ira_free (sorted_loops); + ira_free (infos); +} + +static void +dump_loop_fp_free (ira_loop_tree_node_t root, int level) +{ + int i; + ira_loop_tree_node_t loop; + const char *indent = " "; + + for (i = 0; i < level; i++) + fprintf (ira_dump_file, "%s", indent); + fprintf (ira_dump_file, "loop %d, level %d, [%s][%s]\n", + root->loop_num, root->level, + root->to_remove_p ? "r" : "", + root->fp_is_free ? "fp" : ""); + + for (loop = root->subloops; loop != NULL; loop = loop->subloop_next) + dump_loop_fp_free (loop, level + 1); +} + /* Create a internal representation (IR) for IRA (allocnos, copies, loop tree nodes). The function returns TRUE if we generate loop structure (besides nodes representing all function and the basic @@ -3447,6 +3919,14 @@ ira_build (void) setup_min_max_conflict_allocno_ids (); ira_build_conflicts (); update_conflict_hard_reg_costs (); + + if (frame_pointer_partially_needed) + { + decide_fp_use_in_loops (ira_dump_file); + if (ira_dump_file) + dump_loop_fp_free (ira_loop_tree_root, 0); + } + if (! ira_conflicts_p) { ira_allocno_t a; diff --git a/gcc-4.9/gcc/ira-color.c b/gcc-4.9/gcc/ira-color.c index 1f4c96e9a..a34d34a60 100644 --- a/gcc-4.9/gcc/ira-color.c +++ b/gcc-4.9/gcc/ira-color.c @@ -128,6 +128,13 @@ struct allocno_color_data conflicting with given pseudo. They should be of the allocno class. */ HARD_REG_SET profitable_hard_regs; + /* Record hard regs which has been newly assigned to other pseudo regs + which are conflicting with given pseduo when coloring current region. + For hardregs in new_conflict_hard_regs, the updated_hard_reg_costs + and updated_conflict_hard_reg_costs of the hardregs for given pseudo + are stale, so they should not be used for cost update in + update_conflict_hard_regno_costs. */ + HARD_REG_SET new_conflict_hard_regs; /* The allocno hard registers node. */ allocno_hard_regs_node_t hard_regs_node; /* Array of structures allocno_hard_regs_subnode representing @@ -1052,6 +1059,10 @@ setup_profitable_hard_regs (void) OBJECT_TOTAL_CONFLICT_HARD_REGS (obj)); } } + /* If loop region is marked as !fp_is_free, all the allocnos inside it will + not use fp as a free register. */ + if (frame_pointer_partially_needed && !a->loop_tree_node->fp_is_free) + CLEAR_HARD_REG_BIT (data->profitable_hard_regs, HARD_FRAME_POINTER_REGNUM); } /* Exclude hard regs already assigned for conflicting objects. */ EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, i, bi) @@ -1178,6 +1189,20 @@ free_update_cost_record_list (struct update_cost_record *list) } } +/* Free memory for CURR record in LIST. */ +static void +free_a_update_cost_record (struct update_cost_record **list, + struct update_cost_record *prev, + struct update_cost_record *curr) +{ + if (prev == NULL) + *list = curr->next; + else + prev->next = curr->next; + pool_free (update_cost_record_pool, curr); +} + + /* Free memory allocated for all update cost records. */ static void finish_update_cost_records (void) @@ -1201,10 +1226,10 @@ struct update_cost_queue_elem connecting this allocno to the one being allocated. */ int divisor; - /* Allocno from which we are chaning costs of connected allocnos. + /* Copy from which we are chaning costs of connected allocnos. It is used not go back in graph of allocnos connected by copies. */ - ira_allocno_t from; + ira_copy_t from; /* The next allocno in the queue, or null if this is the last element. */ ira_allocno_t next; @@ -1264,7 +1289,7 @@ start_update_cost (void) /* Add (ALLOCNO, FROM, DIVISOR) to the end of update_cost_queue, unless ALLOCNO is already in the queue, or has NO_REGS class. */ static inline void -queue_update_cost (ira_allocno_t allocno, ira_allocno_t from, int divisor) +queue_update_cost (ira_allocno_t allocno, ira_copy_t from, int divisor) { struct update_cost_queue_elem *elem; @@ -1288,7 +1313,7 @@ queue_update_cost (ira_allocno_t allocno, ira_allocno_t from, int divisor) false if the queue was empty, otherwise make (*ALLOCNO, *FROM, *DIVISOR) describe the removed element. */ static inline bool -get_next_update_cost (ira_allocno_t *allocno, ira_allocno_t *from, int *divisor) +get_next_update_cost (ira_allocno_t *allocno, ira_copy_t *from, int *divisor) { struct update_cost_queue_elem *elem; @@ -1329,16 +1354,19 @@ update_allocno_cost (ira_allocno_t allocno, int hard_regno, int update_cost) /* Update (decrease if DECR_P) HARD_REGNO cost of allocnos connected by copies to ALLOCNO to increase chances to remove some copies as the result of subsequent assignment. Record cost updates if - RECORD_P is true. */ + RECORD_P is true. CONFLICT_P shows whether this is updating cost + for allocno known conflicting with another allocno assigned to + HARD_REGNO. */ static void update_costs_from_allocno (ira_allocno_t allocno, int hard_regno, - int divisor, bool decr_p, bool record_p) + int divisor, bool decr_p, bool record_p, + bool conflict_p) { int cost, update_cost; enum machine_mode mode; enum reg_class rclass, aclass; - ira_allocno_t another_allocno, from = NULL; - ira_copy_t cp, next_cp; + ira_allocno_t another_allocno; + ira_copy_t cp, next_cp, from = NULL; rclass = REGNO_REG_CLASS (hard_regno); do @@ -1360,7 +1388,23 @@ update_costs_from_allocno (ira_allocno_t allocno, int hard_regno, else gcc_unreachable (); - if (another_allocno == from) + if (from != NULL + && (another_allocno == from->first + || another_allocno == from->second)) + continue; + + /* For a = b * c; if there are copies (a, b) and (a, c), + it makes no sense to propagate cost from b to a then to c. */ + if (from != NULL + && from->insn == cp->insn) + continue; + + /* For a = b * c; if there are copies (a, b) and (a, c), + and if we know b is conflicting with hardreg r1, sometimes it is + bad to propagate the disfavor of r1 from b to a because the + alterate copy (a, c) may still want to choose r1. */ + if (conflict_p + && find_alternate_copy (cp, another_allocno)) continue; aclass = ALLOCNO_CLASS (another_allocno); @@ -1381,10 +1425,11 @@ update_costs_from_allocno (ira_allocno_t allocno, int hard_regno, if (! update_allocno_cost (another_allocno, hard_regno, update_cost)) continue; - queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR); + + queue_update_cost (another_allocno, cp, divisor * COST_HOP_DIVISOR); if (record_p && ALLOCNO_COLOR_DATA (another_allocno) != NULL) ALLOCNO_COLOR_DATA (another_allocno)->update_cost_records - = get_update_cost_record (hard_regno, divisor, + = get_update_cost_record (hard_regno, divisor * COST_HOP_DIVISOR, ALLOCNO_COLOR_DATA (another_allocno) ->update_cost_records); } @@ -1402,7 +1447,7 @@ update_costs_from_prefs (ira_allocno_t allocno) start_update_cost (); for (pref = ALLOCNO_PREFS (allocno); pref != NULL; pref = pref->next_pref) update_costs_from_allocno (allocno, pref->hard_regno, - COST_HOP_DIVISOR, true, true); + COST_HOP_DIVISOR, true, true, false); } /* Update (decrease if DECR_P) the cost of allocnos connected to @@ -1417,7 +1462,8 @@ update_costs_from_copies (ira_allocno_t allocno, bool decr_p, bool record_p) hard_regno = ALLOCNO_HARD_REGNO (allocno); ira_assert (hard_regno >= 0 && ALLOCNO_CLASS (allocno) != NO_REGS); start_update_cost (); - update_costs_from_allocno (allocno, hard_regno, 1, decr_p, record_p); + update_costs_from_allocno (allocno, hard_regno, 1, decr_p, + record_p, false); } /* Restore costs of allocnos connected to ALLOCNO by copies as it was @@ -1436,12 +1482,119 @@ restore_costs_from_copies (ira_allocno_t allocno) records = ALLOCNO_COLOR_DATA (allocno)->update_cost_records; start_update_cost (); for (curr = records; curr != NULL; curr = curr->next) + { update_costs_from_allocno (allocno, curr->hard_regno, - curr->divisor, true, false); + curr->divisor, false, false, + false); + } free_update_cost_record_list (records); ALLOCNO_COLOR_DATA (allocno)->update_cost_records = NULL; } +/* If HARDREG is assigned to A, pseudo reg B conflicting with A + will not be assigned to HARDREG anymore. It is better to + take the fact into consideration of cost propagation. So this + func revokes the previous HARDREG related updates originated + from B, then propagates the disfavor of the HARDREG to other + pseudos connecting with B. + + Note: We only propagate cost to the copies connecting with B. + The updated_hard_reg_costs and updated_conflict_hard_reg_costs + of B are not updated here. The impact of hardreg conflicting + may be little underestimated compared with the impact of + preference (For hardreg preference propagation, + updated_hard_reg_costs of A is updated, then B connecting with + A will be updated. When assign_hard_reg for A, the update to B + will be superimposed on the preference of A). In addition, by + updating updated_hard_reg_costs and updated_conflict_hard_reg_costs + of B, the impact to improve_allocation is unclear. So for now, + updated_hard_reg_costs and updated_conflict_hard_reg_costs of B + are not updated. new_conflict_hard_regs is created to prevent + using updated_hard_reg_costs and updated_conflict_hard_reg_costs + of B in update_conflict_hard_regno_costs func. */ + +static void +restore_costs_from_conflicts (ira_allocno_t a, int hardreg) +{ + int word, nwords; + enum machine_mode mode; + + nwords = ALLOCNO_NUM_OBJECTS (a); + mode = ALLOCNO_MODE (a); + ira_init_register_move_cost_if_necessary (mode); + + curr_allocno_process++; + for (word = 0; word < nwords; word++) + { + ira_object_t conflict_obj; + ira_object_t obj = ALLOCNO_OBJECT (a, word); + ira_object_conflict_iterator oci; + + /* Update conflicting allocnos. */ + FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci) + { + ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj); + struct update_cost_record *curr, *prev, *next; + allocno_color_data_t data = ALLOCNO_COLOR_DATA (conflict_a); + + if (!bitmap_bit_p (consideration_allocno_bitmap, + ALLOCNO_NUM (conflict_a)) + || ALLOCNO_ASSIGNED_P (conflict_a) + || (data == NULL) + || (data->last_process == curr_allocno_process)) + continue; + + data->last_process = curr_allocno_process; + /* Record that hardreg will not be assigned to conflict_a in + ira coloring unless improve_allocation adjusts the overall + coloring later. */ + SET_HARD_REG_BIT (data->new_conflict_hard_regs, hardreg); + + start_update_cost (); + /* Revoke the hardreg related cost update records saved in + ALLOCNO_COLOR_DATA (conflict_a), then remove those records + from head of data->update_cost_records list. */ + curr = data->update_cost_records; + prev = data->update_cost_records; + while (curr != NULL && curr->hard_regno == hardreg) + { + update_costs_from_allocno (conflict_a, curr->hard_regno, + curr->divisor, false, false, + false); + /* Delete current record. */ + free_a_update_cost_record (&data->update_cost_records, + NULL, curr); + curr = data->update_cost_records; + prev = data->update_cost_records; + } + if (curr != NULL) + curr = curr->next; + /* Revoke the hardreg related cost update records saved in + ALLOCNO_COLOR_DATA (conflict_a), then remove those records + from the rest of data->update_cost_records list. */ + for (; curr != NULL; curr = next) + { + next = curr->next; + if (curr->hard_regno == hardreg) + { + update_costs_from_allocno (conflict_a, curr->hard_regno, + curr->divisor, false, false, + false); + /* Delete current record. */ + free_a_update_cost_record (&data->update_cost_records, + prev, curr); + } + else + prev = curr; + } + /* Propagate the disfavor of hardreg from conflict_a to the + allocnos connecting with conflict_a via copies. */ + update_costs_from_allocno (conflict_a, hardreg, + 1, false, true, true); + } + } +} + /* This function updates COSTS (decrease if DECR_P) for hard_registers of ACLASS by conflict costs of the unassigned allocnos connected by copies with allocnos in update_cost_queue. This @@ -1455,8 +1608,8 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass, int *conflict_costs; bool cont_p; enum reg_class another_aclass; - ira_allocno_t allocno, another_allocno, from; - ira_copy_t cp, next_cp; + ira_allocno_t allocno, another_allocno; + ira_copy_t cp, next_cp, from; while (get_next_update_cost (&allocno, &from, &divisor)) for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp) @@ -1474,7 +1627,15 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass, else gcc_unreachable (); - if (another_allocno == from) + if (from != NULL + && (another_allocno == from->first + || another_allocno == from->second)) + continue; + + /* For a = b * c; if there are copies (a, b) and (a, c), + it makes no sense to propagate cost from b to a then to c. */ + if (from != NULL + && from->insn == cp->insn) continue; another_aclass = ALLOCNO_CLASS (another_allocno); @@ -1505,6 +1666,16 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass, index = ira_class_hard_reg_index[aclass][hard_regno]; if (index < 0) continue; + /* If it is known that hard_regno will not be assigned to + another_allocno, don't use conflict_costs[i] of + another_allocno to update costs[i]. */ + if (!TEST_HARD_REG_BIT (ALLOCNO_COLOR_DATA (another_allocno) + ->profitable_hard_regs, + hard_regno) + || TEST_HARD_REG_BIT (ALLOCNO_COLOR_DATA (another_allocno) + ->new_conflict_hard_regs, + hard_regno)) + continue; cost = (int) ((unsigned) conflict_costs [i] * mult) / div; if (cost == 0) continue; @@ -1520,7 +1691,7 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass, * COST_HOP_DIVISOR * COST_HOP_DIVISOR * COST_HOP_DIVISOR)) - queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR); + queue_update_cost (another_allocno, cp, divisor * COST_HOP_DIVISOR); } } @@ -1613,7 +1784,9 @@ calculate_saved_nregs (int hard_regno, enum machine_mode mode) ira_assert (hard_regno >= 0); for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--) if (!allocated_hardreg_p[hard_regno + i] - && !TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + i) + && (!TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + i) + || (frame_pointer_partially_needed + && (hard_regno + i == HARD_FRAME_POINTER_REGNUM))) && !LOCAL_REGNO (hard_regno + i)) nregs++; return nregs; @@ -1784,6 +1957,16 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) k = ira_class_hard_reg_index[conflict_aclass][hard_regno]; if (k < 0) continue; + /* If it is known that hard_regno will not be assigned to + conflict_a, don't use conflict_costs[i] of conflict_a + to update full_costs[i]. */ + if (!TEST_HARD_REG_BIT (ALLOCNO_COLOR_DATA (conflict_a) + ->profitable_hard_regs, + hard_regno) + || TEST_HARD_REG_BIT (ALLOCNO_COLOR_DATA (conflict_a) + ->new_conflict_hard_regs, + hard_regno)) + continue; full_costs[j] -= conflict_costs[k]; } queue_update_cost (conflict_a, NULL, COST_HOP_DIVISOR); @@ -1864,6 +2047,8 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) ALLOCNO_ASSIGNED_P (a) = true; if (best_hard_regno >= 0) update_costs_from_copies (a, true, ! retry_p); + if (! retry_p && (best_hard_regno >= 0)) + restore_costs_from_conflicts (a, best_hard_regno); ira_assert (ALLOCNO_CLASS (a) == aclass); /* We don't need updated costs anymore: */ ira_free_allocno_updated_costs (a); diff --git a/gcc-4.9/gcc/ira-conflicts.c b/gcc-4.9/gcc/ira-conflicts.c index c0b4f0499..ba09c6a45 100644 --- a/gcc-4.9/gcc/ira-conflicts.c +++ b/gcc-4.9/gcc/ira-conflicts.c @@ -330,7 +330,8 @@ process_regs_for_copy (rtx reg1, rtx reg2, bool constraint_p, OP_NUM) which dies in the insn as if there were a move insn between them with frequency FREQ. */ static void -process_reg_shuffles (rtx reg, int op_num, int freq, bool *bound_p) +process_reg_shuffles (rtx reg, int op_num, int freq, bool *bound_p, + rtx insn) { int i; rtx another_reg; @@ -345,7 +346,7 @@ process_reg_shuffles (rtx reg, int op_num, int freq, bool *bound_p) || bound_p[i]) continue; - process_regs_for_copy (reg, another_reg, false, NULL_RTX, freq); + process_regs_for_copy (reg, another_reg, false, insn, freq); } } @@ -396,7 +397,7 @@ add_insn_allocno_copies (rtx insn) REG_P (operand) ? operand : SUBREG_REG (operand)) != NULL_RTX) - process_regs_for_copy (operand, dup, true, NULL_RTX, + process_regs_for_copy (operand, dup, true, insn, freq); } } @@ -412,7 +413,8 @@ add_insn_allocno_copies (rtx insn) the corresponding allocno copies. The cost will not correspond to a real move insn cost, so make the frequency smaller. */ - process_reg_shuffles (operand, i, freq < 8 ? 1 : freq / 8, bound_p); + process_reg_shuffles (operand, i, freq < 8 ? 1 : freq / 8, + bound_p, insn); } } diff --git a/gcc-4.9/gcc/ira-int.h b/gcc-4.9/gcc/ira-int.h index 19d86019a..98476fba3 100644 --- a/gcc-4.9/gcc/ira-int.h +++ b/gcc-4.9/gcc/ira-int.h @@ -135,6 +135,10 @@ struct ira_loop_tree_node /* Numbers of copies referred in the corresponding loop. */ bitmap local_copies; + + /* The flag only valid for flag_shrink_wrap_frame_pointer. + It is true when the loop could use fp as a free register. */ + bool fp_is_free; }; /* The root of the loop tree corresponding to the all function. */ @@ -568,6 +572,8 @@ struct ira_allocno_copy case the copy frequency is smaller than the corresponding insn execution frequency. */ rtx insn; + /* list of copies generated from the same insn. */ + ira_copy_t copy_list; /* All copies with the same allocno as FIRST are linked by the two following members. */ ira_copy_t prev_first_allocno_copy, next_first_allocno_copy; @@ -1008,6 +1014,7 @@ extern ira_copy_t ira_create_copy (ira_allocno_t, ira_allocno_t, int, bool, rtx, ira_loop_tree_node_t); extern ira_copy_t ira_add_allocno_copy (ira_allocno_t, ira_allocno_t, int, bool, rtx, ira_loop_tree_node_t); +extern ira_copy_t find_alternate_copy (ira_copy_t cp, ira_allocno_t connect); extern int *ira_allocate_cost_vector (reg_class_t); extern void ira_free_cost_vector (int *, reg_class_t); diff --git a/gcc-4.9/gcc/ira-lives.c b/gcc-4.9/gcc/ira-lives.c index 906d6db58..d41e3021b 100644 --- a/gcc-4.9/gcc/ira-lives.c +++ b/gcc-4.9/gcc/ira-lives.c @@ -737,6 +737,74 @@ mark_hard_reg_early_clobbers (rtx insn, bool live_p) return set_p; } +/* Record all the regs used in PX in DATA. */ +static int +record_reg_use (rtx *px, void *data) +{ + rtx x = *px; + sbitmap *pused = (sbitmap *)data; + + if (REG_P (x) && REGNO (x) >= FIRST_PSEUDO_REGISTER) + bitmap_set_bit (*pused, REGNO (x)); + return 0; +} + +/* If frame_pointer_partially_needed is on, and a pseudo reg is + refered in call insn directly, like "call *pseudo_reg", the + pseudo_reg cannot be given frame pointer, or else after frame + pointer shrinkwrapping transformation, the value of call target + register will be wrongly changed by fp setting of frame address. + Mark such pseudos conflicting with frame pointer register. */ + +static void +mark_ref_conflict_with_fp (rtx insn) +{ + sbitmap regno_set; + sbitmap_iterator bi; + df_ref *use_rec; + + regno_set = sbitmap_alloc (max_reg_num ()); + bitmap_clear (regno_set); + for (use_rec = DF_INSN_USES (insn); *use_rec; use_rec++) + { + int i, n; + unsigned regno; + rtx reg; + ira_allocno_t a; + + reg = DF_REF_REG (*use_rec); + if (GET_CODE (reg) == SUBREG) + reg = SUBREG_REG (reg); + regno = REGNO (reg); + if (REGNO (reg) < FIRST_PSEUDO_REGISTER) + continue; + + bitmap_set_bit (regno_set, regno); + + /* If regno is equivalent with a memory access, we should + mark all the regs used in the memory access to be conflicted + with frame pointer register. */ + if (ira_reg_equiv[regno].memory != NULL) + for_each_rtx (&ira_reg_equiv[regno].memory, record_reg_use, + ®no_set); + + EXECUTE_IF_SET_IN_BITMAP (regno_set, 0, regno, bi) + { + a = ira_curr_regno_allocno_map[regno]; + n = ALLOCNO_NUM_OBJECTS (a); + for (i = 0; i < n; i++) + { + ira_object_t obj = ALLOCNO_OBJECT (a, i); + SET_HARD_REG_BIT (OBJECT_CONFLICT_HARD_REGS (obj), + HARD_FRAME_POINTER_REGNUM); + SET_HARD_REG_BIT (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), + HARD_FRAME_POINTER_REGNUM); + } + } + } + sbitmap_free (regno_set); +} + /* Checks that CONSTRAINTS permits to use only one hard register. If it is so, the function returns the class of the hard register. Otherwise it returns NO_REGS. */ @@ -1258,6 +1326,9 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) if (call_p) { + if (frame_pointer_partially_needed) + mark_ref_conflict_with_fp (insn); + /* Try to find a SET in the CALL_INSN_FUNCTION_USAGE, and from there, try to find a pseudo that is live across the call but can be cheaply reconstructed from the return value. */ diff --git a/gcc-4.9/gcc/ira.c b/gcc-4.9/gcc/ira.c index c0e8a0d23..b2f58d1c4 100644 --- a/gcc-4.9/gcc/ira.c +++ b/gcc-4.9/gcc/ira.c @@ -1707,7 +1707,8 @@ ira_init (void) { free_register_move_costs (); setup_reg_mode_hard_regset (); - setup_alloc_regs (flag_omit_frame_pointer != 0); + setup_alloc_regs (flag_omit_frame_pointer != 0 + || flag_shrink_wrap_frame_pointer); setup_class_subset_and_memory_move_costs (); setup_reg_class_nregs (); setup_prohibited_class_mode_regs (); @@ -2391,12 +2392,19 @@ ira_setup_eliminable_regset (void) int i; static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS; #endif + bool can_omit_leaf_frame_pointer = targetm.can_omit_leaf_frame_pointer (); + frame_pointer_partially_needed = flag_shrink_wrap_frame_pointer + && crtl->sp_is_unchanging + && !can_omit_leaf_frame_pointer; + /* FIXME: If EXIT_IGNORE_STACK is set, we will not save and restore sp for alloca. So we can't eliminate the frame pointer in that case. At some point, we should improve this by emitting the sp-adjusting insns for this case. */ frame_pointer_needed - = (! flag_omit_frame_pointer + = ((!flag_omit_frame_pointer + && !frame_pointer_partially_needed + && !can_omit_leaf_frame_pointer) || (cfun->calls_alloca && EXIT_IGNORE_STACK) /* We need the frame pointer to catch stack overflow exceptions if the stack pointer is moving. */ @@ -2471,7 +2479,116 @@ ira_setup_eliminable_regset (void) #endif } - +/* Adjust frame pointer's alloc order. ALLOC_FIRST means giving fp + reg first allocation order. !ALLOC_FIRST means giving fp reg last + allocation order. */ + +void +adjust_fp_alloc_order (bool alloc_first) +{ + int cl, i, hard_regno; + + hard_regno = HARD_FRAME_POINTER_REGNUM; + for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--) + { + int fp_index; + + if (!TEST_HARD_REG_BIT (reg_class_contents[cl], hard_regno)) + continue; + + fp_index = ira_class_hard_reg_index[cl][hard_regno]; + if (alloc_first) + { + for (i = fp_index; i > 0; i--) + { + int hard_reg_tmp; + hard_reg_tmp = ira_class_hard_regs[cl][i-1]; + ira_class_hard_regs[cl][i] = hard_reg_tmp; + ira_class_hard_reg_index[cl][hard_reg_tmp] = i; + } + ira_class_hard_regs[cl][0] = hard_regno; + ira_class_hard_reg_index[cl][hard_regno] = 0; + } + else + { + int class_size = ira_class_hard_regs_num[cl]; + for (i = fp_index; i < class_size - 1; i++) + { + int hard_reg_tmp; + hard_reg_tmp = ira_class_hard_regs[cl][i+1]; + ira_class_hard_regs[cl][i] = hard_reg_tmp; + ira_class_hard_reg_index[cl][hard_reg_tmp] = i; + } + ira_class_hard_regs[cl][class_size - 1] = hard_regno; + ira_class_hard_reg_index[cl][hard_regno] = class_size - 1; + } + } + /* Do we have to reorder reg_alloc_order to make it consistent + with ira_class_hard_regs? */ +} + +/* Set frame pointer to be call used. */ +static void +set_fp_to_call_used () +{ + int fp = HARD_FRAME_POINTER_REGNUM; + call_used_regs[fp] = true; + SET_HARD_REG_BIT (call_used_reg_set, fp); +} + +/* Reset frame pointer to be call used. */ +static void +reset_fp_to_call_used () +{ + int fp = HARD_FRAME_POINTER_REGNUM; + call_used_regs[fp] = false; + CLEAR_HARD_REG_BIT (call_used_reg_set, fp); +} + +/* FP shrinkwrapping optimization: + Between -fomit-frame-pointer and -fno-omit-frame-pointer, + -fpartial-omit-frame-pointer is introduced to do fp shrinkwrapping. + In -fno-omit-frame-pointer case, fp is dedicately used to keep the + stack frame chain from caller to callee and enable fast stack + backtracing. In -fomit-frame-pointer case, fp is dedicately used as + a free callee-saved register. In -fpartial-omit-frame-pointer case, + fp has two fold usages: it is not only used as the register to pass + frame address of caller to callee, but also used as a caller-saved + register, so we can achieve of the best of both worlds. But these + two usages are conflicted with each other -- using fp as a free + register in a hot loop could inhibit frame address saving insn + (called as fp setting later) before a call inside the loop from being + promoted to the loop preheader. So loop regions in a function should + be partitioned for different fp usages. In IRA phase, there is a cost + evaluation function to partition all the loops to two sets: either use + fp freely or not. LRA will follow the evaluation decision in IRA. In + pro_and_epilogue phase, fp setting will be inserted immediately before + each call initially, and if IRA and LRA don't generate any normal fp + usage in a loop, fp shrinkwrapping could reduce the fp setting cost + by promoting it outside of the loop. */ + +void +ira_init_partial_omit_fp () +{ + /* If frame_pointer_needed is true, give up fp-shrinkwrapping. */ + if (frame_pointer_needed) + frame_pointer_partially_needed = false; + + if (frame_pointer_partially_needed) + { + set_fp_to_call_used (); +#ifdef REG_ALLOC_ORDER + /* In fp shrinkwrapping, fp is expected to be used in + the lowest priority in GENERAL_REGS. */ + adjust_fp_alloc_order (false); +#endif + } + else + { + reset_fp_to_call_used (); + return; + } +} /* Vector of substitutions of register numbers, used to map pseudo regs into hardware regs. @@ -5297,6 +5414,8 @@ ira (FILE *f) max_regno_before_ira = max_reg_num (); ira_setup_eliminable_regset (); + if (flag_shrink_wrap_frame_pointer) + ira_init_partial_omit_fp (); ira_overall_cost = ira_reg_cost = ira_mem_cost = 0; ira_load_cost = ira_store_cost = ira_shuffle_cost = 0; @@ -5522,6 +5641,9 @@ do_reload (void) obstack_free (&ira_obstack, NULL); #endif + if (frame_pointer_partially_needed) + SET_HARD_REG_BIT (regs_invalidated_by_call, HARD_FRAME_POINTER_REGNUM); + /* The code after the reload has changed so much that at this point we might as well just rescan everything. Note that df_rescan_all_insns is not going to help here because it does not diff --git a/gcc-4.9/gcc/java/ChangeLog b/gcc-4.9/gcc/java/ChangeLog index b9185f119..8dba8fa80 100644 --- a/gcc-4.9/gcc/java/ChangeLog +++ b/gcc-4.9/gcc/java/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-16 Release Manager * GCC 4.9.1 released. diff --git a/gcc-4.9/gcc/l-ipo.c b/gcc-4.9/gcc/l-ipo.c index 59dbd33fd..43c514696 100644 --- a/gcc-4.9/gcc/l-ipo.c +++ b/gcc-4.9/gcc/l-ipo.c @@ -47,6 +47,8 @@ along with GCC; see the file COPYING3. If not see #include "timevar.h" #include "vec.h" #include "params.h" +#include "rtl.h" +#include "varasm.h" unsigned ggc_total_memory; /* in KB */ @@ -1118,6 +1120,27 @@ cgraph_unify_type_alias_sets (void) htab_delete (type_hash_tab); } +/* Return true if DECL is an artificial function that we do not want + to promote and which may not be available in the primary module. + The sole exception is currently __tls_init. */ + +static bool +decl_artificial_nopromote (tree decl) +{ + if (!DECL_ARTIFICIAL (decl)) + return false; + + /* Handle the __tls_init function specially as we do want to promote it and + allow the aux module to be resolved to the version in the primary module. + We check if it is prefixed by __tls_init to catch it after promotion + as well from cgraph_is_aux_decl_external. */ + if (!strncmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)), "__tls_init", + 10)) + return false; + + return true; +} + /* Return true if NODE->decl from an auxiliary module has external definition (and therefore is not needed for expansion). */ @@ -1138,8 +1161,11 @@ cgraph_is_aux_decl_external (struct cgraph_node *node) /* Comdat or weak functions in aux modules are not external -- there is no guarantee that the definitition will be emitted - in the primary compilation of this auxiliary module. */ - if (DECL_COMDAT (decl) || DECL_WEAK (decl)) + in the primary compilation of this auxiliary module. + Functions marked artificial (e.g. an implicitly instantiated virtual + destructor) are also not guaranteed to be available in the primary module, + as they are not promoted by process_module_scope_static_func. */ + if (DECL_COMDAT (decl) || DECL_WEAK (decl) || decl_artificial_nopromote (decl)) return false; /* virtual functions won't be deleted in the primary module. */ @@ -1909,6 +1935,9 @@ promote_static_var_func (unsigned module_id, tree decl, bool is_extern) } varpool_link_node (node); insert_to_assembler_name_hash (node, false); + /* Possibly update the RTL name as well. */ + if (DECL_RTL_SET_P (decl)) + XSTR (XEXP (DECL_RTL (decl), 0), 0) = IDENTIFIER_POINTER (assemb_id); } if (is_extern) @@ -2014,7 +2043,7 @@ process_module_scope_static_func (struct cgraph_node *cnode) if (TREE_PUBLIC (decl) || !TREE_STATIC (decl) || DECL_EXTERNAL (decl) - || DECL_ARTIFICIAL (decl)) + || decl_artificial_nopromote (decl)) return; if (flag_ripa_no_promote_always_inline diff --git a/gcc-4.9/gcc/lra-assigns.c b/gcc-4.9/gcc/lra-assigns.c index f7bb86b21..b980c05f2 100644 --- a/gcc-4.9/gcc/lra-assigns.c +++ b/gcc-4.9/gcc/lra-assigns.c @@ -97,6 +97,15 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "lra-int.h" +/* Current iteration number of the pass and current iteration number + of the pass after the latest spill pass when any former reload + pseudo was spilled. */ +int lra_assignment_iter; +int lra_assignment_iter_after_spill; + +/* Flag of spilling former reload pseudos on this pass. */ +static bool former_reload_pseudo_spill_p; + /* Array containing corresponding values of function lra_get_allocno_class. It is used to speed up the code. */ static enum reg_class *regno_allocno_class_array; @@ -446,6 +455,39 @@ adjust_hard_regno_cost (int hard_regno, int incr) hard_regno_costs[hard_regno] += incr; } +/* If any insn referencing the REGNO is used in a BB marked as + BB_FP_IS_FREE, LRA could allocate fp to this REGNO. + + If REGNO is used in call insn, it is not allowed to assign + fp to the regno -- this is to avoid call (*fp). Or else after + framepointer shrinkwrapping transformation, the value of call + target register will be wrongly changed by fp setting of + frame address. */ + +static bool +fp_is_allowed_p (int regno) +{ + unsigned int uid; + bitmap_iterator bi; + basic_block bb; + bool allowed = false; + + EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi) + { + rtx insn; + insn = lra_insn_recog_data[uid]->insn; + if (insn && !DEBUG_INSN_P (insn)) + { + if (CALL_P (insn)) + return false; + bb = BLOCK_FOR_INSN (insn); + if (bb->flags & BB_FP_IS_FREE) + allowed = true; + } + } + return allowed; +} + /* Try to find a free hard register for pseudo REGNO. Return the hard register on success and set *COST to the cost of using that register. (If several registers have equal cost, the one with @@ -476,6 +518,9 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno, HARD_REG_SET impossible_start_hard_regs, available_regs; COPY_HARD_REG_SET (conflict_set, lra_no_alloc_regs); + /* Check whether fp is allowed for this regno. */ + if (frame_pointer_partially_needed && !fp_is_allowed_p (regno)) + SET_HARD_REG_BIT (conflict_set, HARD_FRAME_POINTER_REGNUM); rclass = regno_allocno_class_array[regno]; rclass_intersect_p = ira_reg_classes_intersect_p[rclass]; curr_hard_regno_costs_check++; @@ -617,7 +662,11 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno, for (j = 0; j < hard_regno_nregs[hard_regno][PSEUDO_REGNO_MODE (regno)]; j++) - if (! TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + j) + if ((! TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + j) + /* fp has no less cost than other callee saved reg if + frame_pointer_partially_needed is true. */ + || (frame_pointer_partially_needed + && (hard_regno + j == HARD_FRAME_POINTER_REGNUM))) && ! df_regs_ever_live_p (hard_regno + j)) /* It needs save restore. */ hard_regno_costs[hard_regno] @@ -992,6 +1041,8 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p) /* Spill: */ EXECUTE_IF_SET_IN_BITMAP (&best_spill_pseudos_bitmap, 0, spill_regno, bi) { + if ((int) spill_regno >= lra_constraint_new_regno_start) + former_reload_pseudo_spill_p = true; if (lra_dump_file != NULL) fprintf (lra_dump_file, " Spill %sr%d(hr=%d, freq=%d) for r%d\n", pseudo_prefix_title (spill_regno), @@ -1101,6 +1152,8 @@ setup_live_pseudos_and_spill_after_risky_transforms (bitmap j++) lra_hard_reg_usage[hard_regno + j] -= lra_reg_info[regno].freq; reg_renumber[regno] = -1; + if (regno >= lra_constraint_new_regno_start) + former_reload_pseudo_spill_p = true; if (lra_dump_file != NULL) fprintf (lra_dump_file, " Spill r%d after risky transformations\n", regno); @@ -1361,7 +1414,10 @@ assign_by_spills (void) EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno) { if ((int) conflict_regno >= lra_constraint_new_regno_start) - sorted_pseudos[nfails++] = conflict_regno; + { + sorted_pseudos[nfails++] = conflict_regno; + former_reload_pseudo_spill_p = true; + } if (lra_dump_file != NULL) fprintf (lra_dump_file, " Spill %s r%d(hr=%d, freq=%d)\n", pseudo_prefix_title (conflict_regno), conflict_regno, @@ -1449,12 +1505,17 @@ lra_assign (void) int max_regno = max_reg_num (); timevar_push (TV_LRA_ASSIGN); + lra_assignment_iter++; + if (lra_dump_file != NULL) + fprintf (lra_dump_file, "\n********** Assignment #%d: **********\n\n", + lra_assignment_iter); init_lives (); sorted_pseudos = XNEWVEC (int, max_regno); sorted_reload_pseudos = XNEWVEC (int, max_regno); regno_allocno_class_array = XNEWVEC (enum reg_class, max_regno); for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) regno_allocno_class_array[i] = lra_get_allocno_class (i); + former_reload_pseudo_spill_p = false; init_regno_assign_info (); bitmap_initialize (&all_spilled_pseudos, ®_obstack); create_live_range_start_chains (); @@ -1501,5 +1562,11 @@ lra_assign (void) free (sorted_reload_pseudos); finish_lives (); timevar_pop (TV_LRA_ASSIGN); + if (former_reload_pseudo_spill_p) + lra_assignment_iter_after_spill++; + if (lra_assignment_iter_after_spill > LRA_MAX_ASSIGNMENT_ITERATION_NUMBER) + internal_error + ("Maximum number of LRA assignment passes is achieved (%d)\n", + LRA_MAX_ASSIGNMENT_ITERATION_NUMBER); return no_spills_p; } diff --git a/gcc-4.9/gcc/lra-constraints.c b/gcc-4.9/gcc/lra-constraints.c index 6d13e9d74..c55cefecb 100644 --- a/gcc-4.9/gcc/lra-constraints.c +++ b/gcc-4.9/gcc/lra-constraints.c @@ -4020,10 +4020,6 @@ loc_equivalence_callback (rtx loc, const_rtx, void *data) /* The current iteration number of this LRA pass. */ int lra_constraint_iter; -/* The current iteration number of this LRA pass after the last spill - pass. */ -int lra_constraint_iter_after_spill; - /* True if we substituted equiv which needs checking register allocation correctness because the equivalent value contains allocatable hard registers or when we restore multi-register @@ -4169,11 +4165,6 @@ lra_constraints (bool first_p) if (lra_dump_file != NULL) fprintf (lra_dump_file, "\n********** Local #%d: **********\n\n", lra_constraint_iter); - lra_constraint_iter_after_spill++; - if (lra_constraint_iter_after_spill > LRA_MAX_CONSTRAINT_ITERATION_NUMBER) - internal_error - ("Maximum number of LRA constraint passes is achieved (%d)\n", - LRA_MAX_CONSTRAINT_ITERATION_NUMBER); changed_p = false; lra_risky_transformations_p = false; new_insn_uid_start = get_max_uid (); diff --git a/gcc-4.9/gcc/lra-int.h b/gcc-4.9/gcc/lra-int.h index b2f5cf7d0..726208747 100644 --- a/gcc-4.9/gcc/lra-int.h +++ b/gcc-4.9/gcc/lra-int.h @@ -244,9 +244,10 @@ typedef struct lra_insn_recog_data *lra_insn_recog_data_t; #define LRA_LOSER_COST_FACTOR 6 #define LRA_MAX_REJECT 600 -/* Maximum allowed number of constraint pass iterations after the last - spill pass. It is for preventing LRA cycling in a bug case. */ -#define LRA_MAX_CONSTRAINT_ITERATION_NUMBER 30 +/* Maximum allowed number of assignment pass iterations after the + latest spill pass when any former reload pseudo was spilled. It is + for preventing LRA cycling in a bug case. */ +#define LRA_MAX_ASSIGNMENT_ITERATION_NUMBER 30 /* The maximal number of inheritance/split passes in LRA. It should be more 1 in order to perform caller saves transformations and much @@ -259,7 +260,7 @@ typedef struct lra_insn_recog_data *lra_insn_recog_data_t; #define LRA_MAX_INHERITANCE_PASSES 2 #if LRA_MAX_INHERITANCE_PASSES <= 0 \ - || LRA_MAX_INHERITANCE_PASSES >= LRA_MAX_CONSTRAINT_ITERATION_NUMBER - 8 + || LRA_MAX_INHERITANCE_PASSES >= LRA_MAX_ASSIGNMENT_ITERATION_NUMBER - 8 #error wrong LRA_MAX_INHERITANCE_PASSES value #endif @@ -323,7 +324,6 @@ extern void lra_init_equiv (void); extern int lra_constraint_offset (int, enum machine_mode); extern int lra_constraint_iter; -extern int lra_constraint_iter_after_spill; extern bool lra_risky_transformations_p; extern int lra_inheritance_iter; extern int lra_undo_inheritance_iter; @@ -360,6 +360,8 @@ extern void lra_setup_reload_pseudo_preferenced_hard_reg (int, int, int); /* lra-assigns.c: */ +extern int lra_assignment_iter; +extern int lra_assignment_iter_after_spill; extern void lra_setup_reg_renumber (int, int, bool); extern bool lra_assign (void); diff --git a/gcc-4.9/gcc/lra.c b/gcc-4.9/gcc/lra.c index c1b92d8ee..69b08dc24 100644 --- a/gcc-4.9/gcc/lra.c +++ b/gcc-4.9/gcc/lra.c @@ -2295,8 +2295,8 @@ lra (FILE *f) lra_in_progress = 1; - lra_live_range_iter = lra_coalesce_iter = 0; - lra_constraint_iter = lra_constraint_iter_after_spill = 0; + lra_live_range_iter = lra_coalesce_iter = lra_constraint_iter = 0; + lra_assignment_iter = lra_assignment_iter_after_spill = 0; lra_inheritance_iter = lra_undo_inheritance_iter = 0; setup_reg_spill_flag (); @@ -2419,7 +2419,7 @@ lra (FILE *f) lra_eliminate (false, false); lra_constraint_new_regno_start = max_reg_num (); lra_constraint_new_insn_uid_start = get_max_uid (); - lra_constraint_iter_after_spill = 0; + lra_assignment_iter_after_spill = 0; } restore_scratches (); lra_eliminate (true, false); diff --git a/gcc-4.9/gcc/lto-cgraph.c b/gcc-4.9/gcc/lto-cgraph.c index 173067f65..9e6915f39 100644 --- a/gcc-4.9/gcc/lto-cgraph.c +++ b/gcc-4.9/gcc/lto-cgraph.c @@ -793,7 +793,8 @@ compute_ltrans_boundary (lto_symtab_encoder_t in_encoder) if (DECL_ABSTRACT_ORIGIN (node->decl)) { struct cgraph_node *origin_node - = cgraph_get_node (DECL_ABSTRACT_ORIGIN (node->decl)); + = cgraph_get_create_node (DECL_ABSTRACT_ORIGIN (node->decl)); + origin_node->used_as_abstract_origin = true; add_node_to (encoder, origin_node, true); } } diff --git a/gcc-4.9/gcc/lto-streamer-out.c b/gcc-4.9/gcc/lto-streamer-out.c index b193d730d..6b5df1a61 100644 --- a/gcc-4.9/gcc/lto-streamer-out.c +++ b/gcc-4.9/gcc/lto-streamer-out.c @@ -2077,7 +2077,10 @@ lto_output (void) #endif decl_state = lto_new_out_decl_state (); lto_push_out_decl_state (decl_state); - if (gimple_has_body_p (node->decl) || !flag_wpa) + if (gimple_has_body_p (node->decl) || !flag_wpa + /* Thunks have no body but they may be synthetized + at WPA time. */ + || DECL_ARGUMENTS (node->decl)) output_function (node); else copy_function (node); diff --git a/gcc-4.9/gcc/lto/ChangeLog b/gcc-4.9/gcc/lto/ChangeLog index 6c6ea2bdd..8aed89086 100644 --- a/gcc-4.9/gcc/lto/ChangeLog +++ b/gcc-4.9/gcc/lto/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-08-15 Bin Cheng Backport from mainline diff --git a/gcc-4.9/gcc/objc/ChangeLog b/gcc-4.9/gcc/objc/ChangeLog index 2443c6197..507e32b16 100644 --- a/gcc-4.9/gcc/objc/ChangeLog +++ b/gcc-4.9/gcc/objc/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-16 Release Manager * GCC 4.9.1 released. diff --git a/gcc-4.9/gcc/objcp/ChangeLog b/gcc-4.9/gcc/objcp/ChangeLog index cba09a4be..307fcaa6c 100644 --- a/gcc-4.9/gcc/objcp/ChangeLog +++ b/gcc-4.9/gcc/objcp/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-16 Release Manager * GCC 4.9.1 released. diff --git a/gcc-4.9/gcc/omp-low.c b/gcc-4.9/gcc/omp-low.c index 1753cad45..6d9206c95 100644 --- a/gcc-4.9/gcc/omp-low.c +++ b/gcc-4.9/gcc/omp-low.c @@ -204,6 +204,7 @@ static int taskreg_nesting_level; static int target_nesting_level; static struct omp_region *root_omp_region; static bitmap task_shared_vars; +static vec taskreg_contexts; static void scan_omp (gimple_seq *, omp_context *); static tree scan_omp_1_op (tree *, int *, void *); @@ -1632,7 +1633,8 @@ scan_sharing_clauses (tree clauses, omp_context *ctx) #pragma omp target data, there is nothing to map for those. */ if (gimple_omp_target_kind (ctx->stmt) == GF_OMP_TARGET_KIND_DATA - && !POINTER_TYPE_P (TREE_TYPE (decl))) + && !POINTER_TYPE_P (TREE_TYPE (decl)) + && !OMP_CLAUSE_MAP_ZERO_BIAS_ARRAY_SECTION (c)) break; } if (DECL_P (decl)) @@ -2024,6 +2026,7 @@ scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx) } ctx = new_omp_context (stmt, outer_ctx); + taskreg_contexts.safe_push (ctx); if (taskreg_nesting_level > 1) ctx->is_nested = true; ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); @@ -2043,11 +2046,6 @@ scan_omp_parallel (gimple_stmt_iterator *gsi, omp_context *outer_ctx) if (TYPE_FIELDS (ctx->record_type) == NULL) ctx->record_type = ctx->receiver_decl = NULL; - else - { - layout_type (ctx->record_type); - fixup_child_record_type (ctx); - } } /* Scan an OpenMP task directive. */ @@ -2058,7 +2056,6 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx) omp_context *ctx; tree name, t; gimple stmt = gsi_stmt (*gsi); - location_t loc = gimple_location (stmt); /* Ignore task directives with empty bodies. */ if (optimize > 0 @@ -2069,6 +2066,7 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx) } ctx = new_omp_context (stmt, outer_ctx); + taskreg_contexts.safe_push (ctx); if (taskreg_nesting_level > 1) ctx->is_nested = true; ctx->field_map = splay_tree_new (splay_tree_compare_pointers, 0, 0); @@ -2106,8 +2104,71 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx) t = build_int_cst (long_integer_type_node, 1); gimple_omp_task_set_arg_align (stmt, t); } +} + + +/* If any decls have been made addressable during scan_omp, + adjust their fields if needed, and layout record types + of parallel/task constructs. */ + +static void +finish_taskreg_scan (omp_context *ctx) +{ + if (ctx->record_type == NULL_TREE) + return; + + /* If any task_shared_vars were needed, verify all + OMP_CLAUSE_SHARED clauses on GIMPLE_OMP_{PARALLEL,TASK} + statements if use_pointer_for_field hasn't changed + because of that. If it did, update field types now. */ + if (task_shared_vars) + { + tree c; + + for (c = gimple_omp_taskreg_clauses (ctx->stmt); + c; c = OMP_CLAUSE_CHAIN (c)) + if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_SHARED) + { + tree decl = OMP_CLAUSE_DECL (c); + + /* Global variables don't need to be copied, + the receiver side will use them directly. */ + if (is_global_var (maybe_lookup_decl_in_outer_ctx (decl, ctx))) + continue; + if (!bitmap_bit_p (task_shared_vars, DECL_UID (decl)) + || !use_pointer_for_field (decl, ctx)) + continue; + tree field = lookup_field (decl, ctx); + if (TREE_CODE (TREE_TYPE (field)) == POINTER_TYPE + && TREE_TYPE (TREE_TYPE (field)) == TREE_TYPE (decl)) + continue; + TREE_TYPE (field) = build_pointer_type (TREE_TYPE (decl)); + TREE_THIS_VOLATILE (field) = 0; + DECL_USER_ALIGN (field) = 0; + DECL_ALIGN (field) = TYPE_ALIGN (TREE_TYPE (field)); + if (TYPE_ALIGN (ctx->record_type) < DECL_ALIGN (field)) + TYPE_ALIGN (ctx->record_type) = DECL_ALIGN (field); + if (ctx->srecord_type) + { + tree sfield = lookup_sfield (decl, ctx); + TREE_TYPE (sfield) = TREE_TYPE (field); + TREE_THIS_VOLATILE (sfield) = 0; + DECL_USER_ALIGN (sfield) = 0; + DECL_ALIGN (sfield) = DECL_ALIGN (field); + if (TYPE_ALIGN (ctx->srecord_type) < DECL_ALIGN (sfield)) + TYPE_ALIGN (ctx->srecord_type) = DECL_ALIGN (sfield); + } + } + } + + if (gimple_code (ctx->stmt) == GIMPLE_OMP_PARALLEL) + { + layout_type (ctx->record_type); + fixup_child_record_type (ctx); + } else { + location_t loc = gimple_location (ctx->stmt); tree *p, vla_fields = NULL_TREE, *q = &vla_fields; /* Move VLA fields to the end. */ p = &TYPE_FIELDS (ctx->record_type); @@ -2127,12 +2188,12 @@ scan_omp_task (gimple_stmt_iterator *gsi, omp_context *outer_ctx) fixup_child_record_type (ctx); if (ctx->srecord_type) layout_type (ctx->srecord_type); - t = fold_convert_loc (loc, long_integer_type_node, - TYPE_SIZE_UNIT (ctx->record_type)); - gimple_omp_task_set_arg_size (stmt, t); + tree t = fold_convert_loc (loc, long_integer_type_node, + TYPE_SIZE_UNIT (ctx->record_type)); + gimple_omp_task_set_arg_size (ctx->stmt, t); t = build_int_cst (long_integer_type_node, TYPE_ALIGN_UNIT (ctx->record_type)); - gimple_omp_task_set_arg_align (stmt, t); + gimple_omp_task_set_arg_align (ctx->stmt, t); } } @@ -9827,6 +9888,9 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) continue; } + unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar)); + if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign) + talign = DECL_ALIGN_UNIT (ovar); if (nc) { tree var = lookup_decl_in_outer_ctx (ovar, ctx); @@ -9841,6 +9905,7 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) = create_tmp_var (TREE_TYPE (TREE_TYPE (x)), NULL); mark_addressable (avar); gimplify_assign (avar, build_fold_addr_expr (var), &ilist); + talign = DECL_ALIGN_UNIT (avar); avar = build_fold_addr_expr (avar); gimplify_assign (x, avar, &ilist); } @@ -9893,9 +9958,6 @@ lower_omp_target (gimple_stmt_iterator *gsi_p, omp_context *ctx) default: gcc_unreachable (); } - unsigned int talign = TYPE_ALIGN_UNIT (TREE_TYPE (ovar)); - if (DECL_P (ovar) && DECL_ALIGN_UNIT (ovar) > talign) - talign = DECL_ALIGN_UNIT (ovar); talign = ceil_log2 (talign); tkind |= talign << 3; CONSTRUCTOR_APPEND_ELT (vkind, purpose, @@ -10269,6 +10331,8 @@ static unsigned int execute_lower_omp (void) { gimple_seq body; + int i; + omp_context *ctx; /* This pass always runs, to provide PROP_gimple_lomp. But there is nothing to do unless -fopenmp is given. */ @@ -10281,6 +10345,9 @@ execute_lower_omp (void) body = gimple_body (current_function_decl); scan_omp (&body, NULL); gcc_assert (taskreg_nesting_level == 0); + FOR_EACH_VEC_ELT (taskreg_contexts, i, ctx) + finish_taskreg_scan (ctx); + taskreg_contexts.release (); if (all_contexts->root) { @@ -11115,24 +11182,24 @@ simd_clone_adjust_return_type (struct cgraph_node *node) if (orig_rettype == void_type_node) return NULL_TREE; TREE_TYPE (fndecl) = build_distinct_type_copy (TREE_TYPE (fndecl)); - if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl))) - || POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (fndecl)))) + t = TREE_TYPE (TREE_TYPE (fndecl)); + if (INTEGRAL_TYPE_P (t) || POINTER_TYPE_P (t)) veclen = node->simdclone->vecsize_int; else veclen = node->simdclone->vecsize_float; - veclen /= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl)))); + veclen /= GET_MODE_BITSIZE (TYPE_MODE (t)); if (veclen > node->simdclone->simdlen) veclen = node->simdclone->simdlen; + if (POINTER_TYPE_P (t)) + t = pointer_sized_int_node; if (veclen == node->simdclone->simdlen) - TREE_TYPE (TREE_TYPE (fndecl)) - = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), - node->simdclone->simdlen); + t = build_vector_type (t, node->simdclone->simdlen); else { - t = build_vector_type (TREE_TYPE (TREE_TYPE (fndecl)), veclen); + t = build_vector_type (t, veclen); t = build_array_type_nelts (t, node->simdclone->simdlen / veclen); - TREE_TYPE (TREE_TYPE (fndecl)) = t; } + TREE_TYPE (TREE_TYPE (fndecl)) = t; if (!node->definition) return NULL_TREE; @@ -11221,7 +11288,10 @@ simd_clone_adjust_argument_types (struct cgraph_node *node) if (veclen > node->simdclone->simdlen) veclen = node->simdclone->simdlen; adj.arg_prefix = "simd"; - adj.type = build_vector_type (parm_type, veclen); + if (POINTER_TYPE_P (parm_type)) + adj.type = build_vector_type (pointer_sized_int_node, veclen); + else + adj.type = build_vector_type (parm_type, veclen); node->simdclone->args[i].vector_type = adj.type; for (j = veclen; j < node->simdclone->simdlen; j += veclen) { @@ -11262,7 +11332,10 @@ simd_clone_adjust_argument_types (struct cgraph_node *node) veclen /= GET_MODE_BITSIZE (TYPE_MODE (base_type)); if (veclen > node->simdclone->simdlen) veclen = node->simdclone->simdlen; - adj.type = build_vector_type (base_type, veclen); + if (POINTER_TYPE_P (base_type)) + adj.type = build_vector_type (pointer_sized_int_node, veclen); + else + adj.type = build_vector_type (base_type, veclen); adjustments.safe_push (adj); for (j = veclen; j < node->simdclone->simdlen; j += veclen) @@ -11436,9 +11509,22 @@ ipa_simd_modify_stmt_ops (tree *tp, int *walk_subtrees, void *data) if (tp != orig_tp) { repl = build_fold_addr_expr (repl); - gimple stmt - = gimple_build_assign (make_ssa_name (TREE_TYPE (repl), NULL), repl); - repl = gimple_assign_lhs (stmt); + gimple stmt; + if (is_gimple_debug (info->stmt)) + { + tree vexpr = make_node (DEBUG_EXPR_DECL); + stmt = gimple_build_debug_source_bind (vexpr, repl, NULL); + DECL_ARTIFICIAL (vexpr) = 1; + TREE_TYPE (vexpr) = TREE_TYPE (repl); + DECL_MODE (vexpr) = TYPE_MODE (TREE_TYPE (repl)); + repl = vexpr; + } + else + { + stmt = gimple_build_assign (make_ssa_name (TREE_TYPE (repl), + NULL), repl); + repl = gimple_assign_lhs (stmt); + } gimple_stmt_iterator gsi = gsi_for_stmt (info->stmt); gsi_insert_before (&gsi, stmt, GSI_SAME_STMT); *orig_tp = repl; diff --git a/gcc-4.9/gcc/opts-global.c b/gcc-4.9/gcc/opts-global.c index e115c9bf2..425c3c0b2 100644 --- a/gcc-4.9/gcc/opts-global.c +++ b/gcc-4.9/gcc/opts-global.c @@ -44,6 +44,9 @@ along with GCC; see the file COPYING3. If not see #include "params.h" #include "l-ipo.h" #include "context.h" +#include "xregex.h" +#include "attribs.h" +#include "stringpool.h" typedef const char *const_char_p; /* For DEF_VEC_P. */ @@ -53,6 +56,13 @@ static vec ignored_options; const char **in_fnames; unsigned num_in_fnames; +static struct reg_func_attr_patterns +{ + regex_t r; + const char *attribute; + struct reg_func_attr_patterns *next; +} *reg_func_attr_patterns; + /* Return a malloced slash-separated list of languages in MASK. */ static char * @@ -82,6 +92,62 @@ write_langs (unsigned int mask) return result; } +/* Add strings like attribute_str:pattern... to attribute pattern list. */ + +static void +add_attribute_pattern (const char *arg) +{ + char *tmp; + char *pattern_str; + struct reg_func_attr_patterns *one_pat; + int ec; + + /* We never free this string. */ + tmp = xstrdup (arg); + + pattern_str = strchr (tmp, ':'); + if (!pattern_str) + error ("invalid pattern in -ffunction-attribute-list option: %qs", tmp); + + *pattern_str = '\0'; + pattern_str ++; + + one_pat = XCNEW (struct reg_func_attr_patterns); + one_pat->next = reg_func_attr_patterns; + one_pat->attribute = tmp; + reg_func_attr_patterns = one_pat; + if ((ec= regcomp (&one_pat->r, pattern_str, REG_EXTENDED|REG_NOSUB) != 0)) + { + char err[100]; + regerror (ec, &one_pat->r, err, 99); + error ("invalid pattern in -ffunction-attribute-list option: %qs: %qs", + pattern_str, err); + } +} + +/* Match FNDECL's name with user specified patterns, and add attributes + to FNDECL. */ + +void +pattern_match_function_attributes (tree fndecl) +{ + const char *name; + struct reg_func_attr_patterns *one_pat; + + if (!fndecl) + return; + + if (!reg_func_attr_patterns) + return; + + name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)); + + for (one_pat = reg_func_attr_patterns; one_pat; one_pat = one_pat->next) + if (regexec (&one_pat->r, name, 0, NULL, 0) == 0) + decl_attributes (&fndecl, tree_cons ( + get_identifier (one_pat->attribute), NULL, NULL), 0); +} + /* Complain that switch DECODED does not apply to this front end (mask LANG_MASK). */ @@ -449,6 +515,10 @@ handle_common_deferred_options (void) set_random_seed (opt->arg); break; + case OPT_ffunction_attribute_list_: + add_attribute_pattern (opt->arg); + break; + case OPT_fstack_limit: /* The real switch is -fno-stack-limit. */ if (!opt->value) diff --git a/gcc-4.9/gcc/opts.c b/gcc-4.9/gcc/opts.c index a588d2ec8..ac589412c 100644 --- a/gcc-4.9/gcc/opts.c +++ b/gcc-4.9/gcc/opts.c @@ -485,7 +485,6 @@ static const struct default_options default_options_table[] = { OPT_LEVELS_2_PLUS, OPT_ftree_pre, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_ftree_switch_conversion, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fipa_cp, NULL, 1 }, - { OPT_LEVELS_2_PLUS, OPT_fdevirtualize, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fdevirtualize_speculatively, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_fipa_sra, NULL, 1 }, { OPT_LEVELS_2_PLUS, OPT_falign_loops, NULL, 1 }, @@ -870,6 +869,27 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, opts->x_param_values, opts_set->x_param_values); } + if (opts->x_profile_arc_flag + || opts->x_flag_branch_probabilities) + { + maybe_set_param_value + (PARAM_EARLY_INLINER_MAX_ITERATIONS, 2, + opts->x_param_values, opts_set->x_param_values); + } + + if (!(opts->x_flag_auto_profile + || (opts->x_profile_arc_flag || opts->x_flag_branch_probabilities))) + { + /* In plain mode, we relax the limit to allow funcs not declared as + inline but with big_speedup or good inline hints to be inline candidates + in plain mode. This change will improve some performance but also + increase code size. PARAM_INLINE_UNIT_GROWTH is used to trim down code + size without affecting the improved performance. */ + maybe_set_param_value + (PARAM_INLINE_UNIT_GROWTH, 25, + opts->x_param_values, opts_set->x_param_values); + } + /* Tune vectorization related parametees according to cost model. */ if (opts->x_flag_vect_cost_model == VECT_COST_MODEL_CHEAP) { @@ -907,6 +927,40 @@ finish_options (struct gcc_options *opts, struct gcc_options *opts_set, /* Turn on -ffunction-sections when -freorder-functions=* is used. */ if (opts->x_flag_reorder_functions > 1) opts->x_flag_function_sections = 1; + + /* LIPO module grouping depends on the memory consumed by the profile-gen + parsing phase, recorded in a per-module ggc_memory field of the module + info struct. This will be higher when debug generation is on via + -g/-gmlt, which causes the FE to generate debug structures that will + increase the ggc_total_memory. This could in theory cause the module + groups to be slightly more conservative. Disable -g/-gmlt under + -fripa -fprofile-generate, but provide an option to override this + in case we actually need to debug an instrumented binary. */ + if (opts->x_profile_arc_flag + && opts->x_flag_dyn_ipa + && opts->x_debug_info_level != DINFO_LEVEL_NONE + && !opts->x_flag_dyn_ipa_allow_debug) + { + inform (loc, + "Debug generation via -g option disabled under -fripa " + "-fprofile-generate (use -fripa-allow-debug to override)"); + set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, "0", opts, opts_set, + loc); + } + + /* Userspace and kernel ASan conflict with each other and with TSan. */ + + if ((flag_sanitize & SANITIZE_USER_ADDRESS) + && (flag_sanitize & SANITIZE_KERNEL_ADDRESS)) + error_at (loc, + "-fsanitize=address is incompatible with " + "-fsanitize=kernel-address"); + + if ((flag_sanitize & SANITIZE_ADDRESS) + && (flag_sanitize & SANITIZE_THREAD)) + error_at (loc, + "-fsanitize=address and -fsanitize=kernel-address " + "are incompatible with -fsanitize=thread"); } #define LEFT_COLUMN 27 @@ -1562,7 +1616,10 @@ common_handle_option (struct gcc_options *opts, size_t len; } spec[] = { - { "address", SANITIZE_ADDRESS, sizeof "address" - 1 }, + { "address", SANITIZE_ADDRESS | SANITIZE_USER_ADDRESS, + sizeof "address" - 1 }, + { "kernel-address", SANITIZE_ADDRESS | SANITIZE_KERNEL_ADDRESS, + sizeof "kernel-address" - 1 }, { "thread", SANITIZE_THREAD, sizeof "thread" - 1 }, { "leak", SANITIZE_LEAK, sizeof "leak" - 1 }, { "shift", SANITIZE_SHIFT, sizeof "shift" - 1 }, @@ -1623,6 +1680,25 @@ common_handle_option (struct gcc_options *opts, the null pointer checks. */ if (flag_sanitize & SANITIZE_NULL) opts->x_flag_delete_null_pointer_checks = 0; + + /* Kernel ASan implies normal ASan but does not yet support + all features. */ + if (flag_sanitize & SANITIZE_KERNEL_ADDRESS) + { + maybe_set_param_value (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, 0, + opts->x_param_values, + opts_set->x_param_values); + maybe_set_param_value (PARAM_ASAN_GLOBALS, 0, + opts->x_param_values, + opts_set->x_param_values); + maybe_set_param_value (PARAM_ASAN_STACK, 0, + opts->x_param_values, + opts_set->x_param_values); + maybe_set_param_value (PARAM_ASAN_USE_AFTER_RETURN, 0, + opts->x_param_values, + opts_set->x_param_values); + } + break; } @@ -1887,6 +1963,10 @@ common_handle_option (struct gcc_options *opts, /* Deferred. */ break; + case OPT_ffunction_attribute_list_: + /* Deferred. */ + break; + case OPT_fsched_verbose_: #ifdef INSN_SCHEDULING /* Handled with Var in common.opt. */ @@ -1970,6 +2050,12 @@ common_handle_option (struct gcc_options *opts, set_debug_level (DWARF2_DEBUG, false, "", opts, opts_set, loc); break; + case OPT_gline_tables_only: + set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, "1", opts, opts_set, + loc); + opts->x_debug_line_tables_only = 1; + break; + case OPT_gsplit_dwarf: set_debug_level (NO_DEBUG, DEFAULT_GDB_EXTENSIONS, "", opts, opts_set, loc); @@ -2167,6 +2253,7 @@ set_debug_level (enum debug_info_type type, int extended, const char *arg, struct gcc_options *opts, struct gcc_options *opts_set, location_t loc) { + opts->x_debug_line_tables_only = 0; opts->x_use_gnu_debug_info_extensions = extended; if (type == NO_DEBUG) diff --git a/gcc-4.9/gcc/opts.h b/gcc-4.9/gcc/opts.h index 74e7622db..790be5375 100644 --- a/gcc-4.9/gcc/opts.h +++ b/gcc-4.9/gcc/opts.h @@ -417,6 +417,7 @@ extern bool opt_enum_arg_to_value (size_t opt_index, const char *arg, int *value, unsigned int lang_mask); extern void write_compilation_info_to_asm (void); extern void write_compilation_flags_to_asm (void); +extern void pattern_match_function_attributes (tree); extern void set_profile_use_options (struct gcc_options *, struct gcc_options *, bool, bool); #endif diff --git a/gcc-4.9/gcc/params.def b/gcc-4.9/gcc/params.def index f8d2a9cd1..3d2c913fd 100644 --- a/gcc-4.9/gcc/params.def +++ b/gcc-4.9/gcc/params.def @@ -78,6 +78,11 @@ DEFPARAM (PARAM_MAX_INLINE_INSNS_AUTO, "The maximum number of instructions when automatically inlining", 40, 0, 0) +DEFPARAM (PARAM_MAX_GROWTH_AUTO_INLINE_FUNC, + "max-growth-auto-inline-func", + "The maximum size growth when inlining functions without inline declared in plain mode", + 25, 0, 0) + DEFPARAM (PARAM_MAX_INLINE_INSNS_RECURSIVE, "max-inline-insns-recursive", "The maximum number of instructions inline function can grow to via recursive inlining", @@ -343,7 +348,7 @@ DEFPARAM(PARAM_MAX_COMPLETELY_PEELED_INSNS, DEFPARAM(PARAM_MAX_DEFAULT_COMPLETELY_PEELED_INSNS, "max-default-completely-peeled-insns", "The maximum number of insns of a completely peeled loop", - 200, 0, 0) + 100, 0, 0) /* The maximum number of peelings of a single loop that is peeled completely. */ DEFPARAM(PARAM_MAX_COMPLETELY_PEEL_TIMES, "max-completely-peel-times", @@ -454,6 +459,11 @@ DEFPARAM (PARAM_ALIGN_LOOP_ITERATIONS, "Loops iterating at least selected number of iterations will get loop alignement.", 4, 0, 0) +DEFPARAM (PARAM_ALIGN_LOOP_SIZE, + "align-loop-size", + "For loop small enough, try to align them more strictly.", + 10, 0, 0) + /* For guessed profiles, the loops having unknown number of iterations are predicted to iterate relatively few (10) times at average. For functions containing one loop with large known number of iterations @@ -950,7 +960,7 @@ DEFPARAM (PARAM_ICALL_PROMOTE_PERCENT_THRESHOLD, "icall-promote-target-percent-threshold", "percentage threshold for direct call promotion" " of a callee target", - 33, 0, 100) + 30, 0, 100) DEFPARAM (PARAM_ICALL_PROMOTE_COUNT_THRESHOLD, "icall-promote-target_count-threshold", @@ -1101,6 +1111,16 @@ DEFPARAM (PARAM_PROFILE_GENERATE_SAMPLING_PERIOD, "sampling rate with -fprofile-generate-sampling", 100, 0, 2000000000) +DEFPARAM (PARAM_LIPO_SAMPLING_PERIOD, + "lipo-sampling-period", + "sampling rate for lipo direct call and indirect call profile", + 79, 0, 2000000000) + +DEFPARAM (PARAM_PROFILE_VALUES_TIME, + "profile-values-time", + "Enable time profiling when value profiling", + 0, 0, 1) + DEFPARAM (PARAM_COVERAGE_CALLBACK, "coverage-callback", "callback a user-define function when for arc counter increments.", @@ -1354,14 +1374,36 @@ DEFPARAM (PARAM_ASAN_MEMINTRIN, DEFPARAM (PARAM_ASAN_USE_AFTER_RETURN, "asan-use-after-return", - "Enable asan builtin functions protection", + "Enable asan detection of use-after-return bugs", 1, 0, 1) +DEFPARAM (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD, + "asan-instrumentation-with-call-threshold", + "Use callbacks instead of inline code if number of accesses " + "in function becomes greater or equal to this number", + INT_MAX, 0, INT_MAX) + DEFPARAM (PARAM_UNINIT_CONTROL_DEP_ATTEMPTS, "uninit-control-dep-attempts", "Maximum number of nested calls to search for control dependencies " "during uninitialized variable analysis", 1000, 1, 0) + +/* Fraction of adjusting fp setting cost in framepointer shrinkwrapping. */ +DEFPARAM (PARAM_FPSET_COST_FRACTION, + "fpset-cost-fraction", + "Adjust the estimation of fp setting insn cost with this fraction in" + "framepointer shrinkwrapping", + 10, 1, 100) + +/* Fraction of promoting when choose to promote or not to promote fpset in + framepointer shrinkwrapping. */ +DEFPARAM (PARAM_FPSET_PROMOTE_FRACTION, + "fpset-promote-fraction", + "Adjust the estimation of fpset promotion cost with this fraction in" + "framepointer shrinkwrapping", + 1, 0, 100) + /* Local variables: diff --git a/gcc-4.9/gcc/params.h b/gcc-4.9/gcc/params.h index b1bac4067..d7686f727 100644 --- a/gcc-4.9/gcc/params.h +++ b/gcc-4.9/gcc/params.h @@ -134,6 +134,8 @@ extern void init_param_values (int *params); PARAM_VALUE (PARAM_MIN_INLINE_INSNS) #define MAX_INLINE_INSNS_AUTO \ PARAM_VALUE (PARAM_MAX_INLINE_INSNS_AUTO) +#define MAX_GROWTH_AUTO_INLINE_FUNC \ + PARAM_VALUE (PARAM_MAX_GROWTH_AUTO_INLINE_FUNC) #define MAX_VARIABLE_EXPANSIONS \ PARAM_VALUE (PARAM_MAX_VARIABLE_EXPANSIONS) #define MIN_VECT_LOOP_BOUND \ @@ -234,5 +236,7 @@ extern void init_param_values (int *params); PARAM_VALUE (PARAM_ASAN_MEMINTRIN) #define ASAN_USE_AFTER_RETURN \ PARAM_VALUE (PARAM_ASAN_USE_AFTER_RETURN) +#define ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD \ + PARAM_VALUE (PARAM_ASAN_INSTRUMENTATION_WITH_CALL_THRESHOLD) #endif /* ! GCC_PARAMS_H */ diff --git a/gcc-4.9/gcc/po/ChangeLog b/gcc-4.9/gcc/po/ChangeLog index 399d6b5fa..23a4a9cb2 100644 --- a/gcc-4.9/gcc/po/ChangeLog +++ b/gcc-4.9/gcc/po/ChangeLog @@ -1,3 +1,7 @@ +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-07-16 Release Manager * GCC 4.9.1 released. diff --git a/gcc-4.9/gcc/postreload.c b/gcc-4.9/gcc/postreload.c index 9bfffe5f4..797668b19 100644 --- a/gcc-4.9/gcc/postreload.c +++ b/gcc-4.9/gcc/postreload.c @@ -493,7 +493,13 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) continue; for (l = v->locs; l; l = l->next) - if (REG_P (l->loc)) + if (REG_P (l->loc) + /* If postreload cse replace an expr in call insn with + frame pointer reg, we will end up getting call (...bp...), + this is wrong for frame pointer shrinkwrapping. */ + && !(frame_pointer_partially_needed + && CALL_P (insn) + && REGNO (l->loc) == HARD_FRAME_POINTER_REGNUM)) SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc)); } diff --git a/gcc-4.9/gcc/recog.c b/gcc-4.9/gcc/recog.c index f2647e39a..0481d7dbb 100644 --- a/gcc-4.9/gcc/recog.c +++ b/gcc-4.9/gcc/recog.c @@ -3659,6 +3659,8 @@ peephole2_optimize (void) BITMAP_FREE (live); if (peep2_do_rebuild_jump_labels) rebuild_jump_labels (get_insns ()); + if (peep2_do_cleanup_cfg) + cleanup_cfg (CLEANUP_CFG_CHANGED); } #endif /* HAVE_peephole2 */ diff --git a/gcc-4.9/gcc/ree.c b/gcc-4.9/gcc/ree.c index 435c16696..474c07089 100644 --- a/gcc-4.9/gcc/ree.c +++ b/gcc-4.9/gcc/ree.c @@ -261,6 +261,50 @@ typedef struct ext_cand static int max_insn_uid; +/* Update or remove REG_EQUAL or REG_EQUIV notes for INSN. */ + +static bool +update_reg_equal_equiv_notes (rtx insn, enum machine_mode new_mode, + enum machine_mode old_mode, enum rtx_code code) +{ + rtx *loc = ®_NOTES (insn); + while (*loc) + { + enum reg_note kind = REG_NOTE_KIND (*loc); + if (kind == REG_EQUAL || kind == REG_EQUIV) + { + rtx orig_src = XEXP (*loc, 0); + /* Update equivalency constants. Recall that RTL constants are + sign-extended. */ + if (GET_CODE (orig_src) == CONST_INT + && HOST_BITS_PER_WIDE_INT >= GET_MODE_BITSIZE (new_mode)) + { + if (INTVAL (orig_src) >= 0 || code == SIGN_EXTEND) + /* Nothing needed. */; + else + { + /* Zero-extend the negative constant by masking out the + bits outside the source mode. */ + rtx new_const_int + = gen_int_mode (INTVAL (orig_src) + & GET_MODE_MASK (old_mode), + new_mode); + if (!validate_change (insn, &XEXP (*loc, 0), + new_const_int, true)) + return false; + } + loc = &XEXP (*loc, 1); + } + /* Drop all other notes, they assume a wrong mode. */ + else if (!validate_change (insn, loc, XEXP (*loc, 1), true)) + return false; + } + else + loc = &XEXP (*loc, 1); + } + return true; +} + /* Given a insn (CURR_INSN), an extension candidate for removal (CAND) and a pointer to the SET rtx (ORIG_SET) that needs to be modified, this code modifies the SET rtx to a new SET rtx that extends the @@ -282,6 +326,7 @@ static bool combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set) { rtx orig_src = SET_SRC (*orig_set); + enum machine_mode orig_mode = GET_MODE (SET_DEST (*orig_set)); rtx new_set; rtx cand_pat = PATTERN (cand->insn); @@ -318,9 +363,8 @@ combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set) { /* Zero-extend the negative constant by masking out the bits outside the source mode. */ - enum machine_mode src_mode = GET_MODE (SET_DEST (*orig_set)); rtx new_const_int - = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (src_mode), + = gen_int_mode (INTVAL (orig_src) & GET_MODE_MASK (orig_mode), GET_MODE (new_reg)); new_set = gen_rtx_SET (VOIDmode, new_reg, new_const_int); } @@ -359,7 +403,9 @@ combine_set_extension (ext_cand *cand, rtx curr_insn, rtx *orig_set) /* This change is a part of a group of changes. Hence, validate_change will not try to commit the change. */ - if (validate_change (curr_insn, orig_set, new_set, true)) + if (validate_change (curr_insn, orig_set, new_set, true) + && update_reg_equal_equiv_notes (curr_insn, cand->mode, orig_mode, + cand->code)) { if (dump_file) { @@ -409,7 +455,9 @@ transform_ifelse (ext_cand *cand, rtx def_insn) ifexpr = gen_rtx_IF_THEN_ELSE (cand->mode, cond, map_srcreg, map_srcreg2); new_set = gen_rtx_SET (VOIDmode, map_dstreg, ifexpr); - if (validate_change (def_insn, &PATTERN (def_insn), new_set, true)) + if (validate_change (def_insn, &PATTERN (def_insn), new_set, true) + && update_reg_equal_equiv_notes (def_insn, cand->mode, GET_MODE (dstreg), + cand->code)) { if (dump_file) { @@ -719,6 +767,17 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) != REGNO (get_extended_src_reg (SET_SRC (PATTERN (cand->insn))))); if (copy_needed) { + /* Considering transformation of + (set (reg1) (expression)) + ... + (set (reg2) (any_extend (reg1))) + + into + + (set (reg2) (any_extend (expression))) + (set (reg1) (reg2)) + ... */ + /* In theory we could handle more than one reaching def, it just makes the code to update the insn stream more complex. */ if (state->defs_list.length () != 1) @@ -734,18 +793,6 @@ combine_reaching_defs (ext_cand *cand, const_rtx set_pat, ext_state *state) if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE) return false; - /* Transformation of - (set (reg1) (expression)) - (set (reg2) (any_extend (reg1))) - into - (set (reg2) (any_extend (expression))) - (set (reg1) (reg2)) - is only valid for scalar integral modes, as it relies on the low - subreg of reg1 to have the value of (expression), which is not true - e.g. for vector modes. */ - if (!SCALAR_INT_MODE_P (GET_MODE (SET_DEST (PATTERN (cand->insn))))) - return false; - /* There's only one reaching def. */ rtx def_insn = state->defs_list[0]; @@ -954,6 +1001,7 @@ add_removable_extension (const_rtx expr, rtx insn, different extension. FIXME: this obviously can be improved. */ for (def = defs; def; def = def->next) if ((idx = def_map[INSN_UID (DF_REF_INSN (def->ref))]) + && idx != -1U && (cand = &(*insn_list)[idx - 1]) && cand->code != code) { @@ -965,6 +1013,57 @@ add_removable_extension (const_rtx expr, rtx insn, } return; } + /* For vector mode extensions, ensure that all uses of the + XEXP (src, 0) register are the same extension (both code + and to which mode), as unlike integral extensions lowpart + subreg of the sign/zero extended register are not equal + to the original register, so we have to change all uses or + none. */ + else if (VECTOR_MODE_P (GET_MODE (XEXP (src, 0)))) + { + if (idx == 0) + { + struct df_link *ref_chain, *ref_link; + + ref_chain = DF_REF_CHAIN (def->ref); + for (ref_link = ref_chain; ref_link; ref_link = ref_link->next) + { + if (ref_link->ref == NULL + || DF_REF_INSN_INFO (ref_link->ref) == NULL) + { + idx = -1U; + break; + } + rtx use_insn = DF_REF_INSN (ref_link->ref); + const_rtx use_set; + if (use_insn == insn || DEBUG_INSN_P (use_insn)) + continue; + if (!(use_set = single_set (use_insn)) + || !REG_P (SET_DEST (use_set)) + || GET_MODE (SET_DEST (use_set)) != GET_MODE (dest) + || GET_CODE (SET_SRC (use_set)) != code + || !rtx_equal_p (XEXP (SET_SRC (use_set), 0), + XEXP (src, 0))) + { + idx = -1U; + break; + } + } + if (idx == -1U) + def_map[INSN_UID (DF_REF_INSN (def->ref))] = idx; + } + if (idx == -1U) + { + if (dump_file) + { + fprintf (dump_file, "Cannot eliminate extension:\n"); + print_rtl_single (dump_file, insn); + fprintf (dump_file, + " because some vector uses aren't extension\n"); + } + return; + } + } /* Then add the candidate to the list and insert the reaching definitions into the definition map. */ diff --git a/gcc-4.9/gcc/regcprop.c b/gcc-4.9/gcc/regcprop.c index 5b63cb74d..a1c7b9ddb 100644 --- a/gcc-4.9/gcc/regcprop.c +++ b/gcc-4.9/gcc/regcprop.c @@ -1040,7 +1040,17 @@ copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd) but instead among CLOBBERs on the CALL_INSN, we could wrongly assume the value in it is still live. */ if (ksvd.ignore_set_reg) - note_stores (PATTERN (insn), kill_clobbered_value, vd); + { + note_stores (PATTERN (insn), kill_clobbered_value, vd); + for (exp = CALL_INSN_FUNCTION_USAGE (insn); + exp; + exp = XEXP (exp, 1)) + { + rtx x = XEXP (exp, 0); + if (GET_CODE (x) == CLOBBER) + kill_value (SET_DEST (x), vd); + } + } } /* Notice stores. */ diff --git a/gcc-4.9/gcc/regrename.c b/gcc-4.9/gcc/regrename.c index 6517f4e38..d9a0ced95 100644 --- a/gcc-4.9/gcc/regrename.c +++ b/gcc-4.9/gcc/regrename.c @@ -420,7 +420,7 @@ rename_chains (void) CLEAR_HARD_REG_SET (unavailable); /* Don't clobber traceback for noreturn functions. */ - if (frame_pointer_needed) + if (frame_pointer_needed || frame_pointer_partially_needed) { add_to_hard_reg_set (&unavailable, Pmode, FRAME_POINTER_REGNUM); #if !HARD_FRAME_POINTER_IS_FRAME_POINTER @@ -443,6 +443,7 @@ rename_chains (void) if (fixed_regs[reg] || global_regs[reg] #if !HARD_FRAME_POINTER_IS_FRAME_POINTER || (frame_pointer_needed && reg == HARD_FRAME_POINTER_REGNUM) + || (frame_pointer_partially_needed && reg == HARD_FRAME_POINTER_REGNUM) #else || (frame_pointer_needed && reg == FRAME_POINTER_REGNUM) #endif diff --git a/gcc-4.9/gcc/reload.c b/gcc-4.9/gcc/reload.c index 851daf30f..e0405097a 100644 --- a/gcc-4.9/gcc/reload.c +++ b/gcc-4.9/gcc/reload.c @@ -1622,6 +1622,7 @@ push_reload (rtx in, rtx out, rtx *inloc, rtx *outloc, end_hard_regno (rel_mode, regno), PATTERN (this_insn), inloc) + && ! find_reg_fusage (this_insn, USE, XEXP (note, 0)) /* If this is also an output reload, IN cannot be used as the reload register if it is set in this insn unless IN is also OUT. */ diff --git a/gcc-4.9/gcc/rtlanal.c b/gcc-4.9/gcc/rtlanal.c index 98fbacce4..e99ef7bf7 100644 --- a/gcc-4.9/gcc/rtlanal.c +++ b/gcc-4.9/gcc/rtlanal.c @@ -873,6 +873,17 @@ reg_set_between_p (const_rtx reg, const_rtx from_insn, const_rtx to_insn) int reg_set_p (const_rtx reg, const_rtx insn) { + /* After delay slot handling, call and branch insns might be in a + sequence. Check all the elements there. */ + if (INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE) + { + for (int i = 0; i < XVECLEN (PATTERN (insn), 0); ++i) + if (reg_set_p (reg, XVECEXP (PATTERN (insn), 0, i))) + return true; + + return false; + } + /* We can be passed an insn or part of one. If we are passed an insn, check if a side-effect of the insn clobbers REG. */ if (INSN_P (insn) @@ -884,7 +895,7 @@ reg_set_p (const_rtx reg, const_rtx insn) GET_MODE (reg), REGNO (reg))) || MEM_P (reg) || find_reg_fusage (insn, CLOBBER, reg))))) - return 1; + return true; return set_of (reg, insn) != NULL_RTX; } diff --git a/gcc-4.9/gcc/sanitizer.def b/gcc-4.9/gcc/sanitizer.def index 015b1d85f..b1e6f0497 100644 --- a/gcc-4.9/gcc/sanitizer.def +++ b/gcc-4.9/gcc/sanitizer.def @@ -29,7 +29,7 @@ along with GCC; see the file COPYING3. If not see /* Address Sanitizer */ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_INIT, "__asan_init_v3", BT_FN_VOID, ATTR_NOTHROW_LEAF_LIST) -/* Do not reorder the BUILT_IN_ASAN_REPORT* builtins, e.g. cfgcleanup.c +/* Do not reorder the BUILT_IN_ASAN_{REPORT,CHECK}* builtins, e.g. cfgcleanup.c relies on this order. */ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD1, "__asan_report_load1", BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) @@ -41,6 +41,9 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD8, "__asan_report_load8", BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD16, "__asan_report_load16", BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_LOAD_N, "__asan_report_load_n", + BT_FN_VOID_PTR_PTRMODE, + ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE1, "__asan_report_store1", BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE2, "__asan_report_store2", @@ -51,6 +54,33 @@ DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE8, "__asan_report_store8", BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE16, "__asan_report_store16", BT_FN_VOID_PTR, ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REPORT_STORE_N, "__asan_report_store_n", + BT_FN_VOID_PTR_PTRMODE, + ATTR_TMPURE_NORETURN_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD1, "__asan_load1", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD2, "__asan_load2", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD4, "__asan_load4", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD8, "__asan_load8", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOAD16, "__asan_load16", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_LOADN, "__asan_loadN", + BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE1, "__asan_store1", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE2, "__asan_store2", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE4, "__asan_store4", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE8, "__asan_store8", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STORE16, "__asan_store16", + BT_FN_VOID_PTR, ATTR_TMPURE_NOTHROW_LEAF_LIST) +DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_STOREN, "__asan_storeN", + BT_FN_VOID_PTR_PTRMODE, ATTR_TMPURE_NOTHROW_LEAF_LIST) DEF_SANITIZER_BUILTIN(BUILT_IN_ASAN_REGISTER_GLOBALS, "__asan_register_globals", BT_FN_VOID_PTR_PTRMODE, ATTR_NOTHROW_LEAF_LIST) diff --git a/gcc-4.9/gcc/sched-deps.c b/gcc-4.9/gcc/sched-deps.c index 1d4700733..dc8718745 100644 --- a/gcc-4.9/gcc/sched-deps.c +++ b/gcc-4.9/gcc/sched-deps.c @@ -1233,6 +1233,13 @@ add_or_update_dep_1 (dep_t new_dep, bool resolved_p, switch (ask_dependency_caches (new_dep)) { case DEP_PRESENT: + dep_t present_dep; + sd_iterator_def sd_it; + + present_dep = sd_find_dep_between_no_cache (DEP_PRO (new_dep), + DEP_CON (new_dep), + resolved_p, &sd_it); + DEP_MULTIPLE (present_dep) = 1; return DEP_PRESENT; case DEP_CHANGED: @@ -4747,24 +4754,6 @@ find_inc (struct mem_inc_info *mii, bool backwards) goto next; } } - - /* The inc instruction could have clobbers, make sure those - registers are not used in mem insn. */ - for (def_rec = DF_INSN_DEFS (mii->inc_insn); *def_rec; def_rec++) - if (!reg_overlap_mentioned_p (DF_REF_REG (*def_rec), mii->mem_reg0)) - { - df_ref *use_rec; - for (use_rec = DF_INSN_USES (mii->mem_insn); *use_rec; use_rec++) - if (reg_overlap_mentioned_p (DF_REF_REG (*def_rec), - DF_REF_REG (*use_rec))) - { - if (sched_verbose >= 5) - fprintf (sched_dump, - "inc clobber used in store failure.\n"); - goto next; - } - } - newaddr = mii->inc_input; if (mii->mem_index != NULL_RTX) newaddr = gen_rtx_PLUS (GET_MODE (newaddr), newaddr, diff --git a/gcc-4.9/gcc/simplify-got.c b/gcc-4.9/gcc/simplify-got.c index 61a8fe893..7d46b2683 100644 --- a/gcc-4.9/gcc/simplify-got.c +++ b/gcc-4.9/gcc/simplify-got.c @@ -169,7 +169,7 @@ rest_of_handle_simplify_got (void) /* Since there is no usage of pic_reg now, we can remove it. */ if (use) - remove_insn (use); + delete_insn (use); targetm.got_access.clear_pic_reg (); free (got_accesses); htab_delete (var_table); diff --git a/gcc-4.9/gcc/stor-layout.c b/gcc-4.9/gcc/stor-layout.c index 084d195cd..9dc10d454 100644 --- a/gcc-4.9/gcc/stor-layout.c +++ b/gcc-4.9/gcc/stor-layout.c @@ -211,12 +211,7 @@ self_referential_size (tree size) param_type = TREE_TYPE (ref); param_decl = build_decl (input_location, PARM_DECL, param_name, param_type); - if (targetm.calls.promote_prototypes (NULL_TREE) - && INTEGRAL_TYPE_P (param_type) - && TYPE_PRECISION (param_type) < TYPE_PRECISION (integer_type_node)) - DECL_ARG_TYPE (param_decl) = integer_type_node; - else - DECL_ARG_TYPE (param_decl) = param_type; + DECL_ARG_TYPE (param_decl) = param_type; DECL_ARTIFICIAL (param_decl) = 1; TREE_READONLY (param_decl) = 1; diff --git a/gcc-4.9/gcc/system.h b/gcc-4.9/gcc/system.h index 42bc509f2..40e3cfa07 100644 --- a/gcc-4.9/gcc/system.h +++ b/gcc-4.9/gcc/system.h @@ -928,6 +928,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN; TARGET_HANDLE_PRAGMA_EXTERN_PREFIX \ TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_EVEN \ TARGET_VECTORIZE_BUILTIN_MUL_WIDEN_ODD \ + TARGET_RELAXED_ORDERING /* Arrays that were deleted in favor of a functional interface. */ #pragma GCC poison built_in_decls implicit_built_in_decls diff --git a/gcc-4.9/gcc/target.def b/gcc-4.9/gcc/target.def index 7bbc91d96..5dab85edd 100644 --- a/gcc-4.9/gcc/target.def +++ b/gcc-4.9/gcc/target.def @@ -3621,6 +3621,16 @@ supported by the target.", unsigned HOST_WIDE_INT, (void), NULL) +/* Get frame pointer setting insn when flag_shrink_wrap_frame_pointer + is true. */ +DEFHOOK +(set_fp_insn, + "When flag_shrink_wrap_frame_pointer is true, fp setting insn should\n\ +be generated inside function body. The insertion is done after CFA\n\ +information is known.", + rtx, (void), + default_set_fp_insn) + /* Functions relating to calls - argument passing, returns, etc. */ /* Members of struct call have no special macro prefix. */ HOOK_VECTOR (TARGET_CALLS, calls) @@ -4684,6 +4694,14 @@ five otherwise. This is best for most machines.", unsigned int, (void), default_case_values_threshold) +/* Return true if a function is a leaf and its frame pointer can be omitted. */ +DEFHOOK +(can_omit_leaf_frame_pointer, + "This target hook will return @code{true} if a function is a leaf function and\n\ +its frame pointer can be omitted on the target.", + bool, (void), + hook_bool_void_false) + /* Retutn true if a function must have and use a frame pointer. */ DEFHOOK (frame_pointer_required, @@ -5352,19 +5370,6 @@ for the primary source file, immediately after printing\n\ this to be done. The default is false.", bool, false) -/* True if the target is allowed to reorder memory accesses unless - synchronization is explicitly requested. */ -DEFHOOKPOD -(relaxed_ordering, - "If set to @code{true}, means that the target's memory model does not\n\ -guarantee that loads which do not depend on one another will access\n\ -main memory in the order of the instruction stream; if ordering is\n\ -important, an explicit memory barrier must be used. This is true of\n\ -many recent processors which implement a policy of ``relaxed,''\n\ -``weak,'' or ``release'' memory consistency, such as Alpha, PowerPC,\n\ -and ia64. The default is @code{false}.", - bool, false) - /* Returns true if we should generate exception tables for use with the ARM EABI. The effects the encoding of function exception specifications. */ DEFHOOKPOD @@ -5399,6 +5404,12 @@ DEFHOOKPOD This usually means it will be run as part of machine-specific reorg.", bool, false) +DEFHOOKPOD +(strict_align, + "True if it is beneficial to try stricter function \ + or loop alignment on the target.", + bool, false) + /* Leave the boolean fields at the end. */ /* Close the 'struct gcc_target' definition. */ diff --git a/gcc-4.9/gcc/targhooks.c b/gcc-4.9/gcc/targhooks.c index 8176c54fd..4721186e5 100644 --- a/gcc-4.9/gcc/targhooks.c +++ b/gcc-4.9/gcc/targhooks.c @@ -1367,6 +1367,12 @@ default_profile_before_prologue (void) #endif } +rtx +default_set_fp_insn (void) +{ + return NULL; +} + /* The default implementation of TARGET_PREFERRED_RELOAD_CLASS. */ reg_class_t diff --git a/gcc-4.9/gcc/targhooks.h b/gcc-4.9/gcc/targhooks.h index a7170edb7..6a759205c 100644 --- a/gcc-4.9/gcc/targhooks.h +++ b/gcc-4.9/gcc/targhooks.h @@ -178,6 +178,7 @@ extern int default_register_move_cost (enum machine_mode, reg_class_t, reg_class_t); extern bool default_profile_before_prologue (void); +extern rtx default_set_fp_insn (void); extern reg_class_t default_preferred_reload_class (rtx, reg_class_t); extern reg_class_t default_preferred_output_reload_class (rtx, reg_class_t); extern reg_class_t default_preferred_rename_class (reg_class_t rclass); diff --git a/gcc-4.9/gcc/testsuite/ChangeLog b/gcc-4.9/gcc/testsuite/ChangeLog index 4eefcba93..2d76bdc81 100644 --- a/gcc-4.9/gcc/testsuite/ChangeLog +++ b/gcc-4.9/gcc/testsuite/ChangeLog @@ -1,8 +1,411 @@ +2015-03-26 Bill Schmidt + + Backport r214254 and related tests from mainline + * gcc.target/powerpc/swaps-p8-1.c: New test. + * gcc.target/powerpc/swaps-p8-2.c: New test. + * gcc.target/powerpc/swaps-p8-3.c: New test. + * gcc.target/powerpc/swaps-p8-4.c: New test. + * gcc.target/powerpc/swaps-p8-5.c: New test. + * gcc.target/powerpc/swaps-p8-6.c: New test. + * gcc.target/powerpc/swaps-p8-7.c: New test. + * gcc.target/powerpc/swaps-p8-8.c: New test. + * gcc.target/powerpc/swaps-p8-9.c: New test. + * gcc.target/powerpc/swaps-p8-10.c: New test. + * gcc.target/powerpc/swaps-p8-11.c: New test. + * gcc.target/powerpc/swaps-p8-12.c: New test. + * gcc.target/powerpc/swaps-p8-13.c: New test. + * gcc.target/powerpc/swaps-p8-14.c: New test. + * gcc.target/powerpc/swaps-p8-15.c: New test. + * gcc.target/powerpc/swaps-p8-16.c: New test. + * gcc.target/powerpc/swaps-p8-17.c: New test. + +2015-01-20 Marek Polacek + + Backport from mainline + 2014-06-23 Marek Polacek + + PR c/61553 + * c-c++-common/pr61553.c: New test. + +2015-01-16 Bernd Edlinger + + * c-c++-common/tsan/tsan_barrier.h: New. + * c-c++-common/tsan/atomic_stack.c: Reworked to not depend on sleep. + * c-c++-common/tsan/fd_pipe_race.c: Likewise. + * c-c++-common/tsan/mutexset1.c: Likewise. + * c-c++-common/tsan/race_on_barrier.c: Likewise. + * c-c++-common/tsan/race_on_mutex.c: Likewise. + * c-c++-common/tsan/race_on_mutex2.c: Likewise. + * c-c++-common/tsan/simple_race.c: Likewise. + * c-c++-common/tsan/simple_stack.c: Likewise. + * c-c++-common/tsan/sleep_sync.c: Likewise. + * c-c++-common/tsan/tiny_race.c: Likewise. + * c-c++-common/tsan/tls_race.c: Likewise. + * c-c++-common/tsan/write_in_reader_lock.c: Likewise. + * g++.dg/tsan/atomic_free.C: Likewise. + * g++.dg/tsan/atomic_free2.C: Likewise. + * g++.dg/tsan/cond_race.C: Likewise. + * g++.dg/tsan/tsan_barrier.h: Copied from c-c++-common/tsan. + +2015-01-15 Eric Botcazou + + * gnat.dg/opt47.adb: New test. + +2015-01-14 Jakub Jelinek + + Backported from mainline + 2015-01-12 Jakub Jelinek + + PR target/64513 + * gcc.target/i386/pr64513.c: New test. + + 2015-01-13 Jakub Jelinek + + PR rtl-optimization/64286 + * gcc.target/i386/avx2-pr64286.c: New test. + + PR fortran/64528 + * gfortran.dg/pr64528.f90: New test. + + 2015-01-12 Jakub Jelinek + + PR tree-optimization/64563 + * gcc.dg/pr64563.c: New test. + +2015-01-14 Marek Polacek + + Backport from mainline + 2015-01-13 Marek Polacek + + PR middle-end/64391 + * gcc.dg/tm/pr64391.c: New test. + +2015-01-13 Marc Glisse + + PR c++/54442 + * g++.dg/pr54442.C: New file. + +2015-01-13 Renlin Li + + Backported from mainline + 2014-11-19 Renlin Li + + PR target/63424 + * gcc.target/aarch64/pr63424.c: New Test. + +2015-01-12 Janus Weil + + Backport from mainline + PR fortran/63733 + * gfortran.dg/typebound_operator_20.f90: New. + +2015-01-09 Jakub Jelinek + + PR rtl-optimization/64536 + * gcc.dg/pr64536.c: New test. + +2015-01-09 Michael Meissner + + Backport from mainline: + 2015-01-06 Michael Meissner + + PR target/64505 + * gcc.target/powerpc/pr64505.c: New file to test -m32 -mpowerpc64 + fix is correct. + +2015-01-08 Christian Bruel + + PR target/64507 + * gcc.target/sh/pr64507.c: New test. + +2015-01-05 Ian Lance Taylor + + Backport from mainline: + 2014-11-21 Lynn Boger + + * go.test/go-test.exp (go-set-goarch): Add case for ppc64le goarch + value for go testing. + +2014-12-28 H.J. Lu + + Backport from mainline: + 2014-12-28 H.J. Lu + + * gcc.target/i386/pr57003.c: Skip on x32. + * gcc.target/i386/pr59927.c: Likewise. + * gcc.target/i386/pr60516.c: Likewise. + +2014-12-27 H.J. Lu + + Backport from mainline: + 2014-12-26 H.J. Lu + + PR target/64409 + * gcc.target/i386/pr64409.c: New test. + +2014-12-23 Janus Weil + + Backport from mainline + PR fortran/64244 + * gfortran.dg/typebound_call_26.f90: New. + +2014-12-19 Paolo Carlini + + PR c++/60955 + * g++.dg/warn/register-parm-1.C: New. + +2014-12-15 Jakub Jelinek + + PR tree-optimization/63551 + * gcc.dg/ipa/pr63551.c (fn2): Use 4294967286U instead of + 4294967286 to avoid warnings. + +2014-12-14 H.J. Lu + + Backported from mainline + 2014-12-14 H.J. Lu + + PR rtl-optimization/64037 + * g++.dg/pr64037.C: New test. + +2014-12-14 H.J. Lu + + Backported from mainline + 2014-12-06 H.J. Lu + + PR target/64200 + * gcc.target/i386/memcpy-strategy-4.c: New test. + +2014-12-13 Jakub Jelinek + + Backported from mainline + 2014-12-12 Jakub Jelinek + + PR tree-optimization/64269 + * gcc.c-torture/compile/pr64269.c: New test. + +2014-12-10 Bill Schmidt + + Backport from mainline + 2014-09-02 Bill Schmidt + + * gcc.target/powerpc/builtins-1.c: Add tests for vec_ctf, + vec_cts, and vec_ctu. + * gcc.target/powerpc/builtins-2.c: Likewise. + + Backport from mainline + 2014-08-28 Bill Schmidt + + * gcc.target/powerpc/builtins-1.c: Add tests for vec_xl, vec_xst, + vec_round, vec_splat, vec_div, and vec_mul. + * gcc.target/powerpc/builtins-2.c: New test. + + Backport from mainline + 2014-08-20 Bill Schmidt + + * testsuite/gcc.target/powerpc/builtins-1.c: New test. + +2014-12-10 Jakub Jelinek + + PR tree-optimization/62021 + * gcc.dg/vect/pr62021.c: New test. + +2014-12-09 Uros Bizjak + + PR bootstrap/64213 + Revert: + 2014-11-28 H.J. Lu + + PR rtl-optimization/64037 + * g++.dg/pr64037.C: New test. + +2014-12-07 Oleg Endo + + Backport from mainline + 2014-12-07 Oleg Endo + + * gcc.target/h8300/h8300.exp: Fix duplicated text. + * gcc.target/h8300/pragma-isr.c: Likewise. + * gcc.target/h8300/pragma-isr2.c: Likewise. + +2014-12-05 H.J. Lu + + Backport from mainline + 2014-12-02 H.J. Lu + + PR target/64108 + * gcc.target/i386/memset-strategy-2.c: New test. + +2014-12-05 H.J. Lu + + Backport from mainline + 2014-11-28 H.J. Lu + + PR rtl-optimization/64037 + * g++.dg/pr64037.C: New test. + +2014-12-04 Jakub Jelinek + + PR c++/56493 + * c-c++-common/pr56493.c: New test. + +2014-12-03 Renlin Li + + Backported from mainline + 2014-12-03 Renlin Li + H.J. Lu + + PR middle-end/63762 + PR target/63661 + * gcc.dg/pr63762.c: New test. + * gcc.target/i386/pr63661.c: New test. + +2014-12-01 Martin Jambor + + PR ipa/63551 + * gcc.dg/ipa/pr63551.c: New test. + * gcc.dg/ipa/pr64041.c: Likewise. + +2014-12-01 Richard Biener + + PR tree-optimization/63738 + * gcc.dg/torture/pr63738.c: Fix call to setjmp. + +2014-11-28 Jakub Jelinek + + Backported from mainline + 2014-11-27 Jakub Jelinek + + PR middle-end/64067 + * gcc.c-torture/compile/pr64067.c: New test. + + 2014-11-19 Jakub Jelinek + + PR tree-optimization/63915 + * c-c++-common/gomp/pr60823-4.c: New test. + + PR sanitizer/63913 + * g++.dg/ubsan/pr63913.C: New test. + + 2014-10-31 Jakub Jelinek + + PR rtl-optimization/63659 + * gcc.c-torture/execute/pr63659.c: New test. + +2014-11-26 Richard Biener + + PR middle-end/63738 + * gcc.dg/torture/pr63738.c: New testcase. + +2014-11-26 Richard Biener + + Backport from mainline + 2014-11-26 Richard Biener + + PR tree-optimization/62238 + * gcc.dg/torture/pr62238.c: New testcase. + + 2014-11-07 Richard Biener + + PR tree-optimization/63605 + * gcc.dg/vect/pr63605.c: New testcase. + + 2014-10-28 Richard Biener + + PR middle-end/63665 + * gcc.dg/pr63665.c: New testcase. + +2014-11-24 Eric Botcazou + + * gnat.dg/opt45.adb: New test. + +2014-11-22 Oleg Endo + + Backport from mainline + 2014-11-22 Oleg Endo + + PR target/63783 + PR target/51244 + * gcc.target/sh/torture/pr63783-1.c: New. + * gcc.target/sh/torture/pr63783-2.c: New. + * gcc.target/sh/pr51244-20.c: Adjust. + * gcc.target/sh/pr51244-20-sh2a.c: Adjust. + 2014-11-19 Renlin Li PR middle-end/63762 * gcc.dg/pr63762.c: New test. +2014-11-19 Uros Bizjak + + PR target/63947 + * gcc.target/i386/pr63947.c: New test. + +2014-11-19 Tom de Vries + + Backport from mainline + PR tree-optimization/62167 + * gcc.dg/pr51879-12.c: Add xfails. + * gcc.dg/pr62167-run.c: New test. + * gcc.dg/pr62167.c: New test. + +2014-11-13 Teresa Johnson + + PR tree-optimization/63841 + * g++.dg/tree-ssa/pr63841.C: New test. + +2014-11-12 Jakub Jelinek + + PR ipa/63838 + * g++.dg/ipa/pr63838.C: New test. + +2014-11-11 Paolo Carlini + + PR c++/63265 + * g++.dg/cpp0x/constexpr-63265.C: New. + +2014-11-09 H.J. Lu + + Backported from mainline + 2014-11-09 H.J. Lu + + PR testsuite/63305 + * gcc.target/i386/avx256-unaligned-load-7.c (avx_test): Fix + buffer overflow. + * gcc.target/i386/avx256-unaligned-store-7.c (avx_test): Likewise. + +2014-11-07 Marek Polacek + + * c-c++-common/ubsan/undefined-2.c: New test. + +2014-11-05 Uros Bizjak + + PR target/63538 + * gcc.target/i386/pr63538.c: New test. + +2014-11-03 Marek Polacek + + PR c/52769 + * gcc.dg/pr52769.c: New test. + +2014-10-31 DJ Delorie + + * gcc.dg/20141029-1.c: New. + +2014-10-31 Jakub Jelinek + + PR sanitizer/63697 + * c-c++-common/ubsan/overflow-sub-3.c: New test. + +2014-10-30 Georg-Johann Lay + + PR63633 + * gcc.target/avr/torture/pr63633-ice-mult.c: New test. + +2014-10-30 Release Manager + + * GCC 4.9.2 released. + 2014-10-29 Kyrylo Tkachov * gcc.target/aarch64/madd_after_asm_1.c: New test. @@ -12,17 +415,480 @@ PR tree-optimization/63530 gcc.dg/vect/pr63530.c: New test. +2014-10-27 Eric Botcazou + + * gnat.dg/entry_queues2.adb: New test. + +2014-10-25 Yury Gribov + + PR sanitizer/63638 + * c-c++-common/asan/pr63638.c: New test. + +2014-10-24 Markus Trippelsdorf + + PR bootstrap/63632 + * g++.dg/torture/pr63632.C: New test. + 2014-10-21 Jakub Jelinek PR tree-optimization/63563 * gcc.target/i386/pr63563.c: New test. +2014-10-20 Yury Gribov + + Backported from mainline + 2014-05-30 Jakub Jelinek + + * c-c++-common/asan/misalign-1.c: New test. + * c-c++-common/asan/misalign-2.c: New test. + +2014-10-17 Jakub Jelinek + + * c-c++-common/asan/instrument-with-calls-1.c: Add + -fno-sanitize=address -fsanitize=kernel-address to dg-options. + * c-c++-common/asan/instrument-with-calls-2.c: Likewise. + + PR tree-optimization/63302 + * gcc.c-torture/execute/pr63302.c: New test. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-09-01 Yury Gribov + + PR sanitizer/61897 + PR sanitizer/62140 + + * c-c++-common/asan/pr62140-1.c: New test. + * c-c++-common/asan/pr62140-2.c: New test. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-08-18 Yury Gribov + + PR sanitizer/62089 + + * c-c++-common/asan/pr62089.c: New test. + * c-c++-common/asan/bitfield-1.c: New test. + * c-c++-common/asan/bitfield-2.c: New test. + * c-c++-common/asan/bitfield-3.c: New test. + * c-c++-common/asan/bitfield-4.c: New test. + + Backport from mainline + 2014-08-28 Yury Gribov + + * c-c++-common/asan/pr62089.c: Fix test on 32-bit platforms. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-08-11 Yury Gribov + + * c-c++-common/asan/inc.c: Update test. + * c-c++-common/asan/instrument-with-calls-2.c: Likewise. + * c-c++-common/asan/no-redundant-instrumentation-1.c: Likewise. + * c-c++-common/asan/no-redundant-instrumentation-2.c: Likewise. + * c-c++-common/asan/no-redundant-instrumentation-3.c: Likewise. + * c-c++-common/asan/no-redundant-instrumentation-4.c: Likewise. + * c-c++-common/asan/no-redundant-instrumentation-5.c: Likewise. + * c-c++-common/asan/no-redundant-instrumentation-6.c: Likewise. + * c-c++-common/asan/no-redundant-instrumentation-7.c: Likewise. + * c-c++-common/asan/no-redundant-instrumentation-8.c: Likewise. + * c-c++-common/asan/no-redundant-instrumentation-9.c: Likewise. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-06-24 Max Ostapenko + + * c-c++-common/asan/no-redundant-instrumentation-9.c: New test. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-06-16 Yury Gribov + + * c-c++-common/asan/instrument-with-calls-1.c: New test. + * c-c++-common/asan/instrument-with-calls-2.c: Likewise. + * c-c++-common/asan/no-redundant-instrumentation-1.c: Update + test patterns. + * c-c++-common/asan/no-redundant-instrumentation-2.c: + Likewise. + * c-c++-common/asan/no-redundant-instrumentation-4.c: + Likewise. + * c-c++-common/asan/no-redundant-instrumentation-5.c: + Likewise. + * c-c++-common/asan/no-redundant-instrumentation-6.c: + Likewise. + * c-c++-common/asan/no-redundant-instrumentation-7.c: + Likewise. + * c-c++-common/asan/no-redundant-instrumentation-8.c: + Likewise. + + Backport from mainline + 2014-06-18 Yury Gribov + + PR sanitizer/61530 + + * c-c++-common/asan/pr61530.c: New test. + + Backport from mainline + 2014-06-18 Yury Gribov + + PR sanitizer/61547 + + * c-c++-common/asan/strlen-overflow-1.c: New test. + +2014-10-16 Yury Gribov + + Backport from mainline + 2014-05-14 Yury Gribov + + PR sanitizer/61100 + + * c-c++-common/asan/asan-interface-1.c: New test. + * lib/asan-dg.exp (asan_include_flags): New function. + (asan_init): Call asan_include_flags to obtain path + to sanitizer headers. + +2014-10-15 Vladimir Makarov + + PR rtl-optimization/63448 + * gcc.target/i386/pr63448.c: New test. + +2014-10-15 Eric Botcazou + + * gnat.dg/opt41.adb: New test. + * gnat.dg/opt41_pkg.ad[sb]: New helper. + +2014-10-15 Richard Biener + + Backport from mainline + 2014-08-15 Richard Biener + + PR tree-optimization/62031 + * gcc.dg/torture/pr62031.c: New testcase. + +2014-10-12 Bill Schmidt + + Backport from mainline r215880 + 2014-10-03 Bill Schmidt + + * g++.dg/ext/altivec-2.C: Compile with -Wno-deprecated to avoid + failing with the new warning message. + * gcc.dg/vmx/3c-01a.c: Likewise. + * gcc.dg/vmx/ops-long-1.c: Likewise. + * gcc.dg/vmx/ops.c: Likewise. + * gcc.target/powerpc/altivec-20.c: Likewise. + * gcc.target/powerpc/altivec-6.c: Likewise. + * gcc.target/powerpc/altivec-vec-merge.c: Likewise. + * gcc.target/powerpc/vsx-builtin-8.c: Likewise. + * gcc.target/powerpc/warn-lvsl-lvsr.c: New test. + + Backport from mainline r215882 + 2014-10-03 Bill Schmidt + + * gcc.target/powerpc/lvsl-lvsr.c: New test. + + Backport from mainline r216017 + 2014-10-08 Pat Haugen + + * gcc.dg/vmx/3c-01a.c: Add default options from vmx.exp. + * gcc.dg/vmx/ops.c: Likewise. + * gcc.dg/vmx/ops-long-1.c: Likewise. + +2014-10-11 Christophe Lyon + + Backport from mainline r216117. + 2014-10-11 Christophe Lyon + * lib/target-supports.exp (check_effective_target_shared): New + function. + * g++.dg/ipa/devirt-28a.C: Check if -shared is supported. + +2014-10-10 Jakub Jelinek + + PR c/63495 + * gcc.target/i386/pr63495.c: New test. + +2014-10-10 Richard Biener + + PR tree-optimization/63379 + * gcc.dg/vect/pr63379.c: New testcase. + +2014-10-10 Jakub Jelinek + + PR fortran/59488 + * gfortran.dg/gomp/pr59488-1.f90: New test. + * gfortran.dg/gomp/pr59488-2.f90: New test. + +2014-10-10 Richard Biener + + PR tree-optimization/63380 + * gcc.dg/torture/pr63380-1.c: New testcase. + * gcc.dg/torture/pr63380-2.c: Likewise. + +2014-10-10 Uros Bizjak + + * g++.dg/cpp1y/feat-cxx14.C: Variable templates not in yet. + (dg-do): Use c++1y target. + +2014-10-08 Edward Smith-Rowland <3dw4rd@verizon.net> + + Implement SD-6: SG10 Feature Test Recommendations + * g++.dg/cpp1y/feat-cxx11-neg.C: New. + * g++.dg/cpp1y/feat-cxx11.C: New. + * g++.dg/cpp1y/feat-cxx14.C: New. + * g++.dg/cpp1y/feat-cxx98.C: New. + * g++.dg/cpp1y/feat-cxx98-neg.C: New. + * g++.dg/cpp1y/phoobhar.h: New. + * g++.dg/cpp1y/testinc/phoobhar.h: New. + +2014-10-03 Jan Hubicka + + PR ipa/61144 + * gcc.dg/tree-ssa/pr61144.c: New testcase. + +2014-10-03 Jan Hubicka + + PR ipa/62121 + * g++.dg/torture/pr62121.C: New testcase. + +2014-10-03 Jan Hubicka + + PR lto/62026 + * g++.dg/lto/pr62026.C: New testcase. + +2014-10-03 Jakub Jelinek + + PR libgomp/61200 + * c-c++-common/gomp/pr61200.c: New test. + +2014-10-01 Jakub Jelinek + + PR debug/63342 + * gcc.dg/pr63342.c: New test. + + PR target/63428 + * gcc.dg/torture/vshuf-4.inc: Move test 122 from EXPTESTS + to test 24 in TESTS. + + PR c++/63306 + * g++.dg/ipa/pr63306.C: New test. + + 2014-09-18 Vladimir Makarov + + PR debug/63285 + * gcc.target/i386/pr63285.c: New test. + + 2014-09-10 Jan Hubicka + + PR tree-optimization/63186 + * gcc.dg/pr63186.c: New testcase. + +2014-09-30 Jakub Jelinek + + PR inline-asm/63282 + * gcc.c-torture/compile/pr63282.c: New test. + +2014-09-29 James Clarke + + PR target/61407 + * gcc.dg/darwin-minversion-1.c: Fixed formatting. + * gcc.dg/darwin-minversion-2.c: Fixed formatting. + * gcc.dg/darwin-minversion-3.c: Fixed formatting. + * gcc.dg/darwin-minversion-4.c: Added test for OS X 10.10. + +2014-09-26 Jakub Jelinek + + * g++.dg/compat/struct-layout-1_generate.c: Add -Wno-abi + to default options. + +2014-09-25 Bill Schmidt + + Backport from mainline r215559 + 2014-09-25 Bill Schmidt + + PR target/63335 + * gcc.target/powerpc/pr63335.c: New test. + 2014-09-25 Jakub Jelinek PR tree-optimization/63341 * gcc.dg/vect/pr63341-1.c: New test. * gcc.dg/vect/pr63341-2.c: New test. + PR c++/63249 + * g++.dg/gomp/pr63249.C: New test. + * c-c++-common/gomp/pr63249.c: New test. + +2014-09-22 Paolo Carlini + + PR c++/62219 + * g++.dg/cpp0x/lambda/lambda-template14.C: New. + +2014-09-22 Marek Polacek + + Backport from mainline + 2014-05-21 Marek Polacek + + PR sanitizer/61272 + * g++.dg/ubsan/pr61272.C: New test. + +2014-09-22 Jakub Jelinek + + PR debug/63328 + * c-c++-common/gomp/pr63328.c: New test. + +2014-09-18 H.J. Lu + + Backport from mainline + 2014-09-18 H.J. Lu + + * gcc.dg/pr61053.c: Updated for x32. + +2014-09-18 Jakub Jelinek + + PR c++/62017 + * g++.dg/asan/pr62017.C: New test. + + PR testsuite/63292 + * gcc.dg/vect/pr59594.c (b): Increase size to N + 2 elements. + +2014-09-18 Joseph Myers + + * gcc.dg/torture/float128-exact-underflow.c: New test. + +2014-09-17 Jakub Jelinek + + PR debug/63284 + * gcc.dg/pr63284.c: New test. + +2014-09-17 Paolo Carlini + + PR c++/63241 + * g++.dg/cpp0x/constexpr-63241.C: New. + +2014-09-15 Sharad Singhai + + * g++.dg/tree-prof/lipo/static1_0.C: New test. + * g++.dg/tree-prof/lipo/static1_1.C: New file. + * g++.dg/tree-prof/lipo/static1_2.C: New file. + +2014-09-12 Martin Jambor + + PR ipa/61654 + * g++.dg/ipa/pr61654.C: New test. + +2014-09-11 Alan Lawrence + + Backport r214953 from mainline + 2014-09-05 Alan Lawrence + + * gcc.target/aarch64/scalar_intrinsics.c (*): Replace all + int{32,16,8}x1_t with int{32,16,8}_t. + * gcc.target/aarch64/simd/vqdmlalh_lane_s16.c: Likewise. + * gcc.target/aarch64/simd/vqdmlslh_lane_s16.c: Likewise. + * gcc.target/aarch64/simd/vqdmullh_lane_s16.c: Likewise. + * gcc.target/aarch64/simd/vqdmulls_lane_s32.c: Likewise. + +2014-09-10 Xinliang David Li + + Backport from mainline + PR target/63209 + * gcc.c-torture/execute/pr63209.c: New test. + +2014-09-09 Bill Schmidt + + Backported from mainline + 2014-09-04 Bill Schmidt + + * gcc.target/powerpc/vsx-extract-1.c: Test 0th doubleword + regardless of endianness. + +2014-09-09 Richard Biener + + Backport from mainline + 2014-08-11 Richard Biener + + PR tree-optimization/62075 + * gcc.dg/vect/pr62075.c: New testcase. + + 2014-08-14 Richard Biener + + PR rtl-optimization/62079 + * g++.dg/pr62079.C: New testcase. + + 2014-08-26 Richard Biener + + PR tree-optimization/62175 + * g++.dg/torture/pr62175.C: New testcase. + +2014-09-08 Jakub Jelinek + + PR tree-optimization/60196 + PR tree-optimization/63189 + * gcc.dg/vect/pr63189.c: New test. + * gcc.dg/vect/pr60196-1.c: New test. + * gcc.dg/vect/pr60196-2.c: New test. + +2014-09-06 John David Anglin + + PR testsuite/56194 + * g++.dg/init/const9.C: Skip scan-assembler-not "rodata" on hppa*-*-*. + +2014-09-05 Easwaran Raman + + Backport from mainline + PR rtl-optimization/62146 + * testsuite/g++.dg/opt/pr62146.C: New. + +2014-09-04 Guozhi Wei + + PR target/62040 + * gcc.target/aarch64/pr62040.c: New test. + +2014-09-03 Martin Jambor + + PR ipa/62015 + * g++.dg/ipa/pr62015.C: New test. + +2014-09-03 Martin Jambor + + PR ipa/61986 + * gcc.dg/ipa/pr61986.c: New test. + +2014-09-03 Marek Polacek + + Backport from mainline + 2014-09-02 Marek Polacek + + PR fortran/62270 + * gfortran.dg/pointer_intent_7.f90: Adjust dg-error. + +2014-09-03 Marek Polacek + + PR c/62294 + * gcc.dg/pr56724-1.c: New test. + * gcc.dg/pr56724-2.c: New test. + * gcc.dg/pr62294.c: New test. + * gcc.dg/pr62294.h: New file. + +2014-09-01 Oleg Endo + + Backport from mainline + 2014-09-01 Oleg Endo + + PR target/62312 + * gcc.c-torture/compile/pr62312.c: New. + +2014-09-01 Maciej W. Rozycki + + Backport from mainline + 2014-09-01 Maciej W. Rozycki + + * gcc.dg/tree-ssa/loop-19.c: Exclude classic FPU Power targets. + 2014-09-04 Guozhi Wei PR target/62040 @@ -4619,6 +5485,11 @@ PR middle-end/59471 * gcc.dg/pr59471.c: New testcase. +2014-01-08 Thomas Koenig + + PR fortran/56867 + * gfortran.dg/dependency_45.f90: New test. + 2014-01-07 Jeff Law PR middle-end/53623 diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/asan-interface-1.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/asan-interface-1.c new file mode 100644 index 000000000..8cd80caaa --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/asan-interface-1.c @@ -0,0 +1,14 @@ +/* Check that interface headers work. */ + +/* { dg-do run { target { *-*-linux* } } } */ + +#include +#include + +int main() { + char tmp; + if (__asan_address_is_poisoned((volatile char *)&tmp + 1)) + return 0; + return 1; +} + diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-1.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-1.c new file mode 100644 index 000000000..b3f300c64 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-1.c @@ -0,0 +1,25 @@ +/* Check that Asan correctly instruments bitfields with non-round size. */ + +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +struct A +{ + char base; + int : 4; + long x : 7; +}; + +int __attribute__ ((noinline, noclone)) +f (void *p) { + return ((struct A *)p)->x; +} + +int +main () +{ + char a = 0; + return f (&a); +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-2.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-2.c new file mode 100644 index 000000000..8ab0f8069 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-2.c @@ -0,0 +1,25 @@ +/* Check that Asan correctly instruments bitfields with non-round offset. */ + +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +struct A +{ + char base; + int : 7; + int x : 8; +}; + +int __attribute__ ((noinline, noclone)) +f (void *p) { + return ((struct A *)p)->x; +} + +int +main () +{ + char a = 0; + return f (&a); +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-3.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-3.c new file mode 100644 index 000000000..c5907786f --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-3.c @@ -0,0 +1,25 @@ +/* Check that Asan correctly instruments bitfields with round offset. */ + +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +struct A +{ + char base; + int : 8; + int x : 8; +}; + +int __attribute__ ((noinline, noclone)) +f (void *p) { + return ((struct A *)p)->x; +} + +int +main () +{ + char a = 0; + return f (&a); +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-4.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-4.c new file mode 100644 index 000000000..94de9a437 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/bitfield-4.c @@ -0,0 +1,25 @@ +/* Check that Asan correctly instruments bitfields with round offset. */ + +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +struct A +{ + char base; + int : 0; + int x : 8; +}; + +int __attribute__ ((noinline, noclone)) +f (void *p) { + return ((struct A *)p)->x; +} + +int +main () +{ + char a = 0; + return f (&a); +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/inc.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/inc.c index b9c6734ea..36cc3d8d8 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/asan/inc.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/inc.c @@ -16,6 +16,6 @@ main () return 0; } -/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 1 "asan0" } } */ -/* { dg-final { scan-tree-dump "__builtin___asan_report_load4" "asan0" } } */ +/* { dg-final { scan-tree-dump-times "ASAN_" 1 "asan0" } } */ +/* { dg-final { scan-tree-dump "ASAN_CHECK \\(.*, 4\\);" "asan0" } } */ /* { dg-final { cleanup-tree-dump "asan0" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/instrument-with-calls-1.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/instrument-with-calls-1.c new file mode 100644 index 000000000..32e32a600 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/instrument-with-calls-1.c @@ -0,0 +1,10 @@ +/* { dg-do assemble } */ +/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address --param asan-instrumentation-with-call-threshold=0 -save-temps" } */ + +void f(char *a, int *b) { + *b = *a; +} + +/* { dg-final { scan-assembler "__asan_load1" } } */ +/* { dg-final { scan-assembler "__asan_store4" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c new file mode 100644 index 000000000..1b361e627 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/instrument-with-calls-2.c @@ -0,0 +1,16 @@ +/* { dg-do assemble } */ +/* { dg-options "-fno-sanitize=address -fsanitize=kernel-address --param asan-instrumentation-with-call-threshold=1 -save-temps" } */ + +int x; + +void f(int *a, int *b) { + *a = 0; + asm volatile ("" ::: "memory"); + x = *b; +} + +/* { dg-final { scan-assembler "__asan_store4" } } */ +/* { dg-final { scan-assembler-not "__asan_report_store4" } } */ +/* { dg-final { scan-assembler "__asan_load4" } } */ +/* { dg-final { scan-assembler-not "__asan_report_load4" } } */ +/* { dg-final { cleanup-saved-temps } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/misalign-1.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/misalign-1.c new file mode 100644 index 000000000..0c5b6e0c7 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/misalign-1.c @@ -0,0 +1,42 @@ +/* { dg-do run { target { ilp32 || lp64 } } } */ +/* { dg-options "-O2" } */ +/* { dg-shouldfail "asan" } */ + +struct S { int i; } __attribute__ ((packed)); + +__attribute__((noinline, noclone)) int +foo (struct S *s) +{ + return s->i; +} + +__attribute__((noinline, noclone)) int +bar (int *s) +{ + return *s; +} + +__attribute__((noinline, noclone)) struct S +baz (struct S *s) +{ + return *s; +} + +int +main () +{ + struct T { char a[3]; struct S b[3]; char c; } t; + int v = 5; + struct S *p = t.b; + asm volatile ("" : "+rm" (p)); + p += 3; + if (bar (&v) != 5) __builtin_abort (); + volatile int w = foo (p); + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */ +/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*foo(\[^\n\r]*misalign-1.c:10|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-1.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/misalign-2.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/misalign-2.c new file mode 100644 index 000000000..7fbe299cc --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/misalign-2.c @@ -0,0 +1,42 @@ +/* { dg-do run { target { ilp32 || lp64 } } } */ +/* { dg-options "-O2" } */ +/* { dg-shouldfail "asan" } */ + +struct S { int i; } __attribute__ ((packed)); + +__attribute__((noinline, noclone)) int +foo (struct S *s) +{ + return s->i; +} + +__attribute__((noinline, noclone)) int +bar (int *s) +{ + return *s; +} + +__attribute__((noinline, noclone)) struct S +baz (struct S *s) +{ + return *s; +} + +int +main () +{ + struct T { char a[3]; struct S b[3]; char c; } t; + int v = 5; + struct S *p = t.b; + asm volatile ("" : "+rm" (p)); + p += 3; + if (bar (&v) != 5) __builtin_abort (); + volatile struct S w = baz (p); + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */ +/* { dg-output "0x\[0-9a-f\]+ at pc 0x\[0-9a-f\]+ bp 0x\[0-9a-f\]+ sp 0x\[0-9a-f\]+\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*READ of size 4 at 0x\[0-9a-f\]+ thread T0\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*baz(\[^\n\r]*misalign-2.c:22|\[^\n\r]*:0)|\[(\])\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output " #1 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*misalign-2.c:34|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c index fa52e0ca8..028f8d715 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-1.c @@ -2,7 +2,7 @@ location in the same basic block, the second reference should not be instrumented by the Address Sanitizer. */ -/* { dg-options "-fdump-tree-asan0" } */ +/* { dg-options "-fdump-tree-sanopt" } */ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ @@ -16,12 +16,11 @@ test0 () tab[0] = 1; tab[1] = 2; - /* __builtin___asan_report_load1 called 1 time for the store - below. */ - char t0 = tab[1]; - /* This load should not be instrumented because it is to the same memory location as above. */ + char t0 = tab[1]; + + /* Likewise. */ char t1 = tab[1]; return t0 + t1; @@ -36,7 +35,7 @@ test1 (int i) the initialization. */ foo[i] = 1; - /*__builtin___asan_report_store1 called 2 times here to instrument + /*__builtin___asan_report_store_n called once here to instrument the store to the memory region of tab. */ __builtin_memset (tab, 3, sizeof (tab)); @@ -44,8 +43,8 @@ test1 (int i) __builtin_memset (tab, 4, sizeof (tab)); __builtin_memset (tab, 5, sizeof (tab)); - /* There are 2 calls to __builtin___asan_report_store1 and 2 calls - to __builtin___asan_report_load1 to instrument the store to + /* There is a call to __builtin___asan_report_store_n and a call + to __builtin___asan_report_load_n to instrument the store to (subset of) the memory region of tab. */ __builtin_memcpy (&tab[1], foo + i, 3); @@ -53,7 +52,7 @@ test1 (int i) the reference to tab[1] has been already instrumented above. */ return tab[1]; - /* So for these function, there should be 7 calls to + /* So for these functions, there should be 3 calls to __builtin___asan_report_store1. */ } @@ -63,6 +62,7 @@ main () return test0 () && test1 (0); } -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 7 "asan0" } } */ -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load" 2 "asan0" } } */ -/* { dg-final { cleanup-tree-dump "asan0" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 3 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c index 28525e0ff..a58411c3a 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-2.c @@ -3,7 +3,7 @@ be instrumented by the Address Sanitizer. But in case of access to overlapping regions we must be precise. */ -/* { dg-options "-fdump-tree-asan0" } */ +/* { dg-options "-fdump-tree-sanopt" } */ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ @@ -20,6 +20,7 @@ main () __builtin_memset (tab, 1, 3); } -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 3 "asan0" } } */ -/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 3 "asan0" } } */ -/* { dg-final { cleanup-tree-dump "asan0" } } */ +/* { dg-final { scan-tree-dump-times "& 7" 3 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 2 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c index 420a26309..5193ae06f 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-3.c @@ -1,4 +1,4 @@ -/* { dg-options "-fdump-tree-asan0" } */ +/* { dg-options "-fdump-tree-sanopt" } */ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ @@ -12,7 +12,7 @@ foo (__INT32_TYPE__ *p) return ret; } -/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 2 "asan0" } } */ -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "asan0" } } */ -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store" 1 "asan0" } } */ -/* { dg-final { cleanup-tree-dump "asan0" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report" 2 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c index b2e72841b..c3632aa3d 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-4.c @@ -1,13 +1,17 @@ -/* { dg-options "-fdump-tree-asan0" } */ +/* { dg-options "-fdump-tree-sanopt" } */ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ void foo (int *a, char *b, char *c) { + /* One check for c[0], one check for a[], one check for c, two checks for b. */ __builtin_memmove (c, b, a[c[0]]); + /* For a total of 5 checks. */ } -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 3 "asan0" } } */ -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 1 "asan0" } } */ -/* { dg-final { cleanup-tree-dump "asan0" } } */ +/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c index ead3f5823..077ea34d0 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-5.c @@ -1,13 +1,18 @@ -/* { dg-options "-fdump-tree-asan0" } */ +/* { dg-options "-fdump-tree-sanopt" } */ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ void foo (int *a, char *b, char *c) { + /* One check for b[0], one check for a[], 2 checks for c and one checks for b. */ __builtin_memmove (c, b, a[b[0]]); + /* For a total of 5 checks. */ } -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 2 "asan0" } } */ -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 2 "asan0" } } */ -/* { dg-final { cleanup-tree-dump "asan0" } } */ +/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c index e4691bc47..6d87104aa 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-6.c @@ -1,14 +1,20 @@ -/* { dg-options "-fdump-tree-asan0" } */ +/* { dg-options "-fdump-tree-sanopt" } */ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ void foo (int *a, char *b, char *c) { + /* One check for c[0], one check for a[], one check for c and 2 checks for b. */ __builtin_memmove (c, b, a[c[0]]); + /* One check for a[], one check for c and one check for b. */ __builtin_memmove (c, b, a[b[0]]); + /* For a total of 8 checks. */ } -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 5 "asan0" } } */ -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 2 "asan0" } } */ -/* { dg-final { cleanup-tree-dump "asan0" } } */ +/* { dg-final { scan-tree-dump-times "& 7" 8 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 2 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 2 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 2 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c index bf40a0376..5baa10dcd 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-7.c @@ -1,4 +1,4 @@ -/* { dg-options "-fdump-tree-asan0" } */ +/* { dg-options "-fdump-tree-sanopt" } */ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ @@ -13,11 +13,15 @@ struct S int foo (int *a, char *b, char *c) { + /* 2 checks for s.a, 2 checks for e. */ int d = __builtin_memcmp (s.a, e, 100); + /* One check for s.a and one check for e. */ d += __builtin_memcmp (s.a, e, 200); + /* For a total of 6 checks. */ return d; } -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load" 6 "asan0" } } */ -/* { dg-final { scan-tree-dump-not "__builtin___asan_report_store" "asan0" } } */ -/* { dg-final { cleanup-tree-dump "asan0" } } */ +/* { dg-final { scan-tree-dump-times "& 7" 6 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 4 "sanopt" } } */ +/* { dg-final { scan-tree-dump-not "__builtin___asan_report_store" "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c index 38ea7a21d..2a4c0812f 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-8.c @@ -1,14 +1,20 @@ -/* { dg-options "-fdump-tree-asan0" } */ +/* { dg-options "-fdump-tree-sanopt" } */ /* { dg-do compile } */ /* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ char foo (int *a, char *b, char *c) { + /* One check for b[0], one check for a[], two checks for c and one check for b. */ __builtin_memmove (c, b, a[b[0]]); + /* No checks here. */ return c[0] + b[0]; + /* For a total of 5 checks. */ } -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 3 "asan0" } } */ -/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store1" 2 "asan0" } } */ -/* { dg-final { cleanup-tree-dump "asan0" } } */ +/* { dg-final { scan-tree-dump-times "& 7" 5 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load4" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_load_n" 1 "sanopt" } } */ +/* { dg-final { scan-tree-dump-times "__builtin___asan_report_store_n" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c new file mode 100644 index 000000000..9449de578 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/no-redundant-instrumentation-9.c @@ -0,0 +1,13 @@ +/* { dg-options "-fdump-tree-sanopt" } */ +/* { dg-do compile } */ +/* { dg-skip-if "" { *-*-* } { "*" } { "-O0" } } */ + +__SIZE_TYPE__ +f (char *a) +{ + a[0] = '1'; + return __builtin_strlen (a); +} + +/* { dg-final { scan-tree-dump-times "__asan_report_load1" 1 "sanopt" } } */ +/* { dg-final { cleanup-tree-dump "sanopt" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr61530.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr61530.c new file mode 100644 index 000000000..e306a71be --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr61530.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +__attribute__((noinline,noclone)) void +foo (char *a, char *b) { + a[0] = b[0] = 0; + __builtin_memcpy(a, b, 4); +} + +int +main () { + char a, b; + foo (&a, &b); + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer: stack-buffer-overflow" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62089.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62089.c new file mode 100644 index 000000000..9b92e9bbf --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62089.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-shouldfail "asan" } */ + +#include +#include + +struct vfsmount {}; +struct dentry {}; + +struct path { + struct vfsmount *mnt; + struct dentry *dentry; +}; + +struct fs_struct { + int users; + int lock; + int seq; + int umask; + int in_exec; + struct path root, pwd; +}; + +void __attribute__((noinline, noclone)) +copy_fs_struct(struct fs_struct *a, struct fs_struct *b) { + a->root = b->root; +} + +struct fs_struct a, b; + +int +main () { + __asan_poison_memory_region (&a.root, sizeof (a.root)); + copy_fs_struct (&a, &b); + return 0; +} + +/* { dg-output "ERROR: AddressSanitizer:\[^\n\r]*on address\[^\n\r]*" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62140-1.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62140-1.c new file mode 100644 index 000000000..f0b026de2 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62140-1.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-w -fpermissive" } */ + +int memcmp (const void *p, const void *q, int len); + +int f (int *p, int *q, int len) +{ + return memcmp (p, q, len); +} + diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62140-2.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62140-2.c new file mode 100644 index 000000000..0bb2563ab --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr62140-2.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-w -fpermissive" } */ + +int strlen (const char *p); + +int f (char *p) +{ + int x = strlen (p); + return x; +} + diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr63638.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr63638.c new file mode 100644 index 000000000..a8bafc5aa --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/pr63638.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ + +extern +#ifdef __cplusplus +"C" +#endif +void *memcpy (void *, const void *, __SIZE_TYPE__); + +struct S{ + long d0, d1, d2, d3, d4, d5, d6; +}; + +struct S s[6]; + +int f(struct S *p) +{ + memcpy(p, &s[2], sizeof(*p)); + memcpy(p, &s[1], sizeof(*p)); +} + diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/asan/strlen-overflow-1.c b/gcc-4.9/gcc/testsuite/c-c++-common/asan/strlen-overflow-1.c new file mode 100644 index 000000000..4833dc778 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/asan/strlen-overflow-1.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-skip-if "" { *-*-* } { "-flto" } { "" } } */ +/* { dg-shouldfail "asan" } */ + +#include +#include + +char a[2] = "0"; + +#ifdef __cplusplus +extern "C" +#endif + +__attribute__((no_sanitize_address, noinline)) __SIZE_TYPE__ +strlen (const char *p) { + + __SIZE_TYPE__ n = 0; + for (; *p; ++n, ++p); + return n; +} + +int main () { + char *p = &a[0]; + asm ("" : "+r"(p)); + __asan_poison_memory_region ((char *)&a[1], 1); + return __builtin_strlen (a); +} + +/* { dg-output "READ of size 1 at 0x\[0-9a-f\]+ thread T0.*(\n|\r\n|\r)" } */ +/* { dg-output " #0 0x\[0-9a-f\]+ (in _*main (\[^\n\r]*strlen-overflow-1.c:26|\[^\n\r]*:0)|\[(\]).*(\n|\r\n|\r)" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr60823-4.c b/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr60823-4.c new file mode 100644 index 000000000..a9bc0fa25 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr60823-4.c @@ -0,0 +1,7 @@ +/* PR tree-optimization/63915 */ +/* { dg-do run } */ +/* { dg-require-effective-target vect_simd_clones } */ +/* { dg-options "-O2 -fopenmp-simd" } */ +/* { dg-additional-options "-fpic" { target fpic } } */ + +#include "pr60823-2.c" diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr61200.c b/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr61200.c new file mode 100644 index 000000000..d0d699dfa --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr61200.c @@ -0,0 +1,13 @@ +/* PR libgomp/61200 */ + +int +main () +{ + int var = 1; + #pragma omp parallel + if (var != 1) + __builtin_abort (); + #pragma omp task shared(var) + var = 2; + return 0; +} diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr63249.c b/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr63249.c new file mode 100644 index 000000000..878788ad7 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr63249.c @@ -0,0 +1,16 @@ +/* PR c++/63249 */ +/* { dg-do compile } */ +/* { dg-options "-Wall -W -fopenmp" } */ + +int +foo (int *v, int A, int B) /* { dg-bogus "set but not used" } */ +{ + int r = 0; + int a = 2; /* { dg-bogus "set but not used" } */ + int b = 4; /* { dg-bogus "set but not used" } */ +#pragma omp target map(to: v[a:b]) + r |= v[3]; +#pragma omp target map(to: v[A:B]) + r |= v[3]; + return r; +} diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr63328.c b/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr63328.c new file mode 100644 index 000000000..3958abe16 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/gomp/pr63328.c @@ -0,0 +1,5 @@ +/* PR debug/63328 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fopenmp-simd -fno-strict-aliasing -fcompare-debug" } */ + +#include "pr60823-3.c" diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/pr56493.c b/gcc-4.9/gcc/testsuite/c-c++-common/pr56493.c new file mode 100644 index 000000000..418126043 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/pr56493.c @@ -0,0 +1,16 @@ +/* PR c++/56493 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +unsigned long long bar (void); +int x; + +void +foo (void) +{ + x += bar (); +} + +/* Verify we narrow the addition from unsigned long long to unsigned int type. */ +/* { dg-final { scan-tree-dump " (\[a-zA-Z._0-9]*) = \\(unsigned int\\) \[^;\n\r]*;.* (\[a-zA-Z._0-9]*) = \\(unsigned int\\) \[^;\n\r]*;.* = \\1 \\+ \\2;" "gimple" { target { ilp32 || lp64 } } } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/pr61553.c b/gcc-4.9/gcc/testsuite/c-c++-common/pr61553.c new file mode 100644 index 000000000..8a3b699ee --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/pr61553.c @@ -0,0 +1,8 @@ +/* PR c/61553 */ +/* { dg-do compile } */ + +void +foo (char *s) +{ + __atomic_store (s, (void *) 0, __ATOMIC_SEQ_CST); /* { dg-error "size mismatch" } */ +} diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/atomic_stack.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/atomic_stack.c index 6a3795120..746afa7b4 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/atomic_stack.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/atomic_stack.c @@ -1,22 +1,26 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include +#include "tsan_barrier.h" +static pthread_barrier_t barrier; int Global; void *Thread1(void *x) { - sleep(1); + barrier_wait(&barrier); __atomic_fetch_add(&Global, 1, __ATOMIC_RELAXED); return NULL; } void *Thread2(void *x) { Global++; + barrier_wait(&barrier); return NULL; } int main() { + barrier_init(&barrier, 2); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); pthread_create(&t[1], NULL, Thread2, NULL); diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c index 28cd630d2..e2176da4b 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/fd_pipe_race.c @@ -1,30 +1,35 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include #include +#include "tsan_barrier.h" +static pthread_barrier_t barrier; int fds[2]; void *Thread1(void *x) { write(fds[1], "a", 1); + barrier_wait(&barrier); return NULL; } void *Thread2(void *x) { - sleep(1); + barrier_wait(&barrier); close(fds[0]); close(fds[1]); return NULL; } int main() { + barrier_init(&barrier, 2); pipe(fds); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); pthread_create(&t[1], NULL, Thread2, NULL); pthread_join(t[0], NULL); pthread_join(t[1], NULL); + return 0; } /* { dg-output "WARNING: ThreadSanitizer: data race.*\n" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/mutexset1.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/mutexset1.c index 7c32a8524..084f5141d 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/mutexset1.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/mutexset1.c @@ -1,14 +1,15 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include -#include +#include "tsan_barrier.h" +static pthread_barrier_t barrier; int Global; pthread_mutex_t mtx; void *Thread1(void *x) { - sleep(1); + barrier_wait(&barrier); pthread_mutex_lock(&mtx); Global++; pthread_mutex_unlock(&mtx); @@ -17,11 +18,13 @@ void *Thread1(void *x) { void *Thread2(void *x) { Global--; + barrier_wait(&barrier); return NULL;/* { dg-output ".*" } */ } int main() { + barrier_init(&barrier, 2); pthread_mutex_init(&mtx, 0); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_barrier.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_barrier.c index 0a0e5faba..3de3ff225 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_barrier.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_barrier.c @@ -1,26 +1,28 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include -#include -#include +#include "tsan_barrier.h" +static pthread_barrier_t barrier; pthread_barrier_t B; int Global; void *Thread1(void *x) { pthread_barrier_init(&B, 0, 2); + barrier_wait(&barrier); pthread_barrier_wait(&B); return NULL; } void *Thread2(void *x) { - sleep(1); + barrier_wait(&barrier); pthread_barrier_wait(&B); return NULL; } int main() { + barrier_init(&barrier, 2); pthread_t t; pthread_create(&t, NULL, Thread1, NULL); Thread2(0); diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_mutex.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_mutex.c index 5dad345d8..ae30d053c 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_mutex.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_mutex.c @@ -1,10 +1,10 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include -#include -#include +#include "tsan_barrier.h" +static pthread_barrier_t barrier; pthread_mutex_t Mtx; int Global; @@ -13,11 +13,12 @@ void *Thread1(void *x) { pthread_mutex_lock(&Mtx); Global = 42; pthread_mutex_unlock(&Mtx); + barrier_wait(&barrier); return NULL; } void *Thread2(void *x) { - sleep(1); + barrier_wait(&barrier); pthread_mutex_lock(&Mtx); Global = 43; pthread_mutex_unlock(&Mtx); @@ -25,6 +26,7 @@ void *Thread2(void *x) { } int main() { + barrier_init(&barrier, 2); pthread_t t[2]; pthread_create(&t[0], NULL, Thread1, NULL); pthread_create(&t[1], NULL, Thread2, NULL); @@ -37,7 +39,7 @@ int main() { /* { dg-output "WARNING: ThreadSanitizer: data race.*(\n|\r\n|\r)" } */ /* { dg-output " Atomic read of size 1 at .* by thread T2:(\n|\r\n|\r)" } */ /* { dg-output " #0 pthread_mutex_lock.*" } */ -/* { dg-output " #1 Thread2.* .*(race_on_mutex.c:21|\\?{2}:0) (.*)" } */ +/* { dg-output " #1 Thread2.* .*(race_on_mutex.c:22|\\?{2}:0) (.*)" } */ /* { dg-output " Previous write of size 1 at .* by thread T1:(\n|\r\n|\r)" } */ /* { dg-output " #0 pthread_mutex_init .* (.)*" } */ /* { dg-output " #1 Thread1.* .*(race_on_mutex.c:12|\\?{2}:0) .*" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_mutex2.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_mutex2.c index 80a6fb6c0..57d7e21e7 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_mutex2.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/race_on_mutex2.c @@ -1,22 +1,25 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include -#include -#include +#include "tsan_barrier.h" + +static pthread_barrier_t barrier; void *Thread(void *x) { pthread_mutex_lock((pthread_mutex_t*)x); pthread_mutex_unlock((pthread_mutex_t*)x); + barrier_wait(&barrier); return 0; } int main() { + barrier_init(&barrier, 2); pthread_mutex_t Mtx; pthread_mutex_init(&Mtx, 0); pthread_t t; pthread_create(&t, 0, Thread, &Mtx); - sleep(1); + barrier_wait(&barrier); pthread_mutex_destroy(&Mtx); pthread_join(t, 0); return 0; diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/simple_race.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/simple_race.c index a40accd40..c1a369b45 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/simple_race.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/simple_race.c @@ -1,13 +1,15 @@ /* { dg-set-target-env-var TSAN_OPTIONS "halt_on_error=1" } */ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include #include +#include "tsan_barrier.h" -#define MAX_ITERATIONS_NUMBER 100 -#define SLEEP_STEP 128000 +#define MAX_ITERATIONS_NUMBER 1 +#define SLEEP_STEP 128000 +static pthread_barrier_t barrier; unsigned int delay_time = 1000; static inline void delay () { @@ -17,6 +19,7 @@ static inline void delay () { extern int main_1(); int main() { + barrier_init(&barrier, 2); int i; for (i = 0; i < MAX_ITERATIONS_NUMBER; i++) { main_1(); @@ -28,6 +31,7 @@ int main() { int Global; void *Thread1(void *x) { + barrier_wait(&barrier); delay(); Global = 42; return NULL; @@ -35,6 +39,7 @@ void *Thread1(void *x) { void *Thread2(void *x) { Global = 43; + barrier_wait(&barrier); return NULL; } diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/simple_stack.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/simple_stack.c index b66a67085..a4d0aba69 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/simple_stack.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/simple_stack.c @@ -1,9 +1,10 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include -#include +#include "tsan_barrier.h" +static pthread_barrier_t barrier; int Global; void __attribute__((noinline)) foo1() { @@ -25,13 +26,14 @@ void __attribute__((noinline)) bar2() { } void *Thread1(void *x) { - sleep(1); + barrier_wait(&barrier); bar1(); return NULL; } void *Thread2(void *x) { bar2(); + barrier_wait(&barrier); return NULL; } @@ -40,6 +42,7 @@ void StartThread(pthread_t *t, void *(*f)(void*)) { } int main() { + barrier_init(&barrier, 2); pthread_t t[2]; StartThread(&t[0], Thread1); StartThread(&t[1], Thread2); @@ -50,16 +53,16 @@ int main() { /* { dg-output "WARNING: ThreadSanitizer: data race.*" } */ /* { dg-output " Write of size 4 at .* by thread T1:(\n|\r\n|\r)" } */ -/* { dg-output " #0 foo1.* .*(simple_stack.c:10|\\?{2}:0) (.*)" } */ -/* { dg-output " #1 bar1.* .*(simple_stack.c:15|\\?{2}:0) (.*)" } */ -/* { dg-output " #2 Thread1.* .*(simple_stack.c:29|\\?{2}:0) (.*)" } */ +/* { dg-output " #0 foo1.* .*(simple_stack.c:11|\\?{2}:0) (.*)" } */ +/* { dg-output " #1 bar1.* .*(simple_stack.c:16|\\?{2}:0) (.*)" } */ +/* { dg-output " #2 Thread1.* .*(simple_stack.c:30|\\?{2}:0) (.*)" } */ /* { dg-output " Previous read of size 4 at .* by thread T2:(\n|\r\n|\r)" } */ -/* { dg-output " #0 foo2.* .*(simple_stack.c:19|\\?{2}:0) (.*)" } */ -/* { dg-output " #1 bar2.* .*(simple_stack.c:24|\\?{2}:0) (.*)" } */ -/* { dg-output " #2 Thread2.* .*(simple_stack.c:34|\\?{2}:0) (.*)" } */ +/* { dg-output " #0 foo2.* .*(simple_stack.c:20|\\?{2}:0) (.*)" } */ +/* { dg-output " #1 bar2.* .*(simple_stack.c:25|\\?{2}:0) (.*)" } */ +/* { dg-output " #2 Thread2.* .*(simple_stack.c:35|\\?{2}:0) (.*)" } */ /* { dg-output " Thread T1 \\(tid=.*, running\\) created by main thread at:(\n|\r\n|\r)" } */ /* { dg-output " #0 pthread_create .* (.*)" } */ -/* { dg-output " #1 StartThread.* .*(simple_stack.c:39|\\?{2}:0) (.*)" } */ +/* { dg-output " #1 StartThread.* .*(simple_stack.c:41|\\?{2}:0) (.*)" } */ /* { dg-output " Thread T2 (.*) created by main thread at:(\n|\r\n|\r)" } */ /* { dg-output " #0 pthread_create .* (.*)" } */ -/* { dg-output " #1 StartThread.* .*(simple_stack.c:39|\\?{2}:0) (.*)" } */ +/* { dg-output " #1 StartThread.* .*(simple_stack.c:41|\\?{2}:0) (.*)" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/sleep_sync.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/sleep_sync.c index 44d44554c..c681dcef1 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/sleep_sync.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/sleep_sync.c @@ -1,8 +1,11 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include #include +#include "tsan_barrier.h" +static pthread_barrier_t barrier; int X = 0; void MySleep() { @@ -10,15 +13,18 @@ void MySleep() { } void *Thread(void *p) { + barrier_wait(&barrier); MySleep(); // Assume the main thread has done the write. X = 42; return 0; } int main() { + barrier_init(&barrier, 2); pthread_t t; pthread_create(&t, 0, Thread, 0); X = 43; + barrier_wait(&barrier); pthread_join(t, 0); return 0; } diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tiny_race.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tiny_race.c index 962497b28..10a3feb9b 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tiny_race.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tiny_race.c @@ -1,20 +1,24 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include +#include "tsan_barrier.h" +static pthread_barrier_t barrier; int Global; void *Thread1(void *x) { - sleep(1); + barrier_wait(&barrier); Global = 42; return x; } int main() { + barrier_init(&barrier, 2); pthread_t t; pthread_create(&t, 0, Thread1, 0); Global = 43; + barrier_wait(&barrier); pthread_join(t, 0); return Global; } diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tls_race.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tls_race.c index 423867e38..4dd650604 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tls_race.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tls_race.c @@ -1,18 +1,24 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include +#include "tsan_barrier.h" + +static pthread_barrier_t barrier; void *Thread(void *a) { + barrier_wait(&barrier); *(int*)a = 43; return 0; } int main() { + barrier_init(&barrier, 2); static __thread int Var = 42; pthread_t t; pthread_create(&t, 0, Thread, &Var); Var = 43; + barrier_wait(&barrier); pthread_join(t, 0); } diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tsan_barrier.h b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tsan_barrier.h new file mode 100644 index 000000000..5d37a6475 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/tsan_barrier.h @@ -0,0 +1,14 @@ +/* TSAN-invisible barriers. Link with -ldl. */ +#include +#include + +static __typeof(pthread_barrier_wait) *barrier_wait; + +static +void barrier_init (pthread_barrier_t *barrier, unsigned count) +{ + void *h = dlopen ("libpthread.so.0", RTLD_LAZY); + barrier_wait = (__typeof (pthread_barrier_wait) *) + dlsym (h, "pthread_barrier_wait"); + pthread_barrier_init (barrier, NULL, count); +} diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/write_in_reader_lock.c b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/write_in_reader_lock.c index 898d23d50..df32632bf 100644 --- a/gcc-4.9/gcc/testsuite/c-c++-common/tsan/write_in_reader_lock.c +++ b/gcc-4.9/gcc/testsuite/c-c++-common/tsan/write_in_reader_lock.c @@ -1,8 +1,10 @@ /* { dg-shouldfail "tsan" } */ +/* { dg-additional-options "-ldl" } */ #include -#include +#include "tsan_barrier.h" +static pthread_barrier_t barrier; pthread_rwlock_t rwlock; int GLOB; @@ -10,13 +12,14 @@ void *Thread1(void *p) { (void)p; pthread_rwlock_rdlock(&rwlock); // Write under reader lock. - sleep(1); + barrier_wait(&barrier); GLOB++; pthread_rwlock_unlock(&rwlock); return 0; } int main(int argc, char *argv[]) { + barrier_init(&barrier, 2); pthread_rwlock_init(&rwlock, NULL); pthread_rwlock_rdlock(&rwlock); pthread_t t; @@ -24,6 +27,7 @@ int main(int argc, char *argv[]) { volatile int x = GLOB; (void)x; pthread_rwlock_unlock(&rwlock); + barrier_wait(&barrier); pthread_join(t, 0); pthread_rwlock_destroy(&rwlock); return 0; diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/ubsan/overflow-sub-3.c b/gcc-4.9/gcc/testsuite/c-c++-common/ubsan/overflow-sub-3.c new file mode 100644 index 000000000..deec5c411 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/ubsan/overflow-sub-3.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=signed-integer-overflow" } */ + +__attribute__((noinline, noclone)) int +foo1 (int x, int y) +{ + return x - y; +} + +__attribute__((noinline, noclone)) int +foo2 (int x, int y) +{ + unsigned int xa = (unsigned int) x - (__INT_MAX__ - 3); + xa &= 3; + x = __INT_MAX__ - 3 + xa; + unsigned int ya = y + 1U; + ya &= 1; + y = ya - 1; + return x - y; +} + +int +main () +{ + int xm1, y; + for (xm1 = __INT_MAX__ - 4; xm1 < __INT_MAX__; xm1++) + for (y = -1; y <= 0; y++) + if (foo1 (xm1 + 1, y) != (int) (xm1 + 1U - y) + || foo2 (xm1 + 1, y) != (int) (xm1 + 1U - y)) + __builtin_abort (); + return 0; +} +/* { dg-output ":7:\[0-9]\[^\n\r]*signed integer overflow: 2147483647 - -1 cannot be represented in type 'int'\[^\n\r]*(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*:19:\[0-9]\[^\n\r]*signed integer overflow: 2147483647 - -1 cannot be represented in type 'int'" } */ diff --git a/gcc-4.9/gcc/testsuite/c-c++-common/ubsan/undefined-2.c b/gcc-4.9/gcc/testsuite/c-c++-common/ubsan/undefined-2.c new file mode 100644 index 000000000..fd5b4d3e9 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/c-c++-common/ubsan/undefined-2.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-fsanitize=undefined" } */ +/* { dg-additional-options "-std=gnu11" { target c } } */ +/* { dg-additional-options "-std=c++11" { target c++ } } */ + +#include + +volatile int w, z; + +__attribute__ ((noinline, noclone)) int +foo (int x, int y) +{ + z++; + return x << y; +} + +int +main () +{ + fputs ("1st\n", stderr); + w = foo (0, -__INT_MAX__); + return 0; +} + +/* { dg-output "1st(\n|\r\n|\r)" } */ +/* { dg-output "\[^\n\r]*shift exponent -\[^\n\r]* is negative\[^\n\r]*(\n|\r\n|\r)" } */ diff --git a/gcc-4.9/gcc/testsuite/g++.dg/abi/aarch64_guard1.C b/gcc-4.9/gcc/testsuite/g++.dg/abi/aarch64_guard1.C index ca1778b87..e2669a89f 100644 --- a/gcc-4.9/gcc/testsuite/g++.dg/abi/aarch64_guard1.C +++ b/gcc-4.9/gcc/testsuite/g++.dg/abi/aarch64_guard1.C @@ -13,5 +13,4 @@ int *foo () } // { dg-final { scan-assembler _ZGVZ3foovE1x,8,8 } } -// { dg-final { scan-tree-dump "_ZGVZ3foovE1x & 1" "original" } } -// { dg-final { cleanup-tree-dump "original" } } +// { dg-final { scan-tree-dump "& 1" "original" } } diff --git a/gcc-4.9/gcc/testsuite/g++.dg/abi/no-weak1.C b/gcc-4.9/gcc/testsuite/g++.dg/abi/no-weak1.C new file mode 100644 index 000000000..d53901531 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/g++.dg/abi/no-weak1.C @@ -0,0 +1,13 @@ +// { dg-options "-fno-weak" } +// { dg-final { scan-assembler "local\[ \t\]*_ZZL1fvE1i" { target x86_64-*-*gnu } } } + +static inline void f() +{ + static int i; + ++i; +}; + +int main() +{ + f(); +} diff --git a/gcc-4.9/gcc/testsuite/g++.dg/abi/spec1.C b/gcc-4.9/gcc/testsuite/g++.dg/abi/spec1.C new file mode 100644 index 000000000..153c0cfe7 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/g++.dg/abi/spec1.C @@ -0,0 +1,4 @@ +// { dg-final { scan-assembler-not "weak" } } + +template struct A { static int i; }; +template<> int A::i = 42; diff --git a/gcc-4.9/gcc/testsuite/g++.dg/asan/pr62017.C b/gcc-4.9/gcc/testsuite/g++.dg/asan/pr62017.C new file mode 100644 index 000000000..74ef37fd2 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/g++.dg/asan/pr62017.C @@ -0,0 +1,17 @@ +// PR c++/62017 +// { dg-do run } + +struct A +{ + int x; + virtual ~A () {} +}; +struct B : public virtual A {}; +struct C : public virtual A {}; +struct D : public B, virtual public C {}; + +int +main () +{ + D d; +} diff --git a/gcc-4.9/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c b/gcc-4.9/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c index 2cf08946e..2884c25f3 100644 --- a/gcc-4.9/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c +++ b/gcc-4.9/gcc/testsuite/g++.dg/compat/struct-layout-1_generate.c @@ -1,5 +1,5 @@ /* Structure layout test generator. - Copyright (C) 2004, 2005, 2007, 2008, 2009, 2011, 2012 + Copyright (C) 2004-2014 Free Software Foundation, Inc. Contributed by Jakub Jelinek . @@ -44,7 +44,7 @@ along with GCC; see the file COPYING3. If not see #endif const char *dg_options[] = { -"/* { dg-options \"%s-I%s\" } */\n", +"/* { dg-options \"%s-I%s -Wno-abi\" } */\n", "/* { dg-options \"%s-I%s -mno-mmx -Wno-abi\" { target i?86-*-* x86_64-*-* } } */\n", "/* { dg-options \"%s-I%s -fno-common\" { target hppa*-*-hpux* powerpc*-*-darwin* *-*-mingw32* *-*-cygwin* } } */\n", "/* { dg-options \"%s-I%s -mno-mmx -fno-common -Wno-abi\" { target i?86-*-darwin* x86_64-*-darwin* i?86-*-mingw32* x86_64-*-mingw32* i?86-*-cygwin* } } */\n", diff --git a/gcc-4.9/gcc/testsuite/g++.dg/cpp0x/alias-decl-44.C b/gcc-4.9/gcc/testsuite/g++.dg/cpp0x/alias-decl-44.C new file mode 100644 index 000000000..bd20b54f1 --- /dev/null +++ b/gcc-4.9/gcc/testsuite/g++.dg/cpp0x/alias-decl-44.C @@ -0,0 +1,43 @@ +// PR c++/63849 +// { dg-do compile { target c++11 } } + +template +using First = _T; // we should not use this + // alias with only + // one pack parameter (?) + +template