summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2009-06-03 06:06:01 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2009-06-03 06:06:01 +0000
commit2dda64a6258fe213cb75f8a1b381d6a8ce338bb4 (patch)
tree69dc5d71503b8283d8144704ac5beaf98a8a2c94 /gcc
parentd3ed35175e394ed9bf2721192f14f57c91c1fbe9 (diff)
downloadgcc-2dda64a6258fe213cb75f8a1b381d6a8ce338bb4.tar.gz
2009-06-03 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk r148111 git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@148114 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog1102
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in138
-rw-r--r--gcc/ada/ChangeLog31
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in42
-rw-r--r--gcc/ada/gcc-interface/Makefile.in24
-rw-r--r--gcc/ada/gcc-interface/utils.c19
-rw-r--r--gcc/ada/gcc-interface/utils2.c23
-rw-r--r--gcc/alias.c12
-rw-r--r--gcc/attribs.c12
-rw-r--r--gcc/builtins.c6
-rw-r--r--gcc/c-parser.c7
-rw-r--r--gcc/c-tree.h1
-rw-r--r--gcc/c-typeck.c136
-rw-r--r--gcc/calls.c2
-rw-r--r--gcc/cfgcleanup.c3
-rw-r--r--gcc/cfgexpand.c2
-rw-r--r--gcc/cfglayout.c14
-rw-r--r--gcc/cfgrtl.c12
-rw-r--r--gcc/cgraph.c7
-rw-r--r--gcc/collect2-aix.c371
-rw-r--r--gcc/collect2-aix.h301
-rw-r--r--gcc/collect2.c50
-rw-r--r--gcc/combine.c1
-rw-r--r--gcc/common.opt8
-rw-r--r--gcc/config.gcc9
-rw-r--r--gcc/config.in13
-rw-r--r--gcc/config/alpha/x-alpha2
-rw-r--r--gcc/config/arm/arm.c33
-rw-r--r--gcc/config/arm/lib1funcs.asm21
-rw-r--r--gcc/config/arm/linux-eabi.h16
-rw-r--r--gcc/config/arm/t-arm6
-rw-r--r--gcc/config/arm/t-linux-eabi4
-rw-r--r--gcc/config/arm/t-pe7
-rw-r--r--gcc/config/arm/t-wince-pe5
-rw-r--r--gcc/config/arm/thumb2.md127
-rw-r--r--gcc/config/bfin/bfin.md11
-rw-r--r--gcc/config/freebsd-stdint.h56
-rw-r--r--gcc/config/i386/cygming.opt4
-rw-r--r--gcc/config/i386/driver-i386.c24
-rw-r--r--gcc/config/i386/i386.c540
-rw-r--r--gcc/config/i386/i386.h14
-rw-r--r--gcc/config/i386/i386.md259
-rw-r--r--gcc/config/i386/mingw-tls.c233
-rw-r--r--gcc/config/i386/mmx.md63
-rw-r--r--gcc/config/i386/predicates.md11
-rw-r--r--gcc/config/i386/sse.md322
-rw-r--r--gcc/config/i386/t-cygming8
-rw-r--r--gcc/config/i386/t-cygwin8
-rw-r--r--gcc/config/i386/t-gthr-win324
-rw-r--r--gcc/config/i386/t-i3865
-rw-r--r--gcc/config/i386/t-interix3
-rw-r--r--gcc/config/i386/t-netware3
-rw-r--r--gcc/config/i386/t-nwld6
-rw-r--r--gcc/config/i386/winnt.c17
-rw-r--r--gcc/config/i386/x-cygwin2
-rw-r--r--gcc/config/i386/x-darwin2
-rw-r--r--gcc/config/i386/x-i3862
-rw-r--r--gcc/config/i386/x-mingw322
-rw-r--r--gcc/config/ia64/div.md427
-rw-r--r--gcc/config/ia64/ia64.md640
-rw-r--r--gcc/config/ia64/t-ia647
-rw-r--r--gcc/config/m32c/t-m32c4
-rw-r--r--gcc/config/m32r/m32r.c82
-rw-r--r--gcc/config/m32r/m32r.h10
-rw-r--r--gcc/config/m32r/m32r.md28
-rw-r--r--gcc/config/m32r/predicates.md42
-rw-r--r--gcc/config/mips/mips.c4
-rw-r--r--gcc/config/mips/x-native2
-rw-r--r--gcc/config/pa/pa-hpux.h6
-rw-r--r--gcc/config/pa/pa-hpux10.h6
-rw-r--r--gcc/config/pa/pa-hpux11.h3
-rw-r--r--gcc/config/picochip/picochip.c3
-rw-r--r--gcc/config/rs6000/aix.h16
-rw-r--r--gcc/config/rs6000/aix43.h14
-rw-r--r--gcc/config/rs6000/aix51.h12
-rw-r--r--gcc/config/rs6000/aix52.h12
-rw-r--r--gcc/config/rs6000/aix53.h12
-rw-r--r--gcc/config/rs6000/aix61.h12
-rw-r--r--gcc/config/rs6000/rs6000-c.c8
-rw-r--r--gcc/config/rs6000/t-aix522
-rw-r--r--gcc/config/rs6000/t-rs60007
-rw-r--r--gcc/config/rs6000/x-darwin3
-rw-r--r--gcc/config/rs6000/x-darwin643
-rw-r--r--gcc/config/rs6000/x-rs60002
-rw-r--r--gcc/config/score/t-score-elf6
-rw-r--r--gcc/config/sh/sh.c9
-rw-r--r--gcc/config/sh/sh.md53
-rw-r--r--gcc/config/sh/t-sh3
-rw-r--r--gcc/config/sh/t-symbian8
-rw-r--r--gcc/config/spu/t-spu-elf6
-rw-r--r--gcc/config/t-darwin14
-rw-r--r--gcc/config/t-sol26
-rw-r--r--gcc/config/t-vxworks2
-rw-r--r--gcc/config/v850/t-v8507
-rw-r--r--gcc/config/v850/t-v850e3
-rw-r--r--gcc/config/vax/vax.c2
-rw-r--r--gcc/config/x-darwin2
-rw-r--r--gcc/config/x-hpux2
-rw-r--r--gcc/config/x-linux2
-rw-r--r--gcc/config/x-solaris2
-rwxr-xr-xgcc/configure46
-rw-r--r--gcc/configure.ac13
-rw-r--r--gcc/cp/ChangeLog95
-rw-r--r--gcc/cp/Make-lang.in10
-rw-r--r--gcc/cp/call.c60
-rw-r--r--gcc/cp/cp-tree.h13
-rw-r--r--gcc/cp/cvt.c2
-rw-r--r--gcc/cp/decl.c6
-rw-r--r--gcc/cp/error.c29
-rw-r--r--gcc/cp/mangle.c11
-rw-r--r--gcc/cp/pt.c141
-rw-r--r--gcc/cp/tree.c108
-rw-r--r--gcc/cp/typeck.c19
-rw-r--r--gcc/cse.c240
-rw-r--r--gcc/dce.c7
-rw-r--r--gcc/df-core.c8
-rw-r--r--gcc/diagnostic.c14
-rw-r--r--gcc/diagnostic.h1
-rw-r--r--gcc/doc/contrib.texi4
-rw-r--r--gcc/doc/invoke.texi156
-rw-r--r--gcc/doc/plugins.texi79
-rw-r--r--gcc/doc/tm.texi27
-rw-r--r--gcc/dwarf2out.c439
-rw-r--r--gcc/dwarf2out.h2
-rw-r--r--gcc/emit-rtl.c7
-rw-r--r--gcc/emutls.c10
-rw-r--r--gcc/expr.c61
-rw-r--r--gcc/final.c10
-rw-r--r--gcc/fold-const.c28
-rw-r--r--gcc/fortran/ChangeLog61
-rw-r--r--gcc/fortran/Make-lang.in12
-rw-r--r--gcc/fortran/gfortran.h1
-rw-r--r--gcc/fortran/gfortranspec.c19
-rw-r--r--gcc/fortran/match.c5
-rw-r--r--gcc/fortran/simplify.c72
-rw-r--r--gcc/fortran/trans-decl.c355
-rw-r--r--gcc/fortran/trans-intrinsic.c116
-rw-r--r--gcc/fortran/trans-types.c2
-rw-r--r--gcc/fortran/trans-types.h1
-rw-r--r--gcc/fortran/trans.h2
-rw-r--r--gcc/function.c248
-rw-r--r--gcc/gcc-plugin.h21
-rw-r--r--gcc/gcc.c16
-rw-r--r--gcc/gcse.c20
-rw-r--r--gcc/gengtype.c1
-rw-r--r--gcc/ggc-common.c49
-rw-r--r--gcc/ggc-page.c5
-rw-r--r--gcc/ggc-zone.c5
-rw-r--r--gcc/ggc.h9
-rw-r--r--gcc/gimple-pretty-print.c2
-rw-r--r--gcc/gthr-win32.h5
-rw-r--r--gcc/insn-notes.def4
-rw-r--r--gcc/java/ChangeLog16
-rw-r--r--gcc/java/Make-lang.in21
-rw-r--r--gcc/java/jcf-io.c7
-rw-r--r--gcc/jump.c33
-rw-r--r--gcc/loop-unroll.c127
-rw-r--r--gcc/objc/ChangeLog11
-rw-r--r--gcc/objc/Make-lang.in6
-rw-r--r--gcc/objcp/ChangeLog11
-rw-r--r--gcc/objcp/Make-lang.in9
-rw-r--r--gcc/omp-low.c6
-rw-r--r--gcc/output.h5
-rw-r--r--gcc/params.def30
-rw-r--r--gcc/params.h6
-rw-r--r--gcc/plugin.c19
-rw-r--r--gcc/print-rtl.c17
-rw-r--r--gcc/recog.c32
-rw-r--r--gcc/reg-notes.def35
-rw-r--r--gcc/regstat.c3
-rw-r--r--gcc/rtl.def4
-rw-r--r--gcc/rtl.h2
-rw-r--r--gcc/sel-sched-ir.c4
-rw-r--r--gcc/sel-sched.c20
-rw-r--r--gcc/system.h4
-rw-r--r--gcc/target-def.h2
-rw-r--r--gcc/target.h6
-rw-r--r--gcc/testsuite/ChangeLog280
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/auto14.C29
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist13.C5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist15.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist16.C12
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist17.C9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist18.C19
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist19.C8
-rw-r--r--gcc/testsuite/g++.dg/ext/packed6.C2
-rw-r--r--gcc/testsuite/g++.dg/init/ref15.C4
-rw-r--r--gcc/testsuite/g++.dg/opt/memcpy1.C2
-rw-r--r--gcc/testsuite/g++.dg/plugin/attribute_plugin.c2
-rw-r--r--gcc/testsuite/g++.dg/plugin/dumb_plugin.c2
-rw-r--r--gcc/testsuite/g++.dg/plugin/selfassign.c2
-rw-r--r--gcc/testsuite/g++.dg/pr37742.C2
-rw-r--r--gcc/testsuite/g++.dg/template/access11.C2
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-1.C18
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-2.C18
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-3.C20
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-4.C22
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-5.C22
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-6.C22
-rw-r--r--gcc/testsuite/g++.dg/template/canon-type-7.C21
-rw-r--r--gcc/testsuite/g++.dg/template/spec36.C16
-rw-r--r--gcc/testsuite/g++.dg/template/typedef18.C24
-rw-r--r--gcc/testsuite/g++.dg/template/typedef19.C21
-rw-r--r--gcc/testsuite/g++.dg/template/typedef20.C27
-rw-r--r--gcc/testsuite/g++.dg/torture/20070621-1.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr34222.C2
-rw-r--r--gcc/testsuite/g++.dg/torture/pr34850.C2
-rw-r--r--gcc/testsuite/g++.dg/tree-ssa/pr22444.C4
-rw-r--r--gcc/testsuite/g++.dg/warn/Wcast-qual2.C167
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/array1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash64.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/new3.C2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20000211-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20010328-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20030320-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20030405-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20030902-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20060202-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20080613-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/920428-2.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/980329-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/980816-1.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr32584.c7
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr33173.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr33382.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr34334.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr34688.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr35043.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr37669.c2
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40252.c6
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40291.c7
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/sra-1.c75
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20090527-1.c38
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/align-nest.c28
-rw-r--r--gcc/testsuite/gcc.dg/20050629-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/Wcxx-compat-11.c21
-rw-r--r--gcc/testsuite/gcc.dg/cast-qual-3.c167
-rw-r--r--gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/19940712-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/cpp/Wmissingdirs.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/Wsignprom.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/Wtrigraphs-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/Wtrigraphs.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/arith-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/arith-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/assert2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/cpp.exp2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/escape-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/escape.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/extratokens.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/extratokens2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/if-mpar.c1
-rw-r--r--gcc/testsuite/gcc.dg/cpp/include2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/include2a.c4
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macspace1.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/macspace2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/missing-header-1.c3
-rw-r--r--gcc/testsuite/gcc.dg/cpp/poison.c3
-rw-r--r--gcc/testsuite/gcc.dg/cpp/pr29612-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/redef2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/strify2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/syshdr.c3
-rw-r--r--gcc/testsuite/gcc.dg/cpp/sysmac2.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/tr-warn1.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/tr-warn3.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/tr-warn4.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/tr-warn5.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/tr-warn6.c2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/trad/trad.exp2
-rw-r--r--gcc/testsuite/gcc.dg/cpp/unc4.c1
-rw-r--r--gcc/testsuite/gcc.dg/cpp/undef2.c4
-rw-r--r--gcc/testsuite/gcc.dg/memcpy-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/counter-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/pch/valid-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/pch/valid-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/pch/warn-1.c4
-rw-r--r--gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/plugin/ggcplug.c112
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp4
-rw-r--r--gcc/testsuite/gcc.dg/plugin/selfassign.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr33667.c2
-rw-r--r--gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_pointer.c4
-rw-r--r--gcc/testsuite/gcc.dg/torture/pr39204.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/inline-3.c1
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr36908.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/pr38250.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sra-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sra-2.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sra-3.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sra-4.c4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sra-5.c74
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sra-6.c40
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-26.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-9.c2
-rw-r--r--gcc/testsuite/gcc.dg/va-arg-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-10.c10
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-4.c6
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr40254.c39
-rw-r--r--gcc/testsuite/gcc.target/i386/pr37216.c17
-rw-r--r--gcc/testsuite/gcc.target/mips/const-anchor-1.c10
-rw-r--r--gcc/testsuite/gcc.target/mips/const-anchor-2.c9
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-30.c32
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-31.c29
-rw-r--r--gcc/testsuite/gcc.target/powerpc/altivec-types-1.c2
-rw-r--r--gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03115
-rw-r--r--gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c46
-rw-r--r--gcc/testsuite/gfortran.dg/elemental_dependency_1.f906
-rw-r--r--gcc/testsuite/gfortran.dg/leadz_trailz_1.f90133
-rw-r--r--gcc/testsuite/gfortran.dg/leadz_trailz_2.f9036
-rw-r--r--gcc/testsuite/gfortran.dg/nullify_4.f908
-rw-r--r--gcc/testsuite/gfortran.dg/pr25923.f902
-rw-r--r--gcc/testsuite/gfortran.dg/vector_subscript_4.f902
-rw-r--r--gcc/testsuite/gnat.dg/alignment6.adb2
-rw-r--r--gcc/testsuite/gnat.dg/misaligned_nest.adb26
-rw-r--r--gcc/testsuite/gnat.dg/nested_float_packed.ads24
-rw-r--r--gcc/testsuite/gnat.dg/oconst1.adb18
-rw-r--r--gcc/testsuite/gnat.dg/oconst1.ads25
-rw-r--r--gcc/testsuite/gnat.dg/oconst2.adb15
-rw-r--r--gcc/testsuite/gnat.dg/oconst2.ads23
-rw-r--r--gcc/testsuite/gnat.dg/oconst3.adb16
-rw-r--r--gcc/testsuite/gnat.dg/oconst3.ads26
-rw-r--r--gcc/testsuite/gnat.dg/oconst4.adb24
-rw-r--r--gcc/testsuite/gnat.dg/oconst4.ads66
-rw-r--r--gcc/testsuite/gnat.dg/oconst5.adb15
-rw-r--r--gcc/testsuite/gnat.dg/oconst5.ads27
-rw-r--r--gcc/testsuite/gnat.dg/oconst6.ads18
-rw-r--r--gcc/testsuite/gnat.dg/pack9.adb2
-rw-r--r--gcc/testsuite/gnat.dg/test_oconst.adb13
-rw-r--r--gcc/testsuite/lib/gcc-dg.exp33
-rw-r--r--gcc/testsuite/lib/target-supports.exp12
-rw-r--r--gcc/toplev.c6
-rw-r--r--gcc/tree-data-ref.c21
-rw-r--r--gcc/tree-dfa.c29
-rw-r--r--gcc/tree-flow.h2
-rw-r--r--gcc/tree-inline.c4
-rw-r--r--gcc/tree-pretty-print.c221
-rw-r--r--gcc/tree-sra.c4811
-rw-r--r--gcc/tree-ssa-alias.c178
-rw-r--r--gcc/tree-ssa-alias.h39
-rw-r--r--gcc/tree-ssa-ccp.c43
-rw-r--r--gcc/tree-ssa-copy.c73
-rw-r--r--gcc/tree-ssa-live.c30
-rw-r--r--gcc/tree-ssa-loop-ivopts.c121
-rw-r--r--gcc/tree-ssa-operands.c10
-rw-r--r--gcc/tree-ssa-pre.c52
-rw-r--r--gcc/tree-ssa-sccvn.c267
-rw-r--r--gcc/tree-ssa-sccvn.h9
-rw-r--r--gcc/tree-ssa-structalias.c3
-rw-r--r--gcc/tree-vect-data-refs.c20
-rw-r--r--gcc/tree-vect-loop-manip.c26
-rw-r--r--gcc/tree-vect-loop.c35
-rw-r--r--gcc/tree-vect-slp.c7
-rw-r--r--gcc/tree-vect-stmts.c8
-rw-r--r--gcc/tree-vectorizer.c9
-rw-r--r--gcc/tree-vectorizer.h46
-rw-r--r--gcc/tree.c3
-rw-r--r--gcc/tree.h7
-rw-r--r--gcc/unwind-dw2.c27
-rw-r--r--gcc/varasm.c742
365 files changed, 12185 insertions, 5915 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index b861286af48..67e87e1a1a8 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,1105 @@
+2009-06-02 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * config/sh/sh.c: Revert last change.
+ (sh_expand_epilogue): Emit a blockage insn before the frame
+ pointer adjustment unconditionally.
+
+2009-06-02 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ * config/pa/pa-hpux.h (LINK_SPEC): Remove "%<fwhole-program".
+ * config/pa/pa-hpux10.h (LINK_SPEC): Likewise.
+ * config/pa/pa-hpux11.h (LINK_SPEC): Likewise.
+ * gcc.c (set_collect_gcc_options): Don't add -fwhole-program
+ to COLLECT_GCC_OPTIONS.
+
+2009-06-02 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ * collect2.c (target_system_root): New variable.
+ (main): Handle --sysroot=.
+ (ignore_library): Strip the sysroot from the library path.
+
+2009-06-02 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ * Makefile.in (COLLECT2_OBJS): Add collect2-aix.o.
+ (collect2.o): Depend on collect2-aix.h.
+ (collect2-aix.o): New rule.
+ * collect2-aix.h: New file.
+ * collect2-aix.c: Likewise.
+ * collect2.c: Include collect2-aix.h. Don't undefine
+ OBJECT_FORMAT_COFF if CROSS_AIX_SUPPORT is defined.
+ Guard native includes with #ifndef CROSS_DIRECTORY_STRUCTURE.
+ Use TARGET_AIX_VERSION instead of _AIX51.
+ * config/rs6000/aix43.h (TARGET_AIX_VERSION): Define.
+ * config/rs6000/aix51.h (TARGET_AIX_VERSION): Likewise.
+ * config/rs6000/aix52.h (TARGET_AIX_VERSION): Likewise.
+ * config/rs6000/aix53.h (TARGET_AIX_VERSION): Likewise.
+ * config/rs6000/aix61.h (TARGET_AIX_VERSION): Likewise.
+
+2009-06-02 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ * collect2.c (ignore_library): Avoid premature post-increment
+ and null deference.
+
+2009-06-02 Richard Sandiford <r.sandiford@uk.ibm.com>
+
+ * Makefile.in (libgcc.mvars): Add TARGET_SYSTEM_ROOT.
+ * config/rs6000/aix.h (LINK_SYSCALLS_SPEC): Add %R to the
+ !CROSS_DIRECTORY_STRUCTURE alternative and use it for
+ CROSS_DIRECTORY_STRUCTURE too.
+ (LINK_LIBG_SPEC): Likewise.
+ (LIB_SPEC): Add %R to sysroot paths.
+ * config/rs6000/aix43.h (CPP_SPEC): Add %R to sysroot paths.
+ (CPLUSPLUS_CPP_SPEC, LIB_SPEC): Likewise.
+ * config/rs6000/aix51.h: As for aix43.h.
+ * config/rs6000/aix52.h: Likewise.
+ * config/rs6000/aix53.h: Likewise.
+ * config/rs6000/aix61.h: Likewise.
+ * config/rs6000/t-aix52 (SHLIB_LINK): Add $(TARGET_SYSTEM_ROOT)
+ to the beginning of sysroot paths.
+
+2009-06-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * print_rtl (print_rtx): Don't print modes in EXPR_LISTs and
+ INSN_LISTs that are out of the REG_NOTE range.
+
+2009-06-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * loop-unroll.c (struct iv_to_split): Add pointer to next.
+ (struct var_to_expand): Likewise.
+ (struct opt_info): Add head and tail for linked lists of the above.
+ (analyze_insn_to_expand_var): Initialize next.
+ (analyze_iv_to_split_insn): Likewise.
+ (analyze_insns_in_loop): Create linked lists.
+ (allocate_basic_variable): Simplify for use without hash table.
+ (insert_var_expansion_initialization): Likewise, make it type-safer.
+ (combine_var_copies_in_loop_exit): Likewise.
+ (apply_opt_in_copies): Walk lists rather than hash tables.
+ (release_var_copies): Simplified and inlined by hand into...
+ (free_opt_info): ... this function.
+
+2009-06-02 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Use DECL_SIZE
+ for field decls.
+
+2009-06-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * cfgexpand.c (gimple_expand_cfg): Discard the source location
+ only for builtins that are not overridden.
+
+2009-06-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * gengtype.c (adjust_field_rtx_def): Add NOTE_INSN_DELETED_LABEL's
+ label string.
+
+2009-06-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * df-core.c (df_ref_debug): Honor -fdump-noaddr.
+
+2009-06-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * combine.c (move_deaths): Compare LUIDs within the same BB only.
+
+2009-06-02 Alexandre Oliva <aoliva@redhat.com>
+
+ * common.opt (fdump-unnumbered-links): New.
+ * doc/invoke.texi (-fdump-unnumbered-links): Document it.
+ * print-rtl.c (flag_dump_unnumbered_links): New.
+ (print_rtx): Test it.
+
+2009-06-02 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm.c (arm_get_frame_offsets): Prefer using r3 for padding a
+ push/pop multiple to 8-byte alignment.
+
+2009-06-01 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (queued_cfa_restores): New static variable.
+ (ix86_add_cfa_restore_note, ix86_add_queued_cfa_restore_notes): New
+ functions.
+ (pro_epilogue_adjust_stack): Call ix86_add_queued_cfa_restore_notes.
+ (ix86_emit_restore_reg_using_pop): Add RED_OFFSET argument.
+ Set RTX_FRAME_RELATED_P immediately after adding a REG_CFA_* note.
+ Call ix86_add_cfa_restore_note instead of adding REG_CFA_OFFSET
+ note unconditionally.
+ (ix86_emit_restore_regs_using_mov): Likewise.
+ (ix86_emit_restore_sse_regs_using_mov): Likewise.
+ (ix86_emit_restore_regs_using_pop): Add RED_OFFSET argument, pass
+ it through to ix86_emit_restore_reg_using_pop.
+ (ix86_emit_leave): Add RED_OFFSET argument. Call
+ ix86_add_queued_cfa_restore_notes. Call ix86_add_cfa_restore_note
+ instead of adding REG_CFA_OFFSET note unconditionally.
+ (ix86_expand_epilogue): Compute RED_OFFSET, pass it down to
+ the above functions. Call ix86_add_queued_cfa_restore_notes when
+ needed.
+
+ * dwarf2out.c (dwarf2out_cfi_label): Add FORCE argument, if true,
+ force output of the label even for dwarf2out_do_cfi_asm.
+ (add_fde_cfi): If -g2 and above and cfi might change CFA,
+ force creation of CFI label and chain DW_CFA_set_loc jumping to it
+ for convert_cfa_to_fb_loc_list. Adjust other dwarf2out_cfi_label
+ caller.
+ (dwarf2out_stack_adjust, dwarf2out_frame_debug,
+ dwarf2out_begin_epilogue, dwarf2out_frame_debug_restore_state): Adjust
+ dwarf2out_cfi_label callers.
+ * tree.h (dwarf2out_cfi_label): Adjust prototype.
+ * config/arm/arm.c (thumb_pushpop, thumb1_output_function_prologue):
+ Adjust dwarf2out_cfi_label callers.
+ * config/vax/vax.c (vax_output_function_prologue): Likewise.
+
+ * config/i386/i386.h (struct machine_cfa_state,
+ struct machine_function): Guard with ifndef USED_FOR_TARGET
+ instead of not IN_LIBGCC2 and not in IN_TARGET_LIBS.
+
+ PR other/40024
+ * emutls.c (__emutls_get_address): Change arr->size to mean number
+ of allocated arr->data entries instead of # of slots + 1.
+
+ PR middle-end/40316
+ * recog.c (peep2_reinit_state): New function.
+ (peephole2_init_state): Use it at the end of a basic block and also
+ when seeing a RTX_FRAME_RELATED_P insn.
+
+2009-06-01 Steve Ellcey <sje@cup.hp.com>
+
+ * ia64.md (floatdirf2, fix_truncrfdi, floatunsdirf,
+ fixuns_truncrfdi2): New.
+ (fix_truncxfdi2_alts, fixuns_truncxfdi2_alts,
+ *nmaddsf4_alts, *nmadddf4_alts, *nmadddf4_truncsf_alts,
+ *mulxf3_alts, *mulxf3_truncsf_alts, *mulxf3_truncdf_alts,
+ *maddxf4_alts, *maddxf4_alts_truncsf, *maddxf4_alts_truncdf,
+ *nmaddxf4_alts, *nmaddxf4_truncsf_alts, *nmaddxf4_truncdf_alts,
+ *recip_approx): Remove.
+ (divsi3 modsi3, udivsi3, umodsi3, divsi3_internal, divdi3,
+ moddi3, udivdi3, umoddi3, divdi3_internal_lat, divdi3_internal_thr,
+ divsf3, sqrtsf2, divdf3, sqrtdf2, divxf3, sqrtxf2): Modify and
+ move to div.md.
+ * div.md (fix_truncrfdi2_alts, fixuns_truncrfdi2_alt,
+ setf_exp_rf): New.
+
+2009-06-01 Ian Lance Taylor <iant@google.com>
+
+ * attribs.c (register_attribute): Use CONST_CAST.
+ * collect2.c (main): Use CONST_CAST2.
+ (scan_prog_file): Likewise.
+ * gcc.c (process_command, main): Likewise.
+ * toplev.c (toplev_main): Likewise.
+
+ * c-typeck.c (handle_warn_cast_qual): New static function,
+ partially broken out of build_c_cast.
+ (build_c_cast): Call handle_warn_cast_qual.
+ * doc/invoke.texi (Warning Options): Document new effect of
+ -Wcast-qual.
+
+2009-06-01 Aldy Hernandez <aldyh@redhat.com>
+
+ * diagnostic.c (diagnostic_build_prefix): Always print columns.
+ (diagnostic_report_current_module): Print columns.
+ * common.opt (flag_show_column): Enable by default.
+
+2009-06-01 Luis Machado <luisgpm@br.ibm.com>
+
+ * alias.c (find_base_term): Check for NULL term before returning.
+
+2009-06-01 Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ Revert due to PR40320:
+
+ 2009-06-01 Maxim Kuvyrkov <maxim@codesourcery.com>
+ * calls.c (emit_library_call_value_1): Don't force_operand for move
+ and push insns.
+
+2009-06-01 Olivier Hainque <hainque@adacore.com>
+ Eric Botcazou <botcazou@adacore.com>
+
+ * tree.h (CONSTRUCTOR_BITFIELD_P): True if NODE, a FIELD_DECL, is
+ to be processed as a bitfield for constructor output purposes.
+ * output.h (initializer_constant_valid_for_bitfield_p): Declare
+ new function.
+ * varasm.c (oc_local_state): New type, output_constructor
+ local state to support communication with helpers.
+ (oc_outer_state): New type, output_constructor outer state of
+ relevance in recursive calls.
+ (output_constructor_array_range): New output_constructor helper,
+ extracted code for an array range element.
+ (output_constructor_regular_field): New output_constructor helper,
+ extracted code for an element that is not a bitfield.
+ (output_constructor_bitfield): New output_constructor helper,
+ extracted code for a bitfield element. Accept an OUTER state
+ argument for recursive processing. Recurse on record or array
+ CONSTRUCTOR values, possibly past noop conversions.
+ (initializer_constant_valid_for_bitfield_p): New predicate. Whether
+ VALUE is a valid constant-valued expression for use in a static
+ bit-field initializer.
+ (output_constructor): Rework to use helpers. Accept and honor an
+ OUTER state argument for recursive calls. Return total size. Be
+ prepared for nested constructors initializing bitfields.
+ (output_constant): Feed OUTER in calls to output_constructor.
+
+2009-06-01 Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ * calls.c (emit_library_call_value_1): Don't force_operand for move
+ and push insns.
+
+2009-06-01 Nick Clifton <nickc@redhat.com>
+
+ * doc/invoke.texi (IA-64 Options): Fix typo.
+
+2009-06-01 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/39129
+ * tree-vect-loop-manip.c (conservative_cost_threshold): Change the
+ printed message.
+ (vect_do_peeling_for_loop_bound): Use
+ LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT and
+ LOOP_REQUIRES_VERSIONING_FOR_ALIAS macros.
+ (vect_loop_versioning): Likewise.
+ (vect_create_cond_for_alias_checks): Fix indentation.
+ * tree-vectorizer.h (struct _loop_vec_info): Fix indentation of the
+ macros.
+ (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT): Define.
+ (LOOP_REQUIRES_VERSIONING_FOR_ALIAS): Likewise.
+ * tree-vect-loop.c (vect_analyze_loop_form): Change "too many BBs" to
+ "control flow in loop".
+ (vect_estimate_min_profitable_iters): Use
+ LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT and
+ LOOP_REQUIRES_VERSIONING_FOR_ALIAS macros.
+ * tree-vect-data-refs.c (vect_enhance_data_refs_alignment): Likewise.
+ (vect_create_data_ref_ptr): Don't mention array dimension in printing.
+ * tree-vect-stmts.c (vectorizable_store): Replace the check that the
+ statement belongs to a group of strided accesses with the exact code
+ check.
+ (vectorizable_load): Likewise.
+ * tree-vect-slp.c (vect_analyze_slp_instance): Spell out "basic block".
+ (vect_slp_analyze_bb, vect_slp_transform_bb): Likewise.
+
+2009-06-01 Gerald Pfeifer <gerald@pfeifer.com>
+
+ * config/freebsd-stdint.h: New file.
+ * config.gcc (*-*-freebsd): Set use_gcc_stdint=wrap.
+ Add freebsd-stdint.h to tm_file.
+
+2009-06-01 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm/thumb2.md (thumb2_zero_extendhidi2): New insn and split.
+ (thumb2_extendhidi2): Likewise.
+
+2009-05-31 Ian Lance Taylor <iant@google.com>
+
+ * regstat.c (regstat_n_sets_and_refs): Remove duplicate
+ definition.
+
+2009-05-31 Ian Lance Taylor <iant@google.com>
+
+ * Makefile.in (except.o): Depend upon gt-except.h, not
+ gt-$(EXCEPT_H).
+ (ipa-cp.o): Depend upon $(FIBHEAP_H) and $(PARAMS_H).
+ (ipa-reference.o): Depend upon gt-ipa-reference.h.
+
+2009-05-31 Jason Merrill <jason@redhat.com>
+
+ * tree-pretty-print.c (print_call_name): Take the callee, not the
+ call itself. Make non-static. Use dump_function_name for
+ functions.
+ (dump_generic_node): Adjust.
+ * diagnostic.h: Declare print_call_name.
+ * gimple-pretty-print.c (dump_gimple_call): Use it.
+
+2009-05-31 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * config/sh/sh.md (ashldi3_std): New define_expand.
+ (ashldi3): Use it.
+
+2009-05-31 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ PR target/40313
+ * config/sh/sh.c: Include debug.h.
+ (sh_expand_epilogue): Emit a blockage insn before the frame
+ pointer adjustment also when dwarf2out_do_frame returns true.
+
+2009-05-31 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm/thumb2.md (thumb2_extendsidi2): Add a split sub-pattern.
+ (thumb2_extendqidi2): New pattern.
+
+2009-05-31 Ira Rosen <irar@il.ibm.com>
+
+ * tree-vect-loop-manip.c (slpeel_update_phi_nodes_for_guard1): Don't
+ mark phis for renaming.
+ * tree-vectorizer.c (vect_memsyms_to_rename): Remove.
+ (vectorize_loops): Don't allocate and free vect_memsyms_to_rename.
+ Call mark_sym_for_renaming.
+ * tree-vectorizer.h (vect_memsyms_to_rename): Remove.
+ * tree-vect-loop.c (vect_transform_loop): Remove vect_memsyms_to_rename
+ initialization and a call to mark_set_for_renaming.
+
+2009-05-31 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40304
+ * config/i386/i386.c (pro_epilogue_adjust_stack): Mark insns
+ frame related even if !set_cfa && style < 0.
+
+2009-05-30 Kai Tietz <kai.tietz@onevision.com>
+
+ * config/i386/mingw-tls.c: New file.
+ * config/i386/t-gthr-win32 (LIB2FUNCS_EXTRA): Add
+ mingw-tls.c file.
+ * gthr-win32.h (MINGW32_SUPPORTS_MT_EH): Define
+ it for targets defining _WIN32 but not __CYGWIN__.
+
+2009-05-29 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * configure.ac: Add MPC support.
+
+ * config.in, configure: Regenerate.
+
+2009-05-29 Richard Henderson <rth@redhat.com>
+
+ * cfgcleanup.c (try_crossjump_to_edge): Only skip past
+ NOTE_INSN_BASIC_BLOCK.
+ * cfglayout.c (duplicate_insn_chain): Copy epilogue insn marks.
+ Duplicate NOTE_INSN_EPILOGUE_BEG notes.
+ * cfgrtl.c (can_delete_note_p): Allow NOTE_INSN_EPILOGUE_BEG
+ to be deleted.
+ * dwarf2out.c (struct cfa_loc): Change indirect field to bitfield,
+ add in_use field.
+ (add_cfi): Disable check redefining cfa away from drap.
+ (lookup_cfa_1): Add remember argument; handle remember/restore.
+ (lookup_cfa): Pass remember argument.
+ (cfa_remember): New.
+ (compute_barrier_args_size_1): Remove sibcall check.
+ (dwarf2out_frame_debug_def_cfa): New.
+ (dwarf2out_frame_debug_adjust_cfa): New.
+ (dwarf2out_frame_debug_cfa_offset): New.
+ (dwarf2out_frame_debug_cfa_register): New.
+ (dwarf2out_frame_debug_cfa_restore): New.
+ (dwarf2out_frame_debug): Handle REG_CFA_* notes.
+ (dwarf2out_begin_epilogue): New.
+ (dwarf2out_frame_debug_restore_state): New.
+ (dw_cfi_oprnd1_desc): Handle DW_CFA_remember_state,
+ DW_CFA_restore_state.
+ (output_cfi_directive): Likewise.
+ (convert_cfa_to_fb_loc_list): Likewise.
+ (dw_cfi_oprnd1_desc): Handle DW_CFA_restore.
+ * dwarf2out.h: Update.
+ * emit-rtl.c (try_split): Don't split RTX_FRAME_RELATED_P.
+ (copy_insn_1): Early out for null.
+ * final.c (final_scan_insn): Call dwarf2out_begin_epilogue
+ and dwarf2out_frame_debug_restore_state.
+ * function.c (prologue, epilogue, sibcall_epilogue): Remove.
+ (prologue_insn_hash, epilogue_insn_hash): New.
+ (free_after_compilation): Adjust freeing accordingly.
+ (record_insns): Create hash table if needed; push insns into
+ hash instead of array.
+ (maybe_copy_epilogue_insn): New.
+ (contains): Search hash table instead of array.
+ (sibcall_epilogue_contains): Remove.
+ (thread_prologue_and_epilogue_insns): Split eh_return insns
+ and mark them as epilogues.
+ (reposition_prologue_and_epilogue_notes): Rewrite epilogue
+ scanning in terms of basic blocks.
+ * insn-notes.def (CFA_RESTORE_STATE): New.
+ * jump.c (returnjump_p_1): Accept EH_RETURN.
+ (eh_returnjump_p_1, eh_returnjump_p): New.
+ * reg-notes.def (CFA_DEF_CFA, CFA_ADJUST_CFA, CFA_OFFSET,
+ CFA_REGISTER, CFA_RESTORE): New.
+ * rtl.def (EH_RETURN): New.
+ * rtl.h (eh_returnjump_p, maybe_copy_epilogue_insn): Declare.
+
+ * config/bfin/bfin.md (UNSPEC_VOLATILE_EH_RETURN): Remove.
+ (eh_return_internal): Use eh_return rtx; split w/ epilogue.
+
+ * config/i386/i386.c (gen_push): Update cfa state.
+ (pro_epilogue_adjust_stack): Add set_cfa argument. When true,
+ add a CFA_ADJUST_CFA note.
+ (ix86_dwarf_handle_frame_unspec): Remove.
+ (ix86_expand_prologue): Update cfa state.
+ (ix86_emit_restore_reg_using_pop): New.
+ (ix86_emit_restore_regs_using_pop): New.
+ (ix86_emit_leave): New.
+ (ix86_emit_restore_regs_using_mov): Add CFA_RESTORE notes.
+ (ix86_expand_epilogue): Add notes for unwinding the epilogue.
+ * config/i386/i386.h (struct machine_cfa_state): New.
+ (ix86_cfa_state): New.
+ * config/i386/i386.md (UNSPEC_EH_RETURN): Remove.
+ (eh_return_internal): Merge from eh_return_<mode>,
+ use eh_return rtx, split w/ epilogue.
+
+2009-05-29 Ian Lance Taylor <iant@google.com>
+
+ * builtins.c (validate_gimple_arglist): Don't use va_arg with
+ enum type.
+ * calls.c (emit_library_call_value_1): Likewise.
+
+ * c-typeck.c (c_build_va_arg): New function.
+ * c-tree.h (c_build_va_arg): Declare.
+ * c-parser.c (c_parser_postfix_expression): Call c_build_va_arg
+ instead of build_va_arg.
+
+2009-05-29 Eric Botcazou <ebotcazou@adacore.com>
+
+ * tree-ssa-loop-ivopts.c (strip_offset_1) <MULT_EXPR>: New case.
+ (force_expr_to_var_cost) <NEGATE_EXPR>: Likewise.
+ (ptr_difference_cost): Use affine combinations to compute it.
+ (difference_cost): Likewise.
+ (get_computation_cost_at): Compute more accurate cost for addresses
+ if the ratio is a multiplier allowed in addresses.
+ For non-addresses, consider that an additional offset or symbol is
+ added only once.
+
+2009-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.c (ix86_decompose_address): Avoid useless
+ 0 displacement. Add 0 displacement if base is %[er]bp or %r13.
+
+ * config/i386/i386.md (prefix_data16, prefix_rep): Set to 0 for
+ TYPE_SSE{MULADD,4ARG,IADD1,CVT1} by default.
+ (prefix_rex): For UNIT_MMX don't imply the prefix by default
+ if MODE_DI.
+ (prefix_extra): Default to 2 for TYPE_SSE{MULADD,4ARG} and
+ to 1 for TYPE_SSE{IADD1,CVT1}.
+ (prefix_vex_imm8): Removed.
+ (length_vex): Only pass 1 as second argument to
+ ix86_attr_length_vex_default if prefix_extra is 0.
+ (modrm): For TYPE_INCDEC only set to 0 if not TARGET_64BIT.
+ (length): For prefix vex computation use length_immediate
+ attribute instead of prefix_vex_imm8.
+ (cmpqi_ext_3_insn, cmpqi_ext_3_insn_rex64,
+ addqi_ext_1, addqi_ext_1_rex64, *testqi_ext_0, andqi_ext_0,
+ *andqi_ext_0_cc, *iorqi_ext_0, *xorqi_ext_0, *xorqi_cc_ext_1,
+ *xorqi_cc_ext_1_rex64): Override modrm attribute to 1.
+ (extendsidi2_rex64, extendhidi2, extendqidi2, extendhisi2,
+ *extendhisi2_zext, extendqihi2, extendqisi2, *extendqisi2_zext): Emit
+ a space in between the operands.
+ (*anddi_1_rex64, *andsi_1): Likewise. Override prefix_rex to 1
+ if one operand is 0xff and the other one si, di, bp or sp.
+ (*andhi_1): Override prefix_rex to 1 if one operand is 0xff and the
+ other one si, di, bp or sp.
+ (*btsq, *btrq, *btcq, *btdi_rex64, *btsi): Add mode attribute.
+ (*ffssi_1, *ffsdi_1, ctzsi2, ctzdi2): Add
+ type and mode attributes.
+ (*bsr, *bsr_rex64, *bsrhi): Add type attribute.
+ (*cmpfp_i_mixed, *cmpfp_iu_mixed): For TYPE_SSECOMI, clear
+ prefix_rep attribute and set prefix_data16 attribute iff MODE_DF.
+ (*cmpfp_i_sse, *cmpfp_iu_sse): Clear prefix_rep attribute and set
+ prefix_data16 attribute iff MODE_DF.
+ (*movsi_1): For TYPE_SSEMOV MODE_SI set prefix_data16 attribute.
+ (fix_trunc<mode>di_sse): Set prefix_rex attribute.
+ (*adddi_4_rex64, *addsi_4): Use const128_operand instead of
+ constm128_operand in length_immediate computation.
+ (*addhi_4): Likewise. Fix mode attribute to MODE_HI.
+ (anddi_1_rex64): Use movzbl/movzwl instead of movzbq/movzwq.
+ (*avx_ashlti3, sse2_ashlti3, *avx_lshrti3, sse2_lshrti3): Set
+ length_immediate attribute to 1.
+ (x86_fnstsw_1, x86_fnstcw_1, x86_fldcw_1): Fix length attribute.
+ (*movdi_1_rex64): Override prefix_rex or prefix_data16 attributes
+ for certain alternatives.
+ (*movdf_nointeger, *movdf_integer_rex64, *movdf_integer): Override
+ prefix_data16 attribute if MODE_V1DF.
+ (*avx_setcc<mode>, *sse_setcc<mode>, *sse5_setcc<mode>): Set
+ length_immediate to 1.
+ (set_got_rex64, set_rip_rex64): Remove length attribute, set
+ length_address to 4, set mode attribute to MODE_DI.
+ (set_got_offset_rex64): Likewise. Set length_immediate to 0.
+ (fxam<mode>2_i387): Set length attribute to 4.
+ (*prefetch_sse, *prefetch_sse_rex, *prefetch_3dnow,
+ *prefetch_3dnow_rex): Override length_address attribute.
+ (sse4_2_crc32<mode>): Override prefix_data16 and prefix_rex
+ attributes.
+ * config/i386/predicates.md (ext_QIreg_nomode_operand): New predicate.
+ (constm128_operand): Removed.
+ * config/i386/i386.c (memory_address_length): For
+ disp && !index && !base in 64-bit mode account for SIB byte if
+ print_operand_address can't optimize disp32 into disp32(%rip)
+ and UNSPEC doesn't imply (%rip) addressing. Add 1 to length
+ for fs: or gs: segment.
+ (ix86_attr_length_immediate_default): When checking if shortform
+ is possible, truncate immediate to the length of the non-shortened
+ immediate.
+ (ix86_attr_length_address_default): Ignore MEM_P operands
+ with X constraint.
+ (ix86_attr_length_vex_default): Only check for DImode on
+ GENERAL_REG_P operands.
+ * config/i386/sse.md (<sse>_comi, <sse>_ucomi): Clear
+ prefix_rep attribute, set prefix_data16 attribute iff MODE_DF.
+ (sse_cvttps2pi): Clear prefix_rep attribute.
+ (sse2_cvttps2dq, *sse2_cvtpd2dq, sse2_cvtps2pd): Clear prefix_data16
+ attribute.
+ (*sse2_cvttpd2dq): Don't clear prefix_rep attribute.
+ (*avx_ashr<mode>3, ashr<mode>3, *avx_lshr<mode>3, lshr<mode>3,
+ *avx_ashl<mode>3, ashl<mode>3): Set length_immediate attribute to 1
+ iff operand 2 is const_int_operand.
+ (*vec_dupv4si, avx_shufpd256_1, *avx_shufpd_<mode>,
+ sse2_shufpd_<mode>): Set length_immediate attribute to 1.
+ (sse2_pshufd_1): Likewise. Set prefix attribute to maybe_vex
+ instead of vex.
+ (sse2_pshuflw_1, sse2_pshufhw_1): Set length_immediate to 1 and clear
+ prefix_data16.
+ (sse2_unpckhpd, sse2_unpcklpd, sse2_storehpd, *vec_concatv2df): Set
+ prefix_data16 attribute for movlpd and movhpd instructions.
+ (sse2_loadhpd, sse2_loadlpd, sse2_movsd): Likewise. Override
+ length_immediate for shufpd instruction.
+ (sse2_movntsi, sse3_lddqu): Clear prefix_data16 attribute.
+ (avx_cmpp<avxmodesuffixf2c><mode>3,
+ avx_cmps<ssemodesuffixf2c><mode>3, *avx_maskcmp<mode>3,
+ <sse>_maskcmp<mode>3, <sse>_vmmaskcmp<mode>3,
+ avx_shufps256_1, *avx_shufps_<mode>, sse_shufps_<mode>,
+ *vec_dupv4sf_avx, *vec_dupv4sf): Set
+ length_immediate attribute to 1.
+ (*avx_cvtsi2ssq, *avx_cvtsi2sdq): Set length_vex attribute to 4.
+ (sse_cvtsi2ssq, sse2_cvtsi2sdq): Set prefix_rex attribute to 1.
+ (sse2_cvtpi2pd, sse_loadlps, sse2_storelpd): Override
+ prefix_data16 attribute for the first alternative to 1.
+ (*avx_loadlps): Override length_immediate for the first alternative.
+ (*vec_concatv2sf_avx): Override length_immediate and prefix_extra
+ attributes for second alternative.
+ (*vec_concatv2sf_sse4_1): Override length_immediate and
+ prefix_data16 attributes for second alternative.
+ (*vec_setv4sf_avx, *avx_insertps, vec_extract_lo_<mode>,
+ vec_extract_hi_<mode>, vec_extract_lo_v16hi,
+ vec_extract_hi_v16hi, vec_extract_lo_v32qi,
+ vec_extract_hi_v32qi): Set prefix_extra and length_immediate to 1.
+ (*vec_setv4sf_sse4_1, sse4_1_insertps, *sse4_1_extractps): Set
+ prefix_data16 and length_immediate to 1.
+ (*avx_mulv2siv2di3, *avx_mulv4si3, sse4_2_gtv2di3): Set prefix_extra
+ to 1.
+ (*avx_<code><mode>3, *avx_eq<mode>3, *avx_gt<mode>3): Set
+ prefix_extra attribute for variants that don't have 0f prefix
+ alone.
+ (*avx_pinsr<ssevecsize>): Likewise. Set length_immediate to 1.
+ (*sse4_1_pinsrb, *sse2_pinsrw, *sse4_1_pinsrd, *sse4_1_pextrb,
+ *sse4_1_pextrb_memory, *sse2_pextrw, *sse4_1_pextrw_memory,
+ *sse4_1_pextrd): Set length_immediate to 1.
+ (*sse4_1_pinsrd): Likewise. Set prefix_extra to 1.
+ (*sse4_1_pinsrq, *sse4_1_pextrq): Set prefix_rex and length_immediate
+ to 1.
+ (*vec_extractv2di_1_rex64_avx, *vec_extractv2di_1_rex64,
+ *vec_extractv2di_1_avx, *vec_extractv2di_1_sse2): Override
+ length_immediate to 1 for second alternative.
+ (*vec_concatv2si_avx, *vec_concatv2di_rex64_avx): Override
+ prefix_extra and length_immediate attributes for the first
+ alternative.
+ (vec_concatv2si_sse4_1): Override length_immediate to 1 for the
+ first alternative.
+ (*vec_concatv2di_rex64_sse4_1): Likewise. Override prefix_rex
+ to 1 for the first and third alternative.
+ (*vec_concatv2di_rex64_sse): Override prefix_rex to 1 for the second
+ alternative.
+ (*sse2_maskmovdqu, *sse2_maskmovdqu_rex64): Override length_vex
+ attribute.
+ (*sse_sfence, sse2_mfence, sse2_lfence): Override length_address
+ attribute to 0.
+ (*avx_phaddwv8hi3, *avx_phadddv4si3, *avx_phaddswv8hi3,
+ *avx_phsubwv8hi3, *avx_phsubdv4si3, *avx_phsubswv8hi,
+ *avx_pmaddubsw128, *avx_pmulhrswv8hi3, *avx_pshufbv16qi3,
+ *avx_psign<mode>3): Set prefix_extra attribute to 1.
+ (ssse3_phaddwv4hi3, ssse3_phadddv2si3, ssse3_phaddswv4hi3,
+ ssse3_phsubwv4hi3, ssse3_phsubdv2si3, ssse3_phsubswv4hi3,
+ ssse3_pmaddubsw, *ssse3_pmulhrswv4hi, ssse3_pshufbv8qi3,
+ ssse3_psign<mode>3): Override prefix_rex attribute.
+ (*avx_palignrti): Override prefix_extra and length_immediate
+ to 1.
+ (ssse3_palignrti): Override length_immediate to 1.
+ (ssse3_palignrdi): Override length_immediate to 1, override
+ prefix_rex attribute.
+ (abs<mode>2): Override prefix_rep to 0, override prefix_rex
+ attribute.
+ (sse4a_extrqi): Override length_immediate to 2.
+ (sse4a_insertqi): Likewise. Override prefix_data16 to 0.
+ (sse4a_insertq): Override prefix_data16 to 0.
+ (avx_blendp<avxmodesuffixf2c><avxmodesuffix>,
+ avx_blendvp<avxmodesuffixf2c><avxmodesuffix>,
+ avx_dpp<avxmodesuffixf2c><avxmodesuffix>, *avx_mpsadbw,
+ *avx_pblendvb, *avx_pblendw, avx_roundp<avxmodesuffixf2c>256,
+ avx_rounds<avxmodesuffixf2c>256): Override prefix_extra
+ and length_immediate to 1.
+ (sse4_1_blendp<ssemodesuffixf2c>, sse4_1_dpp<ssemodesuffixf2c>,
+ sse4_2_pcmpestr, sse4_2_pcmpestri, sse4_2_pcmpestrm,
+ sse4_2_pcmpestr_cconly, sse4_2_pcmpistr, sse4_2_pcmpistri,
+ sse4_2_pcmpistrm, sse4_2_pcmpistr_cconly): Override prefix_data16
+ and length_immediate to 1.
+ (sse4_1_blendvp<ssemodesuffixf2c>): Override prefix_data16 to 1.
+ (sse4_1_mpsadbw, sse4_1_pblendw): Override length_immediate to 1.
+ (*avx_packusdw, avx_vtestp<avxmodesuffixf2c><avxmodesuffix>,
+ avx_ptest256): Override prefix_extra to 1.
+ (sse4_1_roundp<ssemodesuffixf2c>, sse4_1_rounds<ssemodesuffixf2c>):
+ Override prefix_data16 and length_immediate to 1.
+ (sse5_pperm_zero_v16qi_v8hi, sse5_pperm_sign_v16qi_v8hi,
+ sse5_pperm_zero_v8hi_v4si, sse5_pperm_sign_v8hi_v4si,
+ sse5_pperm_zero_v4si_v2di, sse5_pperm_sign_v4si_v2di,
+ sse5_vrotl<mode>3, sse5_ashl<mode>3, sse5_lshl<mode>3): Override
+ prefix_data16 to 0 and prefix_extra to 2.
+ (sse5_rotl<mode>3, sse5_rotr<mode>3): Override length_immediate to 1.
+ (sse5_frcz<mode>2, sse5_vmfrcz<mode>2): Don't override prefix_extra
+ attribute.
+ (*sse5_vmmaskcmp<mode>3, sse5_com_tf<mode>3,
+ sse5_maskcmp<mode>3, sse5_maskcmp<mode>3, sse5_maskcmp_uns<mode>3):
+ Override prefix_data16 and prefix_rep to 0, length_immediate to 1
+ and prefix_extra to 2.
+ (sse5_maskcmp_uns2<mode>3, sse5_pcom_tf<mode>3): Override
+ prefix_data16 to 0, length_immediate to 1 and prefix_extra to 2.
+ (*avx_aesenc, *avx_aesenclast, *avx_aesdec, *avx_aesdeclast,
+ avx_vpermilvar<mode>3,
+ avx_vbroadcasts<avxmodesuffixf2c><avxmodesuffix>,
+ avx_vbroadcastss256, avx_vbroadcastf128_p<avxmodesuffixf2c>256,
+ avx_maskloadp<avxmodesuffixf2c><avxmodesuffix>,
+ avx_maskstorep<avxmodesuffixf2c><avxmodesuffix>):
+ Override prefix_extra to 1.
+ (aeskeygenassist, pclmulqdq): Override length_immediate to 1.
+ (*vpclmulqdq, avx_vpermil<mode>, avx_vperm2f128<mode>3,
+ vec_set_lo_<mode>, vec_set_hi_<mode>, vec_set_lo_v16hi,
+ vec_set_hi_v16hi, vec_set_lo_v32qi, vec_set_hi_v32qi): Override
+ prefix_extra and length_immediate to 1.
+ (*avx_vzeroall, avx_vzeroupper, avx_vzeroupper_rex64): Override
+ modrm to 0.
+ (*vec_concat<mode>_avx): Override prefix_extra and length_immediate
+ to 1 for the first alternative.
+ * config/i386/mmx.md (*mov<mode>_internal_rex64): Override
+ prefix_rep, prefix_data16 and/or prefix_rex attributes in certain
+ cases.
+ (*mov<mode>_internal_avx, *movv2sf_internal_rex64,
+ *movv2sf_internal_avx, *movv2sf_internal): Override
+ prefix_rep attribute for certain alternatives.
+ (*mov<mode>_internal): Override prefix_rep or prefix_data16
+ attributes for certain alternatives.
+ (*movv2sf_internal_rex64_avx): Override prefix_rep and length_vex
+ attributes for certain alternatives.
+ (*mmx_addv2sf3, *mmx_subv2sf3, *mmx_mulv2sf3,
+ *mmx_<code>v2sf3_finite, *mmx_<code>v2sf3, mmx_rcpv2sf2,
+ mmx_rcpit1v2sf3, mmx_rcpit2v2sf3, mmx_rsqrtv2sf2, mmx_rsqit1v2sf3,
+ mmx_haddv2sf3, mmx_hsubv2sf3, mmx_addsubv2sf3,
+ *mmx_eqv2sf3, mmx_gtv2sf3, mmx_gev2sf3, mmx_pf2id, mmx_pf2iw,
+ mmx_pi2fw, mmx_floatv2si2, mmx_pswapdv2sf2, *mmx_pmulhrwv4hi3,
+ mmx_pswapdv2si2): Set prefix_extra attribute to 1.
+ (mmx_ashr<mode>3, mmx_lshr<mode>3, mmx_ashl<mode>3): Set
+ length_immediate to 1 if operand 2 is const_int_operand.
+ (*mmx_pinsrw, mmx_pextrw, mmx_pshufw_1, *vec_dupv4hi,
+ *vec_extractv2si_1): Set length_immediate
+ attribute to 1.
+ (*mmx_uavgv8qi3): Override prefix_extra attribute to 1 if
+ using old 3DNOW insn rather than SSE/3DNOW_A.
+ (mmx_emms, mmx_femms): Clear modrm attribute.
+
+2009-05-29 Martin Jambor <mjambor@suse.cz>
+
+ * tree-sra.c: New implementation of SRA.
+
+ * params.def (PARAM_SRA_MAX_STRUCTURE_SIZE): Removed.
+ (PARAM_SRA_MAX_STRUCTURE_COUNT): Removed.
+ (PARAM_SRA_FIELD_STRUCTURE_RATIO): Removed.
+ * params.h (SRA_MAX_STRUCTURE_SIZE): Removed.
+ (SRA_MAX_STRUCTURE_COUNT): Removed.
+ (SRA_FIELD_STRUCTURE_RATIO): Removed.
+ * doc/invoke.texi (sra-max-structure-size): Removed.
+ (sra-field-structure-ratio): Removed.
+
+2009-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40291
+ * builtins.c (expand_builtin_memcmp): Convert len to sizetype
+ before expansion.
+
+2009-05-29 Andrey Belevantsev <abel@ispras.ru>
+
+ PR rtl-optimization/40101
+ * sel-sched-ir.c (get_seqno_by_preds): Allow returning negative
+ seqno. Adjust comment.
+ * sel-sched.c (find_seqno_for_bookkeeping): Assert that when
+ inserting bookkeeping before a jump, the jump is not scheduled.
+ When no positive seqno found, provide a value. Add comment.
+
+2009-05-29 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-alias.c (nonaliasing_component_refs_p): Remove
+ short-cutting on the first component.
+
+2009-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/39958
+ * omp-low.c (scan_omp_1_op): Call remap_type on TREE_TYPE
+ for trees other than decls/types.
+
+2009-05-29 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-operands.c (get_expr_operands): Do not handle
+ INDIRECT_REFs in the handled-component case. Remove
+ unused get_ref_base_and_extent case.
+ * tree-dfa.c (get_ref_base_and_extent): Avoid calling
+ tree_low_cst and host_integerp where possible.
+ * tree-ssa-structalias.c (equiv_class_label_eq): Check hash
+ codes for equivalence.
+ * dce.c (find_call_stack_args): Avoid redundant bitmap queries.
+
+2009-05-29 David Billinghurst <billingd@gcc.gnu.org>
+
+ * config.gcc: Add i386/t-fprules-softfp and soft-fp/t-softfp
+ to tmake_file for i[34567]86-*-cygwin*.
+
+2009-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/40017
+ * config/rs6000/rs6000-c.c (_Bool_keyword): New variable.
+ (altivec_categorize_keyword, init_vector_keywords,
+ rs6000_cpu_cpp_builtins): Define _Bool as conditional macro
+ similar to bool.
+
+2009-05-29 Kai Tietz <kai.tietz@onevision.com>
+
+ * tree.c (handle_dll_attribute): Check if node is
+ of kind FUNCTION_DECL for DECL_DECLARED_INLINE_P check.
+
+2009-05-29 Richard Earnshaw <rearnsha@arm.com>
+
+ * config/arm/thumb2.md (thumb2_zero_extendsidi2): Add a split
+ component.
+ (thumb2_zero_extendqidi2): Likewise.
+
+2009-05-28 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * config/sh/sh.c (sh_expand_t_scc): Use gen_xorsi3_movrt
+ instead of gen_movrt.
+ * config/sh/sh.md (movrt): Remove.
+
+2009-05-28 Steve Ellcey <sje@cup.hp.com>
+
+ * doc/invoke.texi (IA-64 Options)
+ Add -msdata, -mfused-madd, -mno-inline-float-divide,
+ -mno-inline-int-divide, -mno-inline-sqrt, -msched-spec-ldc,
+ -msched-spec-control-ldc, -msched-prefer-non-data-spec-insns,
+ -msched-prefer-non-control-spec-insns,
+ -msched-stop-bits-after-every-cycle,
+ -msched-count-spec-in-critical-path,
+ -msel-sched-dont-check-control-spec, -msched-fp-mem-deps-zero-cost
+ -msched-max-memory-insns-hard-limit, -msched-max-memory-insns
+ Remove -mt, -pthread, -msched-ldc, -mno-sched-control-ldc,
+ and -msched-spec-verbose.
+
+2009-05-28 Joseph Myers <joseph@codesourcery.com>
+
+ * config/arm/lib1funcs.asm (__clear_cache): Define if
+ L_clear_cache.
+ * config/arm/linux-eabi.h (CLEAR_INSN_CACHE): Define to give an
+ error if used.
+ * config/arm/t-linux-eabi (LIB1ASMFUNCS): Add _clear_cache.
+
+2009-05-28 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-alias.c (ao_ref_init): New function.
+ (ao_ref_base): Likewise.
+ (ao_ref_base_alias_set): Likewise.
+ (ao_ref_alias_set): Likewise.
+ (refs_may_alias_p_1): Change signature.
+ (refs_may_alias_p): Adjust.
+ (refs_anti_dependent_p): Likewise.
+ (refs_output_dependent_p): Likewise.
+ (call_may_clobber_ref_p_1): Change signature.
+ (call_may_clobber_ref_p): Adjust.
+ (stmt_may_clobber_ref_p_1): New function split out from ...
+ (stmt_may_clobber_ref_p): ... here.
+ (maybe_skip_until): Adjust signature.
+ (get_continuation_for_phi): Likewise.
+ (walk_non_aliased_vuses): Likewise.
+ * tree-ssa-alias.h (struct ao_ref_s): New structure type.
+ (ao_ref_init): Declare.
+ (ao_ref_base): Likewise.
+ (ao_ref_alias_set): Likewise.
+ (stmt_may_clobber_ref_p_1): Likewise.
+ (walk_non_aliased_vuses): Adjust.
+ * tree-ssa-sccvn.c (ao_ref_init_from_vn_reference): New function.
+ (get_ref_from_reference_ops): remove.
+ (vn_reference_lookup_2): Adjust signature.
+ (vn_reference_lookup_3): Do not re-build trees. Handle unions.
+ (vn_reference_lookup_pieces): Adjust signature, do not re-build
+ trees.
+ (vn_reference_lookup): Adjust.
+ (vn_reference_insert): Likewise.
+ (vn_reference_insert_pieces): Adjust signature.
+ (visit_reference_op_call): Adjust.
+ * tree-ssa-pre.c (get_expr_type): Simplify.
+ (phi_translate_1): Adjust.
+ (compute_avail): Likewise.
+ (translate_vuse_through_block): Do not re-build trees.
+ (value_dies_in_block_x): Likewise.
+ * tree-ssa-sccvn.h (struct vn_reference_s): Add type and alias-set
+ fields.
+ (vn_reference_lookup_pieces): Adjust declaration.
+ (vn_reference_insert_pieces): Likewise.
+
+2009-05-28 Benjamin Kosnik <bkoz@redhat.com>
+
+ * tree-ssa-copy.c (replace_exp_1): Move op for warning-free use
+ with checking disabled.
+
+2009-05-28 Dave Korn <dave.korn.cygwin@gmail.com>
+
+ PR target/37216
+
+ * configure.ac (HAVE_GAS_ALIGNED_COMM): Add autoconf test and
+ macro definition for support of three-operand format aligned
+ .comm directive in assembler on cygwin/pe/mingw target OS.
+ * configure: Regenerate.
+ * config.h: Regenerate.
+
+ * config/i386/winnt.c (i386_pe_asm_output_aligned_decl_common): Use
+ aligned form of .comm directive if -mpe-aligned-commons is in effect.
+ * config/i386/cygming.opt (-mpe-aligned-commons): Add new option.
+
+ * doc/invoke.texi (-mpe-aligned-commons): Document new target option.
+ * doc/tm.texi (ASM_OUTPUT_COMMON): Document zero size commons.
+
+2009-05-28 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/40254
+ * tree-data-ref.c (dr_analyze_innermost): Take POFFSET into account
+ in analysis of basic blocks.
+
+2009-05-28 Adam Nemet <anemet@caviumnetworks.com>
+
+ PR middle-end/33699
+ * target.h (struct gcc_target): Fix indentation. Add
+ const_anchor.
+ * target-def.h (TARGET_CONST_ANCHOR): New macro.
+ (TARGET_INITIALIZER): Use it.
+ * cse.c (CHEAPER): Move it up to the other macros.
+ (insert): Rename this ...
+ (insert_with_costs): ... to this. Add cost parameters. Update
+ function comment.
+ (insert): New function. Call insert_with_costs.
+ (compute_const_anchors, insert_const_anchor, insert_const_anchors,
+ find_reg_offset_for_const, try_const_anchors): New functions.
+ (cse_insn): Call try_const_anchors. Adjust cost of src_related
+ when using a const-anchor. Call insert_const_anchors.
+ * config/mips/mips.c (mips_set_mips16_mode): Set
+ targetm.const_anchor.
+ * doc/tm.texi (Misc): Document TARGET_CONST_ANCHOR.
+
+2009-05-28 Alexandre Oliva <aoliva@redhat.com>
+
+ * tree-inline.c (remap_decls): Enable nonlocalized variables
+ when not optimizing.
+
+2009-05-28 Alexandre Oliva <aoliva@redhat.com>
+
+ * tree-ssa-live.c (remove_unused_locals): Skip when not optimizing.
+ Simplify other tests involving optimize.
+
+2009-05-27 Tom Tromey <tromey@redhat.com>
+
+ * unwind-dw2.c (_Unwind_DebugHook): New function.
+ (uw_install_context): Call _Unwind_DebugHook.
+
+2009-05-27 Tom Tromey <tromey@redhat.com>
+
+ * system.h (CONST_CAST2): Use C++ const_cast when compiled as C++
+
+2009-05-27 Ian Lance Taylor <iant@google.com>
+
+ * Makefile.in (LINKER, LINKER_FLAGS): Define.
+ (LINKER_FOR_BUILD, BUILD_LINKERFLAGS): Define.
+ (ALL_LINKERFLAGS): Define.
+ (xgcc$(exeext)): Change $(COMPILER) to $(LINKER).
+ (cpp$(exeext), cc1-dummy$(exeext), cc1$(exeext)): Likewise.
+ (collect2$(exeext), mips-tfile, mips-tdump): Likewise.
+ (gcov$(exeext), gcov-dump$(exeext)): Likewise.
+ (build/gen%$(build_exeext)): Change $(COMPILER_FOR_BUILD) to
+ $(LINKER_FOR_BUILD).
+ (build/gcov-iov$(build_exeext)): Likewise.
+
+2009-05-27 Julian Brown <julian@codesourcery.com>
+
+ * gcse.c (target.h): Include.
+ (can_assign_to_reg_without_clobbers_p): Check that the target allows
+ copy of argument to a pseudo register.
+
+2009-05-27 Diego Novillo <dnovillo@google.com>
+
+ * tree-ssa-live.c (dump_scope_block): Document arguments.
+ (dump_scope_blocks): Document.
+ (debug_scope_blocks): New.
+ * tree-flow.h (debug_scope_blocks): Declare.
+
+2009-05-21 Denis Chertykov <denisc@overta.ru>
+
+ * doc/contrib.texi (Contributors): add myself to the list.
+
+2009-05-27 Olivier Hainque <hainque@adacore.com>
+
+ * expr.c (target_align): New function. Alignment the TARGET of an
+ assignment may be assume to have.
+ (highest_pow2_factor_for_target): Use it instead of relying on
+ immediate tree attributes of TARGET, not necessarily honored when
+ intermediate bitfields are involved.
+
+2009-05-27 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/40266
+ * config/i386/driver-i386.c (host_detect_local_cpu): Support
+ AVX, SSE4, AES, PCLMUL and POPCNT.
+
+2009-05-27 Diego Novillo <dnovillo@google.com>
+
+ * tree-pretty-print.c (dump_location): New.
+ (dump_generic_node): Call it.
+ Factor code to handle BLOCK nodes ...
+ (dump_block_node): ... here.
+
+2009-05-27 Rafael Avila de Espindola <espindola@google.com>
+
+ * Makefile.in (GCC_PLUGIN_H): New. Replace all uses of gcc-plugin.h with
+ it.
+ * doc/plugins.texi: Document that gcc-plugin.h must be the first to be
+ included.
+ * gcc-plugin.h: Include config.h and system.h.
+ (IN_GCC): Define if not defined.
+
+2009-05-27 Hans-Peter Nilsson <hp@axis.com>
+
+ PR middle-end/40249
+ * Makefile.in (CRTSTUFF_CFLAGS): Replace -fno-inline-functions
+ with -fno-inline.
+
+2009-05-27 Shujing Zhao <pearly.zhao@oracle.com>
+
+ * config/m32r/m32r.c: Use REG_P, MEM_P and CONST_INT_P where
+ applicable.
+ * config/m32r/m32r.h: Ditto.
+ * config/m32r/m32r.md: Ditto.
+ * config/m32r/predicates.md: Ditto.
+
+2009-05-27 Alexandre Oliva <aoliva@redhat.com>
+
+ * cgraph.c (dump_cgraph_node): Honor -fdump-noaddr.
+
+2009-05-26 Basile Starynkevitch <basile@starynkevitch.net>
+
+ * doc/plugins.texi
+ (Loading plugins): typo.
+ (Plugin callbacks): Documented PLUGIN_INFO, PLUGIN_GGC_START,
+ PLUGIN_GGC_MARKING, PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS.
+ (Interacting with the GCC Garbage Collector): Added new section.
+ (Giving information about a plugin): Added new section for
+ PLUGIN_INFO.
+ * ggc.h (ggc_register_root_tab): Added declaration.
+ * gcc-plugin.h (PLUGIN_GGC_START, PLUGIN_GGC_MARKING)
+ (PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS): Added new events.
+ (register_callback): Improved comment in declaration.
+ * ggc-common.c (const_ggc_root_tab_t) Added new typedef for
+ vectors.
+ (extra_root_vec) Added static variable for dynamic roots
+ registration.
+ (ggc_register_root_tab) Added new routine.
+ (ggc_mark_roots) Added iteration inside extra_root_vec, and invoke
+ PLUGIN_GGC_MARKING event.
+ * ggc-zone.c: Include plugin.h.
+ (ggc_collect): Invoke PLUGIN_GGC_START & PLUGIN_GGC_END events.
+ * ggc-page.c: Include plugin.h.
+ (ggc_collect): Invoke PLUGIN_GGC_START & PLUGIN_GGC_END events.
+ * plugin.c (plugin_event_name): added names of PLUGIN_GGC_START,
+ PLUGIN_GGC_MARKING, PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS
+ (register_callback): check lack of callbacks for
+ pseudo-events. Added handling of PLUGIN_REGISTER_GGC_ROOTS,
+ PLUGIN_GGC_START, PLUGIN_GGC_MARKING, PLUGIN_GGC_END.
+ (invoke_plugin_callbacks): Handle PLUGIN_GGC_START,
+ PLUGIN_GGC_MARKING, PLUGIN_GGC_END, PLUGIN_REGISTER_GGC_ROOTS.
+ * Makefile.in (ggc-common.o, ggc-zone.o, ggc-page.o): Added
+ dependency on plugin.h.
+ (plugin.o): Added dependency on ggc.h...
+
+2009-05-26 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/40248
+ Revert
+ * expr.c (expand_expr_real_1): Avoid calling do_store_flag
+ with mismatched comparison modes.
+
+ * expr.c (expand_expr_real_1): Expand the operand of a
+ VIEW_CONVERT_EXPR in its natural mode.
+
+2009-05-26 Ian Lance Taylor <iant@google.com>
+
+ * Makefile.in (COMPILER, COMPILER_FLAGS): Define.
+ (COMPILER_FOR_BUILD, BUILD_COMPILERFLAGS): Define.
+ (ALL_COMPILERFLAGS): Define.
+ (.c.o, xgcc$(exeext), cpp$(exeext)): Use $(COMPILER).
+ (cc1-dummy$(exeext), cc1$(exeext)): Likewise.
+ (collect2$(exeext), collect2.o): Likewise.
+ (c-opts.o, c-cppbuiltin.o, c-pch.o, gcc.o, gccspec.o): Likewise.
+ (gcc-options.o, version.o, prefix.o, toplev.o): Likewise.
+ ($(out_object_file), mips-tfile, mips-tdump): Likewise.
+ (libbackend.o, intl.o, cppdefault.o): Likewise.
+ (gcov$(exeext), gcov-dump$(exeext)): Likewise.
+ (build/%.o): Use $(COMPILER_FOR_BUILD).
+ (build/gen%$(build_exeext)): Likewise.
+ (build/gcov-iov$(build_exeext)): LIkewise.
+ * config/t-darwin (darwin.o): Use $(COMPILER).
+ (darwin-c.o, darwin-f.o, darwin-driver.o): Likewise.
+ * config/t-sol2 (sol2-c.o): Likewise.
+ (sol2.o): Likewise.
+ * config/t-vxworks (vxworks.o): Likewise.
+ * config/x-darwin (host-darwin.o): Likewise.
+ * config/x-hpux (host-hpux.o): Likewise.
+ * config/x-linux (host-linux.o): Likewise.
+ * config/x-solaris (host-solaris.o): Likewise.
+ * config/alpha/x-alpha (driver-alpha.o): Likewise.
+ * config/arm/t-arm (arm-c.o): Likewise.
+ * config/arm/t-pe (pe.o): Likewise.
+ * config/arm/t-wince-pe (pe.o): Likewise.
+ * config/i386/t-cygming (winnt.o): Likewise.
+ (winnt-cxx.o, winnt-stubs.o, msformat-c.o): Likewise.
+ * config/i386/t-cygwin (cygwin1.o): Likewise.
+ (cygwin2.o): Likewise.
+ * config/i386/t-i386 (i386-c.o): Likewise.
+ * config/i386/t-interix (winnt.o): Likewise.
+ * config/i386/t-netware (netware.o): Likewise.
+ * config/i386/t-nwld (nwld.o): Likewise.
+ * config/i386/x-darwin (host-i386-darwin.o): Likewise.
+ * config/i386/x-i386 (driver-i386.o): Likewise.
+ * config/i386/x-cygwin (host-cygwin.o): Likewise.
+ * config/i386/x-mingw32 (host-mingw32.o): Likewise.
+ * config/ia64/t-ia64 (ia64-c.o): Likewise.
+ * config/m32c/t-m32c (m32c-pragma.o): Likewise.
+ * config/mips/x-native (driver-native.o): Likewise.
+ * config/rs6000/t-rs6000 (rs6000-c.o): Likewise.
+ * config/rs6000/x-darwin (host-ppc-darwin.o): Likewise.
+ * config/rs6000/x-darwin64 (host-ppc64-darwin.o): Likewise.
+ * config/rs6000/x-rs6000 (driver-rs6000.o): Likewise.
+ * config/score/t-score-elf (score7.o): Likewise.
+ (score3.o): Likewise.
+ * config/sh/t-sh (sh-c.o): Likewise.
+ * config/sh/t-symbian (sh-c.o): Likewise.
+ (symbian.o): Likewise.
+ * config/spu/t-spu-elf (spu-c.o): Likewise.
+ * config/v850/t-v850 (v850-c.o): Likewise.
+ * config/v850/t-v850e (v850-c.o): Likewise.
+
+2009-05-26 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/40122
+ * tree-ssa-ccp.c (ccp_fold): Fold vector CONSTRUCTORs to
+ VECTOR_CSTs if possible.
+ (fold_gimple_assign): Likewise.
+
+2009-05-26 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/40252
+ * fold-const.c (fold_binary): Use the correct types for building
+ rotates.
+
+2009-05-26 Richard Guenther <rguenther@suse.de>
+
+ * tree-vect-data-refs.c (vect_create_data_ref_ptr): Remove
+ redundant calls to merge_alias_info.
+ (bump_vector_ptr): Likewise.
+ * tree-ssa-copy.c (merge_alias_info): Remove.
+ (replace_exp_1): Remove call to merge_alias_info.
+ (propagate_tree_value): Likewise.
+ (fini_copy_prop): Propagate points-to info.
+ * tree-flow.h (merge_alias_info): Remove.
+
+2009-05-07 Hariharan Sandanagobalane <hariharan@picochip.com>
+
+ * config/picochip/picochip.C (PARAM_INLINE_CALL_COST): Remove.
+
2009-05-25 Jan Hubicka <jh@suse.cz>
* cgraph.c (dump_cgraph_node): Dump size/time/benefit.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 90acbf81497..1e29a894563 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20090526
+20090603
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index 43c676ac2c1..6445f5fa927 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -202,6 +202,13 @@ NM = @NM@
RANLIB = @RANLIB@
RANLIB_FLAGS = @ranlib_flags@
+# The name of the compiler to use. Currently always $(CC). In the
+# future this may change to $(CXX).
+COMPILER = $(CC)
+COMPILER_FLAGS = $(CFLAGS)
+LINKER = $(CC)
+LINKER_FLAGS = $(CFLAGS)
+
# -------------------------------------------
# Programs which operate on the build machine
# -------------------------------------------
@@ -627,7 +634,7 @@ TARGET_LIBGCC2_CFLAGS =
# Options to use when compiling crtbegin/end.
CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
- -finhibit-size-directive -fno-inline-functions -fno-exceptions \
+ -finhibit-size-directive -fno-inline -fno-exceptions \
-fno-zero-initialized-in-bss -fno-toplevel-reorder -fno-tree-vectorize \
$(INHIBIT_LIBC_CFLAGS)
@@ -726,6 +733,14 @@ DIR = ../gcc
CC_FOR_BUILD = @CC_FOR_BUILD@
BUILD_CFLAGS= @BUILD_CFLAGS@ -DGENERATOR_FILE
+# Native compiler that we use. This may be C++ some day.
+COMPILER_FOR_BUILD = $(CC_FOR_BUILD)
+BUILD_COMPILERFLAGS = $(BUILD_CFLAGS)
+
+# Native linker that we use.
+LINKER_FOR_BUILD = $(CC_FOR_BUILD)
+BUILD_LINKERFLAGS = $(BUILD_CFLAGS)
+
# Native linker and preprocessor flags. For x-fragment overrides.
BUILD_LDFLAGS=@BUILD_LDFLAGS@
BUILD_CPPFLAGS=$(ALL_CPPFLAGS)
@@ -912,7 +927,8 @@ EBIMAP_H = ebitmap.h sbitmap.h
IPA_PROP_H = ipa-prop.h $(TREE_H) vec.h $(CGRAPH_H)
GSTAB_H = gstab.h stab.def
BITMAP_H = bitmap.h $(HASHTAB_H) statistics.h
-PLUGIN_H = plugin.h gcc-plugin.h
+GCC_PLUGIN_H = gcc-plugin.h $(CONFIG_H) $(SYSTEM_H)
+PLUGIN_H = plugin.h $(GCC_PLUGIN_H)
PLUGIN_VERSION_H = plugin-version.h configargs.h
#
@@ -934,6 +950,12 @@ ALL_CFLAGS = $(T_CFLAGS) \
# win against random include files in /usr/include.
ALL_CPPFLAGS = $(INCLUDES) $(CPPFLAGS)
+# This is the variable to use when using $(COMPILER).
+ALL_COMPILERFLAGS = $(ALL_CFLAGS)
+
+# This is the variable to use when using $(LINKER).
+ALL_LINKERFLAGS = $(ALL_CFLAGS)
+
# Build and host support libraries.
LIBIBERTY = ../libiberty/libiberty.a
BUILD_LIBIBERTY = $(build_libobjdir)/libiberty/libiberty.a
@@ -981,7 +1003,7 @@ INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
$(PPLINC) $(CLOOGINC) $(LTDLINC)
.c.o:
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
#
# Support for additional languages (other than C).
@@ -1671,16 +1693,16 @@ libbackend.a: $(OBJS@onestep@)
# and CC is `gcc'. It is renamed to `gcc' when it is installed.
xgcc$(exeext): $(GCC_OBJS) gccspec.o version.o intl.o prefix.o \
version.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) gccspec.o \
- intl.o prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \
+ gccspec.o intl.o prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
# cpp is to cpp0 as gcc is to cc1.
# The only difference from xgcc is that it's linked with cppspec.o
# instead of gccspec.o.
cpp$(exeext): $(GCC_OBJS) cppspec.o version.o intl.o prefix.o \
version.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) cppspec.o \
- intl.o prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \
+ cppspec.o intl.o prefix.o version.o $(EXTRA_GCC_OBJS) $(LIBS)
# Dump a specs file to make -B./ read these specs over installed ones.
$(SPECS): xgcc$(exeext)
@@ -1696,8 +1718,8 @@ gcc-cross$(exeext): xgcc$(exeext)
dummy-checksum.o : dummy-checksum.c
cc1-dummy$(exeext): $(C_OBJS) dummy-checksum.o $(BACKEND) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(LTDL_LDFLAGS) -o $@ $(C_OBJS) dummy-checksum.o \
- $(BACKEND) $(LIBS) $(BACKENDLIBS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \
+ dummy-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
cc1-checksum.c : cc1-dummy$(exeext) build/genchecksum$(build_exeext)
build/genchecksum$(build_exeext) cc1-dummy$(exeext) > $@
@@ -1705,8 +1727,8 @@ cc1-checksum.c : cc1-dummy$(exeext) build/genchecksum$(build_exeext)
cc1-checksum.o : cc1-checksum.c
cc1$(exeext): $(C_OBJS) cc1-checksum.o $(BACKEND) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(LTDL_LDFLAGS) -o $@ $(C_OBJS) cc1-checksum.o \
- $(BACKEND) $(LIBS) $(BACKENDLIBS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(C_OBJS) \
+ cc1-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
#
# Build libgcc.a.
@@ -1775,6 +1797,7 @@ libgcc.mvars: config.status Makefile $(LIB2ADD) $(LIB2ADD_ST) specs \
echo CRTSTUFF_CFLAGS = '$(CRTSTUFF_CFLAGS)' >> tmp-libgcc.mvars
echo CRTSTUFF_T_CFLAGS = '$(CRTSTUFF_T_CFLAGS)' >> tmp-libgcc.mvars
echo CRTSTUFF_T_CFLAGS_S = '$(CRTSTUFF_T_CFLAGS_S)' >> tmp-libgcc.mvars
+ echo TARGET_SYSTEM_ROOT = '$(TARGET_SYSTEM_ROOT)' >> tmp-libgcc.mvars
mv tmp-libgcc.mvars libgcc.mvars
@@ -1918,19 +1941,22 @@ ebitmap.o: ebitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(EBITMAP_H) $(RTL_H) $(FLAGS_H) $(OBSTACK_H)
sparseset.o: sparseset.c $(SYSTEM_H) sparseset.h $(CONFIG_H)
-COLLECT2_OBJS = collect2.o tlink.o intl.o version.o
+COLLECT2_OBJS = collect2.o collect2-aix.o tlink.o intl.o version.o
COLLECT2_LIBS = @COLLECT2_LIBS@
collect2$(exeext): $(COLLECT2_OBJS) $(LIBDEPS)
# Don't try modifying collect2 (aka ld) in place--it might be linking this.
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o T$@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o T$@ \
$(COLLECT2_OBJS) $(LIBS) $(COLLECT2_LIBS)
mv -f T$@ $@
collect2.o : collect2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h \
- $(OBSTACK_H) $(DEMANGLE_H) collect2.h version.h
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(OBSTACK_H) $(DEMANGLE_H) collect2.h collect2-aix.h version.h
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DTARGET_MACHINE=\"$(target_noncanonical)\" \
- -c $(srcdir)/collect2.c $(OUTPUT_OPTION)
+ -c $(srcdir)/collect2.c $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@
+
+collect2-aix.o : collect2-aix.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
+ collect2-aix.h
tlink.o: tlink.c $(DEMANGLE_H) $(HASHTAB_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(OBSTACK_H) collect2.h intl.h
@@ -1955,15 +1981,15 @@ c-opts.o : c-opts.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_INLINE_H) $(DIAGNOSTIC_H) intl.h debug.h $(C_COMMON_H) \
opts.h options.h $(MKDEPS_H) incpath.h cppdefault.h $(TARGET_H) \
$(TM_P_H) $(VARRAY_H) $(C_TREE_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
$< $(OUTPUT_OPTION) @TARGET_SYSTEM_ROOT_DEFINE@
c-cppbuiltin.o : c-cppbuiltin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TREE_H) version.h $(C_COMMON_H) $(C_PRAGMA_H) $(FLAGS_H) \
$(TOPLEV_H) output.h $(EXCEPT_H) $(REAL_H) $(TARGET_H) $(TM_P_H) \
$(BASEVER) debug.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) -DBASEVER=$(BASEVER_s) \
- $< $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
+ -DBASEVER=$(BASEVER_s) $< $(OUTPUT_OPTION)
# A file used by all variants of C and some other languages.
@@ -1987,7 +2013,7 @@ c-dump.o : c-dump.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
c-pch.o : c-pch.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(CPPLIB_H) $(TREE_H) \
$(C_COMMON_H) output.h $(TOPLEV_H) $(C_PRAGMA_H) $(GGC_H) debug.h \
langhooks.h $(FLAGS_H) hosthooks.h version.h $(TARGET_H) opts.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DHOST_MACHINE=\"$(host)\" -DTARGET_MACHINE=\"$(target)\" \
$< $(OUTPUT_OPTION)
@@ -2013,13 +2039,13 @@ gcc.o: gcc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h multilib.h \
Makefile $(lang_specs_files) specs.h prefix.h $(GCC_H) $(FLAGS_H) \
configargs.h $(OBSTACK_H) opts.h
(SHLIB_LINK='$(SHLIB_LINK)'; \
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
$(DRIVER_DEFINES) \
-c $(srcdir)/gcc.c $(OUTPUT_OPTION))
gccspec.o: gccspec.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H)
(SHLIB_LINK='$(SHLIB_LINK)'; \
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
$(DRIVER_DEFINES) \
-c $(srcdir)/gccspec.c $(OUTPUT_OPTION))
@@ -2054,7 +2080,8 @@ options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TARGET_H) $(FLAGS_H)
$(TM_H) opts.h intl.h
gcc-options.o: options.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) opts.h intl.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(OUTPUT_OPTION) -DGCC_DRIVER options.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(OUTPUT_OPTION) \
+ -DGCC_DRIVER options.c
dumpvers: dumpvers.c
@@ -2063,7 +2090,7 @@ version.o: version.c version.h $(REVISION) $(DATESTAMP) $(BASEVER) $(DEVPHASE)
else
version.o: version.c version.h $(DATESTAMP) $(BASEVER) $(DEVPHASE)
endif
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DBASEVER=$(BASEVER_s) -DDATESTAMP=$(DATESTAMP_s) \
-DREVISION=$(REVISION_s) \
-DDEVPHASE=$(DEVPHASE_s) -DPKGVERSION=$(PKGVERSION_s) \
@@ -2077,15 +2104,16 @@ gtype-desc.o: gtype-desc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(CPP_ID_DATA_H) tree-chrec.h $(CFGLAYOUT_H) $(EXCEPT_H) output.h \
$(CFGLOOP_H)
-ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \
- $(HASHTAB_H) $(TOPLEV_H) $(PARAMS_H) hosthooks.h $(HOSTHOOKS_DEF_H)
+ggc-common.o: ggc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
+ $(GGC_H) $(HASHTAB_H) $(TOPLEV_H) $(PARAMS_H) hosthooks.h \
+ $(HOSTHOOKS_DEF_H) vec.h plugin.h
ggc-page.o: ggc-page.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) \
- $(FLAGS_H) $(TOPLEV_H) $(GGC_H) $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H) $(TREE_FLOW_H)
+ $(FLAGS_H) $(TOPLEV_H) $(GGC_H) $(TIMEVAR_H) $(TM_P_H) $(PARAMS_H) $(TREE_FLOW_H) plugin.h
ggc-zone.o: ggc-zone.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(TREE_H) $(FLAGS_H) $(TOPLEV_H) $(GGC_H) $(TIMEVAR_H) $(TM_P_H) \
- $(PARAMS_H) $(BITMAP_H) $(VARRAY_H)
+ $(PARAMS_H) $(BITMAP_H) $(VARRAY_H) plugin.h
ggc-none.o: ggc-none.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(GGC_H) \
$(BCONFIG_H)
@@ -2095,7 +2123,7 @@ stringpool.o: stringpool.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
prefix.o: prefix.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) prefix.h \
Makefile $(BASEVER)
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DPREFIX=\"$(prefix)\" -DBASEVER=$(BASEVER_s) \
-c $(srcdir)/prefix.c $(OUTPUT_OPTION)
@@ -2542,7 +2570,7 @@ toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(CGRAPH_H) $(COVERAGE_H) alloc-pool.h $(GGC_H) $(INTEGRATE_H) \
opts.h params.def tree-mudflap.h $(REAL_H) $(TREE_PASS_H) $(GIMPLE_H) \
tree-ssa-alias.h $(PLUGIN_H)
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DTARGET_NAME=\"$(target_noncanonical)\" \
-c $(srcdir)/toplev.c $(OUTPUT_OPTION)
@@ -2558,7 +2586,7 @@ passes.o : passes.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
gt-passes.h $(DF_H) $(PREDICT_H)
plugin.o : plugin.c $(PLUGIN_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h \
- $(TOPLEV_H) $(TREE_H) $(TREE_PASS_H) intl.h $(PLUGIN_VERSION_H)
+ $(TOPLEV_H) $(TREE_H) $(TREE_PASS_H) intl.h $(PLUGIN_VERSION_H) $(GGC_H)
main.o : main.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TOPLEV_H)
@@ -2602,7 +2630,7 @@ except.o : except.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(TREE_H) $(FLAGS_H) $(EXCEPT_H) $(FUNCTION_H) $(EXPR_H) libfuncs.h \
langhooks.h insn-config.h hard-reg-set.h $(BASIC_BLOCK_H) output.h \
dwarf2asm.h dwarf2out.h $(TOPLEV_H) $(HASHTAB_H) intl.h $(GGC_H) \
- gt-$(EXCEPT_H) $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) dwarf2.h \
+ gt-except.h $(CGRAPH_H) $(INTEGRATE_H) $(DIAGNOSTIC_H) dwarf2.h \
$(TARGET_H) $(TM_P_H) $(TREE_PASS_H) $(TIMEVAR_H) $(TREE_FLOW_H)
expr.o : expr.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
$(TREE_H) $(FLAGS_H) $(FUNCTION_H) $(REGS_H) $(EXPR_H) $(OPTABS_H) \
@@ -2709,7 +2737,7 @@ ipa-prop.o : ipa-prop.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
ipa-cp.o : ipa-cp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TREE_H) $(TARGET_H) $(CGRAPH_H) $(IPA_PROP_H) $(TREE_FLOW_H) \
$(TREE_PASS_H) $(FLAGS_H) $(TIMEVAR_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
- $(TREE_INLINE_H)
+ $(TREE_INLINE_H) $(FIBHEAP_H) $(PARAMS_H)
matrix-reorg.o : matrix-reorg.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(RTL_H) $(TREE_INLINE_H) $(TREE_FLOW_H) \
tree-flow-inline.h langhooks.h $(HASHTAB_H) $(TOPLEV_H) $(FLAGS_H) $(GGC_H) \
@@ -2729,8 +2757,7 @@ ipa-reference.o : ipa-reference.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) langhooks.h \
pointer-set.h $(GGC_H) $(IPA_REFERENCE_H) $(IPA_UTILS_H) $(SPLAY_TREE_H) \
$(GIMPLE_H) $(CGRAPH_H) output.h $(FLAGS_H) $(TREE_PASS_H) \
- $(TIMEVAR_H) $(DIAGNOSTIC_H) $(FUNCTION_H)
-
+ $(TIMEVAR_H) $(DIAGNOSTIC_H) $(FUNCTION_H) gt-ipa-reference.h
ipa-pure-const.o : ipa-pure-const.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TREE_H) $(TREE_FLOW_H) $(TREE_INLINE_H) langhooks.h \
pointer-set.h $(GGC_H) $(IPA_UTILS_H) $(TARGET_H) \
@@ -2814,11 +2841,9 @@ tree-ssa-ccp.o : tree-ssa-ccp.c $(TREE_FLOW_H) $(CONFIG_H) \
$(DIAGNOSTIC_H) $(FUNCTION_H) $(TIMEVAR_H) $(TM_H) coretypes.h \
$(TREE_DUMP_H) $(BASIC_BLOCK_H) $(TREE_PASS_H) langhooks.h \
tree-ssa-propagate.h value-prof.h $(FLAGS_H) $(TARGET_H) $(TOPLEV_H)
-tree-sra.o : tree-sra.c $(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(RTL_H) \
- $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \
- $(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(GIMPLE_H) \
- langhooks.h $(TREE_PASS_H) $(FLAGS_H) $(EXPR_H) $(BASIC_BLOCK_H) \
- $(BITMAP_H) $(GGC_H) hard-reg-set.h $(OBSTACK_H) $(PARAMS_H) $(TARGET_H)
+tree-sra.o : tree-sra.c $(CONFIG_H) $(SYSTEM_H) coretypes.h alloc-pool.h \
+ $(TM_H) $(TREE_H) $(GIMPLE_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TREE_DUMP_H) \
+ $(TIMEVAR_H) $(PARAMS_H) $(TARGET_H) $(FLAGS_H)
tree-switch-conversion.o : tree-switch-conversion.c $(CONFIG_H) $(SYSTEM_H) \
$(TREE_H) $(TM_P_H) $(TREE_FLOW_H) $(DIAGNOSTIC_H) $(TREE_INLINE_H) \
$(TIMEVAR_H) $(TM_H) coretypes.h $(TREE_DUMP_H) $(GIMPLE_H) \
@@ -3168,18 +3193,20 @@ $(out_object_file): $(out_file) $(CONFIG_H) coretypes.h $(TM_H) $(TREE_H) \
output.h $(INSN_ATTR_H) $(SYSTEM_H) $(TOPLEV_H) $(TARGET_H) libfuncs.h \
$(TARGET_DEF_H) $(FUNCTION_H) $(SCHED_INT_H) $(TM_P_H) $(EXPR_H) \
langhooks.h $(GGC_H) $(OPTABS_H) $(REAL_H) tm-constrs.h $(GIMPLE_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
$(out_file) $(OUTPUT_OPTION)
# Build auxiliary files that support ecoff format.
mips-tfile: mips-tfile.o version.o $(LIBDEPS)
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ mips-tfile.o version.o $(LIBS)
+ $(LINKER) $(LINKERFLAGS) $(LDFLAGS) -o $@ \
+ mips-tfile.o version.o $(LIBS)
mips-tfile.o : mips-tfile.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) coretypes.h \
$(TM_H) version.h $(srcdir)/../include/getopt.h $(GSTAB_H) intl.h
mips-tdump: mips-tdump.o version.o $(LIBDEPS)
- $(CC) $(CFLAGS) $(LDFLAGS) -o $@ mips-tdump.o version.o $(LIBS)
+ $(LINKER) $(LINKERFLAGS) $(LDFLAGS) -o $@ \
+ mips-tdump.o version.o $(LIBS)
mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) coretypes.h \
$(TM_H) version.h $(srcdir)/../include/getopt.h stab.def
@@ -3188,7 +3215,7 @@ mips-tdump.o : mips-tdump.c $(CONFIG_H) $(RTL_H) $(SYSTEM_H) coretypes.h \
libbackend.o : $(OBJS-common:.o=.c) $(out_file) \
insn-config.h insn-flags.h insn-codes.h insn-constants.h \
insn-attr.h $(DATESTAMP) $(BASEVER) $(DEVPHASE) gcov-iov.h
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DTARGET_NAME=\"$(target_noncanonical)\" \
-DLOCALEDIR=\"$(localedir)\" \
-c $(filter %.c,$^) -o $@ \
@@ -3462,7 +3489,8 @@ s-gtype: build/gengtype$(build_exeext) $(filter-out [%], $(GTFILES)) \
# How to compile object files to run on the build machine.
build/%.o : # dependencies provided by explicit rule later
- $(CC_FOR_BUILD) -c $(BUILD_CFLAGS) $(BUILD_CPPFLAGS) -o $@ $<
+ $(COMPILER_FOR_BUILD) -c $(BUILD_COMPILERFLAGS) $(BUILD_CPPFLAGS) \
+ -o $@ $<
# Header dependencies for the programs that generate source code.
# These are library modules...
@@ -3540,13 +3568,13 @@ build/genrecog.o : genrecog.c $(RTL_BASE_H) $(BCONFIG_H) $(SYSTEM_H) \
coretypes.h $(GTM_H) errors.h gensupport.h
# Compile the programs that generate insn-* from the machine description.
-# They are compiled with $(CC_FOR_BUILD), and associated libraries,
+# They are compiled with $(COMPILER_FOR_BUILD), and associated libraries,
# since they need to run on this machine
# even if GCC is being compiled to run on some other machine.
# As a general rule...
build/gen%$(build_exeext): build/gen%.o $(BUILD_LIBDEPS)
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) -o $@ \
+ $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) -o $@ \
$(filter-out $(BUILD_LIBDEPS), $^) $(BUILD_LIBS)
# All these programs use the MD reader ($(BUILD_RTL)).
@@ -3570,7 +3598,7 @@ gengtype-lex.c : gengtype-lex.l
#
# Remake internationalization support.
intl.o: intl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) intl.h Makefile
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DLOCALEDIR=\"$(localedir)\" \
-c $(srcdir)/intl.c $(OUTPUT_OPTION)
@@ -3592,7 +3620,7 @@ PREPROCESSOR_DEFINES = \
cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
cppdefault.h Makefile
- $(CC) $(ALL_CFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
$(PREPROCESSOR_DEFINES) \
-c $(srcdir)/cppdefault.c $(OUTPUT_OPTION)
@@ -3604,7 +3632,8 @@ build/gcov-iov.o: gcov-iov.c $(BCONFIG_H) coretypes.h $(GTM_H) \
$(SYSTEM_H) coretypes.h $(TM_H)
build/gcov-iov$(build_exeext): build/gcov-iov.o
- $(CC_FOR_BUILD) $(BUILD_CFLAGS) $(BUILD_LDFLAGS) build/gcov-iov.o -o $@
+ $(LINKER_FOR_BUILD) $(BUILD_LINKERFLAGS) $(BUILD_LDFLAGS) \
+ build/gcov-iov.o -o $@
gcov-iov.h: s-iov
s-iov: build/gcov-iov$(build_exeext) $(BASEVER) $(DEVPHASE)
@@ -3620,10 +3649,11 @@ gcov-dump.o: gcov-dump.c gcov-io.c $(GCOV_IO_H) $(SYSTEM_H) coretypes.h \
GCOV_OBJS = gcov.o intl.o version.o errors.o
gcov$(exeext): $(GCOV_OBJS) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(GCOV_OBJS) $(LIBS) -o $@
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_OBJS) $(LIBS) -o $@
GCOV_DUMP_OBJS = gcov-dump.o version.o errors.o
gcov-dump$(exeext): $(GCOV_DUMP_OBJS) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) $(GCOV_DUMP_OBJS) $(LIBS) -o $@
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) $(GCOV_DUMP_OBJS) \
+ $(LIBS) -o $@
#
# Build the include directories. The stamp files are stmp-* rather than
# s-* so that mostlyclean does not force the include directory to
@@ -4097,8 +4127,8 @@ installdirs:
$(mkinstalldirs) $(DESTDIR)$(man7dir)
PLUGIN_HEADERS = $(TREE_H) $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
- $(TOPLEV_H) $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_PASS_H) gcc-plugin.h intl.h \
- $(PLUGIN_VERSION_H)
+ $(TOPLEV_H) $(BASIC_BLOCK_H) $(GIMPLE_H) $(TREE_PASS_H) $(GCC_PLUGIN_H) \
+ intl.h $(PLUGIN_VERSION_H)
# Install the headers needed to build a plugin.
install-plugin: installdirs
diff --git a/gcc/ada/ChangeLog b/gcc/ada/ChangeLog
index 6a652be62cd..16fe9243b35 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,34 @@
+2009-06-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/Make-lang.in: Fix formatting.
+
+2009-06-01 Olivier Hainque <hainque@adacore.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils.c (convert) <CONSTRUCTOR case>: When converting
+ to the packable version of the type, clear TREE_STATIC/TREE_CONSTANT
+ on the result if at least one of the input fields couldn't be output
+ as a static constant any more.
+
+2009-06-01 Olivier Hainque <hainque@adacore.com>
+ Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/utils2.c (gnat_build_constructor): Factor
+ out code. Use initializer_constant_valid_for_bitfield_p and
+ CONSTRUCTOR_BITFIELD_P for bit-fields.
+
+2009-05-26 Ian Lance Taylor <iant@google.com>
+
+ * gcc-interface/Makefile.in (COMPILER): Define.
+ (COMPILER_FLAGS, ALL_COMPILERFLAGS): Define.
+ (.c.o, cio.o, init.o, initialize.o, targext.o): Use $(COMPILER).
+ (seh_init.o, tracebak.o): Likewise.
+ * gcc-interface/Make-lang.in (ada/targext.o): Likewise.
+ (ada/cio.o, ada/init.o, ada/initialize.o, ada/raise.o): Likewise.
+ (ada/tracebak.o, ada/cuintp.o, ada/decl.o, ada/misc.o): Likewise.
+ (ada/targtyps.o, ada/trans.o, ada/utils.o): Likewise.
+ (ada/utils2.o): Likewise.
+
2009-05-24 Olivier Hainque <hainque@adacore.com>
* switch.adb (Is_Internal_GCC_Switch, Switch_Last): Bodies of ...
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 564919d793e..83b74fa4ff2 100644
--- a/gcc/ada/gcc-interface/Make-lang.in
+++ b/gcc/ada/gcc-interface/Make-lang.in
@@ -1124,35 +1124,35 @@ ada/link.o : ada/link.c
ada/targext.o : ada/targext.c $(SYSTEM_H) coretypes.h $(TM_H)
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- $< $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
+ $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-ada/cio.o : ada/cio.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) \
- $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+ada/cio.o : ada/cio.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
+ $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-ada/init.o : ada/init.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h ada/raise.h
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) \
- $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+ada/init.o : ada/init.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h ada/raise.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
+ $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
ada/initialize.o : ada/initialize.c
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) \
- $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
+ $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
-ada/raise.o : ada/raise.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h ada/raise.h
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) \
+ada/raise.o : ada/raise.c $(CONFIG_H) $(SYSTEM_H) ada/adaint.h ada/raise.h
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
$(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
# Need to keep the frame pointer to unwind the stack properly for some targets.
ada/tracebak.o : ada/tracebak.c $(CONFIG_H) $(SYSTEM_H)
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- -fno-omit-frame-pointer $< $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) $(ALL_CPPFLAGS) \
+ $(INCLUDES) -fno-omit-frame-pointer $< $(OUTPUT_OPTION)
ada/cuintp.o : ada/gcc-interface/cuintp.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) ada/gcc-interface/ada.h ada/types.h ada/uintp.h \
ada/atree.h ada/elists.h ada/nlists.h ada/stringt.h ada/fe.h $(ADA_TREE_H) \
ada/gcc-interface/gigi.h
- $(CC) -c $(ALL_CFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
ada/decl.o : ada/gcc-interface/decl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(FLAGS_H) toplev.h $(TARGET_H) $(EXPR_H) \
@@ -1160,7 +1160,7 @@ ada/decl.o : ada/gcc-interface/decl.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
ada/elists.h ada/namet.h ada/nlists.h ada/repinfo.h ada/snames.h \
ada/stringt.h ada/uintp.h ada/fe.h ada/sinfo.h ada/einfo.h $(ADA_TREE_H) \
ada/gcc-interface/gigi.h gt-ada-decl.h
- $(CC) -c $(ALL_CFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
ada/misc.o : ada/gcc-interface/misc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(DIAGNOSTIC_H) $(TARGET_H) $(EXPR_H) libfuncs.h \
@@ -1169,14 +1169,14 @@ ada/misc.o : ada/gcc-interface/misc.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
ada/gcc-interface/ada.h ada/adadecode.h ada/types.h ada/atree.h \
ada/elists.h ada/namet.h ada/nlists.h ada/stringt.h ada/uintp.h ada/fe.h \
ada/sinfo.h ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h
- $(CC) -c $(ALL_CFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
ada/targtyps.o : ada/gcc-interface/targtyps.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TREE_H) ada/gcc-interface/ada.h ada/types.h \
ada/atree.h ada/elists.h ada/namet.h ada/nlists.h ada/snames.h \
ada/stringt.h ada/uintp.h ada/urealp.h ada/fe.h ada/sinfo.h ada/einfo.h \
$(ADA_TREE_H) ada/gcc-interface/gigi.h
- $(CC) -c $(ALL_CFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
ada/trans.o : ada/gcc-interface/trans.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(FLAGS_H) $(EXPR_H) output.h tree-iterator.h \
@@ -1184,7 +1184,7 @@ ada/trans.o : ada/gcc-interface/trans.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
ada/atree.h ada/elists.h ada/namet.h ada/nlists.h ada/snames.h \
ada/stringt.h ada/uintp.h ada/urealp.h ada/fe.h ada/sinfo.h ada/einfo.h \
$(ADA_TREE_H) ada/gcc-interface/gigi.h gt-ada-trans.h
- $(CC) -c $(ALL_CFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
ada/utils.o : ada/gcc-interface/utils.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(FLAGS_H) toplev.h $(RTL_H) output.h debug.h convert.h \
@@ -1193,14 +1193,14 @@ ada/utils.o : ada/gcc-interface/utils.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
ada/gcc-interface/ada.h ada/types.h ada/atree.h ada/elists.h ada/namet.h \
ada/nlists.h ada/stringt.h ada/uintp.h ada/fe.h ada/sinfo.h ada/einfo.h \
$(ADA_TREE_H) ada/gcc-interface/gigi.h gt-ada-utils.h gtype-ada.h
- $(CC) -c $(ALL_CFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
ada/utils2.o : ada/gcc-interface/utils2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TREE_H) $(FLAGS_H) output.h $(TREE_INLINE_H) \
ada/gcc-interface/ada.h ada/types.h ada/atree.h ada/elists.h ada/namet.h \
ada/nlists.h ada/snames.h ada/stringt.h ada/uintp.h ada/fe.h ada/sinfo.h \
ada/einfo.h $(ADA_TREE_H) ada/gcc-interface/gigi.h
- $(CC) -c $(ALL_CFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) -I.. $(ALL_CPPFLAGS) $< -o $@
#
# DO NOT PUT SPECIAL RULES BELOW, THIS SECTION IS UPDATED AUTOMATICALLY
diff --git a/gcc/ada/gcc-interface/Makefile.in b/gcc/ada/gcc-interface/Makefile.in
index 04553d4b2ce..ef42fa3bea9 100644
--- a/gcc/ada/gcc-interface/Makefile.in
+++ b/gcc/ada/gcc-interface/Makefile.in
@@ -92,6 +92,9 @@ RANLIB = @RANLIB@
RANLIB_FLAGS = @ranlib_flags@
AWK = @AWK@
+COMPILER = $(CC)
+COMPILER_FLAGS = $(CFLAGS)
+
SHELL = @SHELL@
PWD_COMMAND = $${PWDCMD-pwd}
# How to copy preserving the date
@@ -218,6 +221,9 @@ ALL_CFLAGS = $(INTERNAL_CFLAGS) $(T_CFLAGS) $(LOOSE_CFLAGS)
# Likewise.
ALL_CPPFLAGS = $(CPPFLAGS)
+# Used with $(COMPILER).
+ALL_COMPILERFLAGS = $(ALL_CFLAGS)
+
# This is where we get libiberty.a from.
LIBIBERTY = ../../libiberty/libiberty.a
@@ -253,8 +259,8 @@ ADA_INCLUDES_FOR_SUBDIR = -I. -I$(fsrcdir)/ada
$(CC) -c -x assembler $< $(OUTPUT_OPTION)
.c.o:
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
- $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) $(ALL_CPPFLAGS) \
+ $(INCLUDES) $< $(OUTPUT_OPTION)
.adb.o:
$(CC) -c $(ALL_ADAFLAGS) $(ADA_INCLUDES) $< $(OUTPUT_OPTION)
@@ -2529,33 +2535,33 @@ raise.o : raise.c raise.h
vx_stack_info.o : vx_stack_info.c
cio.o : cio.c
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
$(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
init.o : init.c adaint.h raise.h
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
$(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
initialize.o : initialize.c raise.h
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
$(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
targext.o : targext.c
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
$(ALL_CPPFLAGS) $(INCLUDES_FOR_SUBDIR) \
$< $(OUTPUT_OPTION)
# No optimization to compile this file as optimizations (-O1 or above) breaks
# the SEH handling on Windows. The reasons are not clear.
seh_init.o : seh_init.c raise.h
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) -O0 \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) -O0 \
$(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
# Need to keep the frame pointer in this file to pop the stack properly on
# some targets.
tracebak.o : tracebak.c tb-alvms.c tb-alvxw.c tb-gcc.c
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
- -fno-omit-frame-pointer $< $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) $(ALL_CPPFLAGS) \
+ $(INCLUDES) -fno-omit-frame-pointer $< $(OUTPUT_OPTION)
# In GNU Make, ignore whether `stage*' exists.
.PHONY: stage1 stage2 stage3 stage4 clean realclean TAGS bootstrap
diff --git a/gcc/ada/gcc-interface/utils.c b/gcc/ada/gcc-interface/utils.c
index 6dbd1e700e1..f3755a01631 100644
--- a/gcc/ada/gcc-interface/utils.c
+++ b/gcc/ada/gcc-interface/utils.c
@@ -3979,6 +3979,10 @@ convert (tree type, tree expr)
unsigned HOST_WIDE_INT idx;
tree index, value;
+ /* Whether we need to clear TREE_CONSTANT et al. on the output
+ constructor when we convert in place. */
+ bool clear_constant = false;
+
FOR_EACH_CONSTRUCTOR_ELT(e, idx, index, value)
{
constructor_elt *elt = VEC_quick_push (constructor_elt, v, NULL);
@@ -3987,15 +3991,30 @@ convert (tree type, tree expr)
break;
elt->index = field;
elt->value = convert (TREE_TYPE (field), value);
+
+ /* If packing has made this field a bitfield and the input
+ value couldn't be emitted statically any more, we need to
+ clear TREE_CONSTANT on our output. */
+ if (!clear_constant && TREE_CONSTANT (expr)
+ && !CONSTRUCTOR_BITFIELD_P (efield)
+ && CONSTRUCTOR_BITFIELD_P (field)
+ && !initializer_constant_valid_for_bitfield_p (value))
+ clear_constant = true;
+
efield = TREE_CHAIN (efield);
field = TREE_CHAIN (field);
}
+ /* If we have been able to match and convert all the input fields
+ to their output type, convert in place now. We'll fallback to a
+ view conversion downstream otherwise. */
if (idx == len)
{
expr = copy_node (expr);
TREE_TYPE (expr) = type;
CONSTRUCTOR_ELTS (expr) = v;
+ if (clear_constant)
+ TREE_CONSTANT (expr) = TREE_STATIC (expr) = false;
return expr;
}
}
diff --git a/gcc/ada/gcc-interface/utils2.c b/gcc/ada/gcc-interface/utils2.c
index 3fe85853879..ec72a27ebbc 100644
--- a/gcc/ada/gcc-interface/utils2.c
+++ b/gcc/ada/gcc-interface/utils2.c
@@ -1623,34 +1623,35 @@ compare_elmt_bitpos (const PTR rt1, const PTR rt2)
tree
gnat_build_constructor (tree type, tree list)
{
- tree elmt;
- int n_elmts;
bool allconstant = (TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST);
bool side_effects = false;
- tree result;
+ tree elmt, result;
+ int n_elmts;
/* Scan the elements to see if they are all constant or if any has side
effects, to let us set global flags on the resulting constructor. Count
the elements along the way for possible sorting purposes below. */
for (n_elmts = 0, elmt = list; elmt; elmt = TREE_CHAIN (elmt), n_elmts ++)
{
- if (!TREE_CONSTANT (TREE_VALUE (elmt))
+ tree obj = TREE_PURPOSE (elmt);
+ tree val = TREE_VALUE (elmt);
+
+ /* The predicate must be in keeping with output_constructor. */
+ if (!TREE_CONSTANT (val)
|| (TREE_CODE (type) == RECORD_TYPE
- && DECL_BIT_FIELD (TREE_PURPOSE (elmt))
- && TREE_CODE (TREE_VALUE (elmt)) != INTEGER_CST)
- || !initializer_constant_valid_p (TREE_VALUE (elmt),
- TREE_TYPE (TREE_VALUE (elmt))))
+ && CONSTRUCTOR_BITFIELD_P (obj)
+ && !initializer_constant_valid_for_bitfield_p (val))
+ || !initializer_constant_valid_p (val, TREE_TYPE (val)))
allconstant = false;
- if (TREE_SIDE_EFFECTS (TREE_VALUE (elmt)))
+ if (TREE_SIDE_EFFECTS (val))
side_effects = true;
/* Propagate an NULL_EXPR from the size of the type. We won't ever
be executing the code we generate here in that case, but handle it
specially to avoid the compiler blowing up. */
if (TREE_CODE (type) == RECORD_TYPE
- && (0 != (result
- = contains_null_expr (DECL_SIZE (TREE_PURPOSE (elmt))))))
+ && (result = contains_null_expr (DECL_SIZE (obj))) != NULL_TREE)
return build1 (NULL_EXPR, type, TREE_OPERAND (result, 0));
}
diff --git a/gcc/alias.c b/gcc/alias.c
index 4d42778a644..3488382df6c 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -1511,10 +1511,18 @@ find_base_term (rtx x)
/* If either operand is known to be a pointer, then use it
to determine the base term. */
if (REG_P (tmp1) && REG_POINTER (tmp1))
- return find_base_term (tmp1);
+ {
+ rtx base = find_base_term (tmp1);
+ if (base)
+ return base;
+ }
if (REG_P (tmp2) && REG_POINTER (tmp2))
- return find_base_term (tmp2);
+ {
+ rtx base = find_base_term (tmp2);
+ if (base)
+ return base;
+ }
/* Neither operand was known to be a pointer. Go ahead and find the
base term for both operands. */
diff --git a/gcc/attribs.c b/gcc/attribs.c
index 5b18aa35751..5ae462e7287 100644
--- a/gcc/attribs.c
+++ b/gcc/attribs.c
@@ -1,6 +1,6 @@
/* Functions dealing with attribute handling, used by most front ends.
Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
- 2002, 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GCC.
@@ -195,15 +195,15 @@ void
register_attribute (const struct attribute_spec *attr)
{
struct substring str;
- const void **slot;
+ void **slot;
str.str = attr->name;
str.length = strlen (str.str);
- slot = (const void **)htab_find_slot_with_hash (attribute_hash, &str,
- substring_hash (str.str, str.length),
- INSERT);
+ slot = htab_find_slot_with_hash (attribute_hash, &str,
+ substring_hash (str.str, str.length),
+ INSERT);
gcc_assert (!*slot);
- *slot = attr;
+ *slot = (void *) CONST_CAST (struct attribute_spec *, attr);
}
/* Return the spec for the attribute named NAME. */
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 783fce4ec68..80ff09d26bd 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -4189,7 +4189,7 @@ expand_builtin_memcmp (tree exp, rtx target, enum machine_mode mode)
arg1_rtx = get_memory_rtx (arg1, len);
arg2_rtx = get_memory_rtx (arg2, len);
- arg3_rtx = expand_normal (len);
+ arg3_rtx = expand_normal (fold_convert (sizetype, len));
/* Set MEM_SIZE as appropriate. */
if (GET_CODE (arg3_rtx) == CONST_INT)
@@ -11231,7 +11231,7 @@ validate_gimple_arglist (const_gimple call, ...)
do
{
- code = va_arg (ap, enum tree_code);
+ code = (enum tree_code) va_arg (ap, int);
switch (code)
{
case 0:
@@ -11282,7 +11282,7 @@ validate_arglist (const_tree callexpr, ...)
do
{
- code = va_arg (ap, enum tree_code);
+ code = (enum tree_code) va_arg (ap, int);
switch (code)
{
case 0:
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index 0320feece40..244c238023d 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -5338,6 +5338,7 @@ c_parser_postfix_expression (c_parser *parser)
expr.value = error_mark_node;
break;
}
+ loc = c_parser_peek_token (parser)->location;
t1 = c_parser_type_name (parser);
c_parser_skip_until_found (parser, CPP_CLOSE_PAREN,
"expected %<)%>");
@@ -5348,9 +5349,9 @@ c_parser_postfix_expression (c_parser *parser)
else
{
tree type_expr = NULL_TREE;
- expr.value = build_va_arg (e1.value, groktypename (t1,
- &type_expr,
- NULL));
+ expr.value = c_build_va_arg (e1.value,
+ groktypename (t1, &type_expr, NULL),
+ loc);
if (type_expr)
{
expr.value = build2 (C_MAYBE_CONST_EXPR,
diff --git a/gcc/c-tree.h b/gcc/c-tree.h
index 6062d59982d..05b52d8a45c 100644
--- a/gcc/c-tree.h
+++ b/gcc/c-tree.h
@@ -650,6 +650,7 @@ extern tree c_finish_omp_parallel (tree, tree);
extern tree c_begin_omp_task (void);
extern tree c_finish_omp_task (tree, tree);
extern tree c_finish_omp_clauses (tree);
+extern tree c_build_va_arg (tree, tree, location_t);
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 1a1b009398c..28fb8b8c049 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -4055,6 +4055,93 @@ build_compound_expr (tree expr1, tree expr2)
return ret;
}
+/* Issue -Wcast-qual warnings when appropriate. TYPE is the type to
+ which we are casting. OTYPE is the type of the expression being
+ cast. Both TYPE and OTYPE are pointer types. -Wcast-qual appeared
+ on the command line. */
+
+static void
+handle_warn_cast_qual (tree type, tree otype)
+{
+ tree in_type = type;
+ tree in_otype = otype;
+ int added = 0;
+ int discarded = 0;
+ bool is_const;
+
+ /* Check that the qualifiers on IN_TYPE are a superset of the
+ qualifiers of IN_OTYPE. The outermost level of POINTER_TYPE
+ nodes is uninteresting and we stop as soon as we hit a
+ non-POINTER_TYPE node on either type. */
+ do
+ {
+ in_otype = TREE_TYPE (in_otype);
+ in_type = TREE_TYPE (in_type);
+
+ /* GNU C allows cv-qualified function types. 'const' means the
+ function is very pure, 'volatile' means it can't return. We
+ need to warn when such qualifiers are added, not when they're
+ taken away. */
+ if (TREE_CODE (in_otype) == FUNCTION_TYPE
+ && TREE_CODE (in_type) == FUNCTION_TYPE)
+ added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
+ else
+ discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
+ }
+ while (TREE_CODE (in_type) == POINTER_TYPE
+ && TREE_CODE (in_otype) == POINTER_TYPE);
+
+ if (added)
+ warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
+
+ if (discarded)
+ /* There are qualifiers present in IN_OTYPE that are not present
+ in IN_TYPE. */
+ warning (OPT_Wcast_qual,
+ "cast discards qualifiers from pointer target type");
+
+ if (added || discarded)
+ return;
+
+ /* A cast from **T to const **T is unsafe, because it can cause a
+ const value to be changed with no additional warning. We only
+ issue this warning if T is the same on both sides, and we only
+ issue the warning if there are the same number of pointers on
+ both sides, as otherwise the cast is clearly unsafe anyhow. A
+ cast is unsafe when a qualifier is added at one level and const
+ is not present at all outer levels.
+
+ To issue this warning, we check at each level whether the cast
+ adds new qualifiers not already seen. We don't need to special
+ case function types, as they won't have the same
+ TYPE_MAIN_VARIANT. */
+
+ if (TYPE_MAIN_VARIANT (in_type) != TYPE_MAIN_VARIANT (in_otype))
+ return;
+ if (TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE)
+ return;
+
+ in_type = type;
+ in_otype = otype;
+ is_const = TYPE_READONLY (TREE_TYPE (in_type));
+ do
+ {
+ in_type = TREE_TYPE (in_type);
+ in_otype = TREE_TYPE (in_otype);
+ if ((TYPE_QUALS (in_type) &~ TYPE_QUALS (in_otype)) != 0
+ && !is_const)
+ {
+ warning (OPT_Wcast_qual,
+ ("new qualifiers in middle of multi-level non-const cast "
+ "are unsafe"));
+ break;
+ }
+ if (is_const)
+ is_const = TYPE_READONLY (in_type);
+ }
+ while (TREE_CODE (in_type) == POINTER_TYPE);
+}
+
/* Build an expression representing a cast to type TYPE of expression EXPR. */
tree
@@ -4139,46 +4226,10 @@ build_c_cast (tree type, tree expr)
otype = TREE_TYPE (value);
/* Optionally warn about potentially worrisome casts. */
-
if (warn_cast_qual
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (otype) == POINTER_TYPE)
- {
- tree in_type = type;
- tree in_otype = otype;
- int added = 0;
- int discarded = 0;
-
- /* Check that the qualifiers on IN_TYPE are a superset of
- the qualifiers of IN_OTYPE. The outermost level of
- POINTER_TYPE nodes is uninteresting and we stop as soon
- as we hit a non-POINTER_TYPE node on either type. */
- do
- {
- in_otype = TREE_TYPE (in_otype);
- in_type = TREE_TYPE (in_type);
-
- /* GNU C allows cv-qualified function types. 'const'
- means the function is very pure, 'volatile' means it
- can't return. We need to warn when such qualifiers
- are added, not when they're taken away. */
- if (TREE_CODE (in_otype) == FUNCTION_TYPE
- && TREE_CODE (in_type) == FUNCTION_TYPE)
- added |= (TYPE_QUALS (in_type) & ~TYPE_QUALS (in_otype));
- else
- discarded |= (TYPE_QUALS (in_otype) & ~TYPE_QUALS (in_type));
- }
- while (TREE_CODE (in_type) == POINTER_TYPE
- && TREE_CODE (in_otype) == POINTER_TYPE);
-
- if (added)
- warning (OPT_Wcast_qual, "cast adds new qualifiers to function type");
-
- if (discarded)
- /* There are qualifiers present in IN_OTYPE that are not
- present in IN_TYPE. */
- warning (OPT_Wcast_qual, "cast discards qualifiers from pointer target type");
- }
+ handle_warn_cast_qual (type, otype);
/* Warn about possible alignment problems. */
if (STRICT_ALIGNMENT
@@ -9976,3 +10027,14 @@ c_build_qualified_type (tree type, int type_quals)
return build_qualified_type (type, type_quals);
}
+
+/* Build a VA_ARG_EXPR for the C parser. */
+
+tree
+c_build_va_arg (tree expr, tree type, location_t loc)
+{
+ if (warn_cxx_compat && TREE_CODE (type) == ENUMERAL_TYPE)
+ warning_at (loc, OPT_Wc___compat,
+ "C++ requires promoted type, not enum type, in %<va_arg%>");
+ return build_va_arg (expr, type);
+}
diff --git a/gcc/calls.c b/gcc/calls.c
index 219b1d3afa6..c10b0cd3aba 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -3445,7 +3445,7 @@ emit_library_call_value_1 (int retval, rtx orgfun, rtx value,
for (; count < nargs; count++)
{
rtx val = va_arg (p, rtx);
- enum machine_mode mode = va_arg (p, enum machine_mode);
+ enum machine_mode mode = (enum machine_mode) va_arg (p, int);
/* We cannot convert the arg value to the mode the library wants here;
must do it earlier where we know the signedness of the arg. */
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 39aae8c4671..8da967a4ee0 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -1672,8 +1672,7 @@ try_crossjump_to_edge (int mode, edge e1, edge e2)
/* Skip possible basic block header. */
if (LABEL_P (newpos1))
newpos1 = NEXT_INSN (newpos1);
-
- if (NOTE_P (newpos1))
+ if (NOTE_INSN_BASIC_BLOCK_P (newpos1))
newpos1 = NEXT_INSN (newpos1);
redirect_from = split_block (src1, PREV_INSN (newpos1))->src;
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index 65a13de8a3d..31d346e6cb3 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2438,7 +2438,7 @@ gimple_expand_cfg (void)
rtl_profile_for_bb (ENTRY_BLOCK_PTR);
insn_locators_alloc ();
- if (!DECL_BUILT_IN (current_function_decl))
+ if (!DECL_IS_BUILTIN (current_function_decl))
{
/* Eventually, all FEs should explicitly set function_start_locus. */
if (cfun->function_start_locus == UNKNOWN_LOCATION)
diff --git a/gcc/cfglayout.c b/gcc/cfglayout.c
index ee72030327c..d93b84542fc 100644
--- a/gcc/cfglayout.c
+++ b/gcc/cfglayout.c
@@ -1112,7 +1112,7 @@ cfg_layout_can_duplicate_bb_p (const_basic_block bb)
rtx
duplicate_insn_chain (rtx from, rtx to)
{
- rtx insn, last;
+ rtx insn, last, copy;
/* Avoid updating of boundaries of previous basic block. The
note will get removed from insn stream in fixup. */
@@ -1133,7 +1133,8 @@ duplicate_insn_chain (rtx from, rtx to)
if (GET_CODE (PATTERN (insn)) == ADDR_VEC
|| GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
break;
- emit_copy_of_insn_after (insn, get_last_insn ());
+ copy = emit_copy_of_insn_after (insn, get_last_insn ());
+ maybe_copy_epilogue_insn (insn, copy);
break;
case CODE_LABEL:
@@ -1153,23 +1154,18 @@ duplicate_insn_chain (rtx from, rtx to)
case NOTE_INSN_DELETED:
case NOTE_INSN_DELETED_LABEL:
/* No problem to strip these. */
- case NOTE_INSN_EPILOGUE_BEG:
- /* Debug code expect these notes to exist just once.
- Keep them in the master copy.
- ??? It probably makes more sense to duplicate them for each
- epilogue copy. */
case NOTE_INSN_FUNCTION_BEG:
/* There is always just single entry to function. */
case NOTE_INSN_BASIC_BLOCK:
break;
+ case NOTE_INSN_EPILOGUE_BEG:
case NOTE_INSN_SWITCH_TEXT_SECTIONS:
emit_note_copy (insn);
break;
default:
- /* All other notes should have already been eliminated.
- */
+ /* All other notes should have already been eliminated. */
gcc_unreachable ();
}
break;
diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c
index a2c0e0f2026..040d4184e61 100644
--- a/gcc/cfgrtl.c
+++ b/gcc/cfgrtl.c
@@ -86,8 +86,16 @@ static void rtl_make_forwarder_block (edge);
static int
can_delete_note_p (const_rtx note)
{
- return (NOTE_KIND (note) == NOTE_INSN_DELETED
- || NOTE_KIND (note) == NOTE_INSN_BASIC_BLOCK);
+ switch (NOTE_KIND (note))
+ {
+ case NOTE_INSN_DELETED:
+ case NOTE_INSN_BASIC_BLOCK:
+ case NOTE_INSN_EPILOGUE_BEG:
+ return true;
+
+ default:
+ return false;
+ }
}
/* True if a given label can be deleted. */
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index c7939b9d2c4..fe1126bca91 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -1,5 +1,5 @@
/* Callgraph handling code.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008
+ Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Jan Hubicka
@@ -1377,8 +1377,9 @@ void
dump_cgraph_node (FILE *f, struct cgraph_node *node)
{
struct cgraph_edge *edge;
- fprintf (f, "%s/%i(%i) [%p]:", cgraph_node_name (node), node->uid,
- node->pid, (void *) node);
+ fprintf (f, "%s/%i(%i)", cgraph_node_name (node), node->uid,
+ node->pid);
+ dump_addr (f, " @", (void *)node);
if (node->global.inlined_to)
fprintf (f, " (inline copy in %s/%i)",
cgraph_node_name (node->global.inlined_to),
diff --git a/gcc/collect2-aix.c b/gcc/collect2-aix.c
new file mode 100644
index 00000000000..7d25e7e6b89
--- /dev/null
+++ b/gcc/collect2-aix.c
@@ -0,0 +1,371 @@
+/* AIX cross support for collect2.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "collect2-aix.h"
+
+#ifdef CROSS_AIX_SUPPORT
+
+#include <sys/mman.h>
+
+/* Read SIZE bytes starting at DATA as a big-endian value. */
+
+static inline bfd_vma
+read_value (char *data, unsigned int size)
+{
+ bfd_vma value;
+ unsigned int i;
+
+ value = 0;
+ for (i = 0; i < size; i++)
+ {
+ value <<= 8;
+ value += (unsigned char) data[i];
+ }
+ return value;
+}
+
+/* FIELD is a char array. Read the contents as a big-endian integer. */
+#define READ_FIELD(FIELD) \
+ read_value (FIELD, sizeof (FIELD))
+
+/* OBJECT is a char pointer to an in-file object of type struct TYPE.
+ Return the address of field FIELD. */
+#define OBJECT_FIELD(OBJECT, TYPE, FIELD) \
+ (OBJECT) + offsetof (struct TYPE, FIELD)
+
+/* Return the size of FIELD, which is a field of struct TYPE. */
+#define FIELD_SIZE(TYPE, FIELD) \
+ sizeof (((struct TYPE *) (0))->FIELD)
+
+/* OBJECT is a char pointer to an in-file object of type struct TYPE.
+ Read the value of field FIELD as a big-endian integer. */
+#define READ_OBJECT(OBJECT, TYPE, FIELD) \
+ read_value (OBJECT_FIELD (OBJECT, TYPE, FIELD), FIELD_SIZE (TYPE, FIELD))
+
+/* Copy FIELD from an external structure of type TYPE at address FROM
+ to an internal structure pointed to by TO. */
+#define COPY_FIELD(TO, FROM, TYPE, FIELD) \
+ ((TO)->FIELD = READ_OBJECT (FROM, TYPE, FIELD))
+
+/* Return true if STRING is less than SIZE bytes long. EXTRA_TERMINATOR
+ is another character (besides '\0') that acts as a terminator,
+ or '\0' if none. */
+
+static bool
+string_within_bounds_p (const char *string, size_t size, char extra_terminator)
+{
+ const char *p;
+
+ for (p = string; p < string + size; p++)
+ if (*p == '\0' || *p == extra_terminator)
+ return true;
+ return false;
+}
+
+/* STRING is a pointer to a char array. Try to read its value as an
+ ASCII-encoded integer. On success, return true and store the result
+ in TARGET. */
+#define PARSE_INTEGER(TARGET, STRING) \
+ (string_within_bounds_p (&(STRING)[0], sizeof (STRING), ' ') \
+ && ((TARGET) = strtoul (STRING, NULL, 0), true))
+
+/* Check that LDFILE's current object has SIZE bytes starting at OFFSET. */
+
+static inline bool
+within_object_p (LDFILE *ldfile, size_t offset, size_t size)
+{
+ return offset <= ldfile->object_size && offset + size <= ldfile->object_size;
+}
+
+/* Try to read the file header for an XCOFF object at OFFSET bytes into
+ LDFILE. The object is expected to be OBJECT_SIZE bytes in size.
+ If the object is a member of an archive, NEXT_MEMBER is the offset
+ of the next member, otherwise it is -1.
+
+ Return true on success, recording the object information in LDFILE. */
+
+static bool
+read_xcoff_object (LDFILE *ldfile, size_t offset, size_t object_size,
+ off_t next_member)
+{
+ struct internal_filehdr *internal;
+ char *external;
+ void *map;
+ size_t page_size;
+
+ /* First try to map the file into memory. */
+ page_size = getpagesize ();
+ ldfile->page_offset = offset & (page_size - 1);
+ map = mmap (NULL, object_size + ldfile->page_offset, PROT_READ,
+ MAP_SHARED, ldfile->fd, offset - ldfile->page_offset);
+ if (map == MAP_FAILED)
+ return false;
+
+ /* Record the success. */
+ ldfile->object = (char *) map + ldfile->page_offset;
+ ldfile->object_size = object_size;
+ ldfile->next_member = next_member;
+
+ /* Read the magic value to determine the type of file. */
+ if (!within_object_p (ldfile, 0, F_MAGIC_SIZE))
+ return false;
+
+ internal = &ldfile->filehdr;
+ external = ldfile->object;
+ internal->f_magic = read_value (external, F_MAGIC_SIZE);
+ if (internal->f_magic == U802TOCMAGIC)
+ {
+ if (!within_object_p (ldfile, 0, sizeof (struct external_filehdr_32)))
+ return false;
+
+ COPY_FIELD (internal, external, external_filehdr_32, f_nscns);
+ COPY_FIELD (internal, external, external_filehdr_32, f_timdat);
+ COPY_FIELD (internal, external, external_filehdr_32, f_symptr);
+ COPY_FIELD (internal, external, external_filehdr_32, f_nsyms);
+ COPY_FIELD (internal, external, external_filehdr_32, f_opthdr);
+ COPY_FIELD (internal, external, external_filehdr_32, f_flags);
+ return true;
+ }
+ else if (internal->f_magic == U803XTOCMAGIC
+ || internal->f_magic == U64_TOCMAGIC)
+ {
+ if (!within_object_p (ldfile, 0, sizeof (struct external_filehdr_64)))
+ return false;
+
+ COPY_FIELD (internal, external, external_filehdr_64, f_nscns);
+ COPY_FIELD (internal, external, external_filehdr_64, f_timdat);
+ COPY_FIELD (internal, external, external_filehdr_64, f_symptr);
+ COPY_FIELD (internal, external, external_filehdr_64, f_nsyms);
+ COPY_FIELD (internal, external, external_filehdr_64, f_opthdr);
+ COPY_FIELD (internal, external, external_filehdr_64, f_flags);
+ return true;
+ }
+ return false;
+}
+
+/* Try to read an archive member at OFFSET bytes into LDFILE.
+ Return true on success, recording the member and object
+ information in LDFILE. */
+
+static bool
+read_archive_member (LDFILE *ldfile, size_t offset)
+{
+ struct external_big_ar_member member;
+ size_t namlen;
+ size_t size;
+ off_t next_member;
+
+ if (lseek (ldfile->fd, offset, SEEK_SET) >= 0
+ && read (ldfile->fd, &member, sizeof (member)) == sizeof (member)
+ && PARSE_INTEGER (namlen, member.ar_namlen)
+ /* Stop once we reach the member table entry, which has a name
+ of length 0. */
+ && namlen > 0
+ && PARSE_INTEGER (size, member.ar_size)
+ && PARSE_INTEGER (next_member, member.ar_nextoff))
+ {
+ /* The archive is followed by an even-padded name, then by
+ a magic string of length SXCOFFARFMAG. The object itself
+ starts after that. */
+ offset += sizeof (member) + namlen + SXCOFFARFMAG;
+ offset += offset & 1;
+ return read_xcoff_object (ldfile, offset, size, next_member);
+ }
+ return false;
+}
+
+/* Try to treat LDFILE as a non-empty big archive. Return true
+ on success, storing the member and object information for
+ the first member in LDFILE. */
+
+static bool
+read_big_archive (LDFILE *ldfile)
+{
+ struct external_big_ar_filehdr filehdr;
+ size_t offset;
+
+ return (lseek (ldfile->fd, 0L, SEEK_SET) == 0
+ && read (ldfile->fd, &filehdr, sizeof (filehdr)) == sizeof (filehdr)
+ && memcmp (filehdr.fl_magic, FL_MAGIC_BIG_AR, FL_MAGIC_SIZE) == 0
+ && PARSE_INTEGER (offset, filehdr.fl_firstmemoff)
+ && read_archive_member (ldfile, offset));
+}
+
+/* LDFILE is a zero-initialized structure. Try to open FILENAME,
+ returning true on success. */
+
+static bool
+open_file (LDFILE *ldfile, const char *filename)
+{
+ struct stat st;
+
+ ldfile->fd = open (filename, O_RDONLY);
+ if (ldfile->fd < 0)
+ return false;
+
+ if (read_big_archive (ldfile))
+ return true;
+
+ if (fstat (ldfile->fd, &st) < 0)
+ return false;
+
+ return read_xcoff_object (ldfile, 0, st.st_size, -1);
+}
+
+/* Release the memory associated with the current object, if one has
+ been mapped. */
+
+static void
+free_object (LDFILE *ldfile)
+{
+ if (ldfile->object)
+ munmap (ldfile->object - ldfile->page_offset,
+ ldfile->object_size + ldfile->page_offset);
+}
+
+/* Free LDFILE and all resources associated with it. */
+
+static void
+free_ldfile (LDFILE *ldfile)
+{
+ if (ldfile->fd >= 0)
+ close (ldfile->fd);
+ XDELETE (ldfile);
+}
+
+/* Implement the API-defined ldopen function. */
+
+LDFILE *
+ldopen (char *filename, LDFILE *ldfile)
+{
+ if (ldfile == NULL)
+ {
+ ldfile = XCNEW (LDFILE);
+ if (!open_file (ldfile, filename))
+ {
+ free_object (ldfile);
+ free_ldfile (ldfile);
+ return NULL;
+ }
+ }
+ return ldfile;
+}
+
+/* Implement the API-defined ldtbread function. */
+
+int
+ldtbread (LDFILE *ldfile, long index, SYMENT *internal)
+{
+ size_t offset, name_length;
+ char *external;
+
+ /* Make sure that the symbol index is valid. */
+ if (index < 0 || index >= HEADER (ldfile).f_nsyms)
+ return FAILURE;
+
+ /* Work out the offset of the symbol table entry. */
+ offset = HEADER (ldfile).f_symptr + index * sizeof (struct external_syment);
+ if (!within_object_p (ldfile, offset, sizeof (struct external_syment)))
+ return FAILURE;
+
+ /* Read all the fields. The format differs between 32-bit and
+ 64-bit files. */
+ external = ldfile->object + offset;
+ if (HEADER (ldfile).f_magic == U802TOCMAGIC)
+ {
+ /* Copy the n_zeroes/n_offset interpretation. */
+ internal->n_zeroes = READ_OBJECT (external, external_syment,
+ u.xcoff32.u.u.n_zeroes);
+ internal->n_offset = READ_OBJECT (external, external_syment,
+ u.xcoff32.u.u.n_offset);
+
+ /* Copy the n_name interpretation. The internal version has room
+ for a null terminator. */
+ name_length = FIELD_SIZE (external_syment, u.xcoff32.u.n_name);
+ memcpy (internal->n_name,
+ external + offsetof (struct external_syment, u.xcoff32.u.n_name),
+ name_length);
+ internal->n_name[name_length] = 0;
+
+ internal->n_value = READ_OBJECT (external, external_syment,
+ u.xcoff32.n_value);
+ }
+ else
+ {
+ internal->n_zeroes = 0;
+ internal->n_offset = READ_OBJECT (external, external_syment,
+ u.xcoff64.n_offset);
+ internal->n_value = READ_OBJECT (external, external_syment,
+ u.xcoff64.n_value);
+ }
+ COPY_FIELD (internal, external, external_syment, n_scnum);
+ COPY_FIELD (internal, external, external_syment, n_type);
+ COPY_FIELD (internal, external, external_syment, n_sclass);
+ COPY_FIELD (internal, external, external_syment, n_numaux);
+ return SUCCESS;
+}
+
+/* Implement the API-defined ldgetname function. */
+
+char *
+ldgetname (LDFILE *ldfile, SYMENT *symbol)
+{
+ char *name;
+ size_t offset;
+
+ /* If the zeroes field is nonzero, the name is in the symbol table
+ entry itself. */
+ if (symbol->n_zeroes != 0)
+ return symbol->n_name;
+
+ /* Otherwise, the symbol table entry contains an offset into the
+ string table, which starts after the end of the symbol table. */
+ offset = (HEADER (ldfile).f_symptr
+ + HEADER (ldfile).f_nsyms * sizeof (struct external_syment)
+ + symbol->n_offset);
+ if (offset >= ldfile->object_size)
+ return NULL;
+
+ /* Make sure that the name is entirely contained within the object. */
+ name = ldfile->object + offset;
+ if (!string_within_bounds_p (name, ldfile->object_size - offset, '\0'))
+ return NULL;
+
+ return name;
+}
+
+/* Implement the API-defined ldclose function. */
+
+int
+ldclose (LDFILE *ldfile)
+{
+ free_object (ldfile);
+ if (ldfile->next_member >= 0
+ && read_archive_member (ldfile, ldfile->next_member))
+ return FAILURE;
+
+ free_ldfile (ldfile);
+ return SUCCESS;
+}
+
+#endif
diff --git a/gcc/collect2-aix.h b/gcc/collect2-aix.h
new file mode 100644
index 00000000000..1ab313d0f34
--- /dev/null
+++ b/gcc/collect2-aix.h
@@ -0,0 +1,301 @@
+/* AIX cross support for collect2.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* collect2-aix.c requires mmap support. It should otherwise be
+ fairly portable. */
+#if defined(CROSS_DIRECTORY_STRUCTURE) \
+ && defined(TARGET_AIX_VERSION) \
+ && HAVE_MMAP
+
+#define CROSS_AIX_SUPPORT 1
+
+/* -------------------------------------------------------------------------
+ Definitions adapted from bfd. (Fairly heavily adapted in some cases.)
+ ------------------------------------------------------------------------- */
+
+/* Compatiblity types for bfd. */
+typedef unsigned HOST_WIDE_INT bfd_vma;
+
+/* The size of an archive's fl_magic field. */
+#define FL_MAGIC_SIZE 8
+
+/* The expected contents of fl_magic for big archives. */
+#define FL_MAGIC_BIG_AR "<bigaf>\012"
+
+/* The size of each offset string in the header of a big archive. */
+#define AR_BIG_OFFSET_SIZE 20
+
+/* The format of the file header in a "big" XCOFF archive. */
+struct external_big_ar_filehdr
+{
+ /* Magic string. */
+ char fl_magic[FL_MAGIC_SIZE];
+
+ /* Offset of the member table (decimal ASCII string). */
+ char fl_memoff[AR_BIG_OFFSET_SIZE];
+
+ /* Offset of the global symbol table for 32-bit objects (decimal ASCII
+ string). */
+ char fl_symoff[AR_BIG_OFFSET_SIZE];
+
+ /* Offset of the global symbol table for 64-bit objects (decimal ASCII
+ string). */
+ char fl_symoff64[AR_BIG_OFFSET_SIZE];
+
+ /* Offset of the first member in the archive (decimal ASCII string). */
+ char fl_firstmemoff[AR_BIG_OFFSET_SIZE];
+
+ /* Offset of the last member in the archive (decimal ASCII string). */
+ char fl_lastmemoff[AR_BIG_OFFSET_SIZE];
+
+ /* Offset of the first member on the free list (decimal ASCII
+ string). */
+ char fl_freeoff[AR_BIG_OFFSET_SIZE];
+};
+
+/* Each archive name is followed by this many bytes of magic string. */
+#define SXCOFFARFMAG 2
+
+/* The format of a member header in a "big" XCOFF archive. */
+struct external_big_ar_member
+{
+ /* File size not including the header (decimal ASCII string). */
+ char ar_size[AR_BIG_OFFSET_SIZE];
+
+ /* File offset of next archive member (decimal ASCII string). */
+ char ar_nextoff[AR_BIG_OFFSET_SIZE];
+
+ /* File offset of previous archive member (decimal ASCII string). */
+ char ar_prevoff[AR_BIG_OFFSET_SIZE];
+
+ /* File mtime (decimal ASCII string). */
+ char ar_date[12];
+
+ /* File UID (decimal ASCII string). */
+ char ar_uid[12];
+
+ /* File GID (decimal ASCII string). */
+ char ar_gid[12];
+
+ /* File mode (octal ASCII string). */
+ char ar_mode[12];
+
+ /* Length of file name (decimal ASCII string). */
+ char ar_namlen[4];
+
+ /* This structure is followed by the file name. The length of the
+ name is given in the namlen field. If the length of the name is
+ odd, the name is followed by a null byte. The name and optional
+ null byte are followed by XCOFFARFMAG, which is not included in
+ namlen. The contents of the archive member follow; the number of
+ bytes is given in the size field. */
+};
+
+/* The known values of f_magic in an XCOFF file header. */
+#define U802WRMAGIC 0730 /* Writeable text segments. */
+#define U802ROMAGIC 0735 /* Readonly sharable text segments. */
+#define U802TOCMAGIC 0737 /* Readonly text segments and TOC. */
+#define U803XTOCMAGIC 0757 /* Aix 4.3 64-bit XCOFF. */
+#define U64_TOCMAGIC 0767 /* AIX 5+ 64-bit XCOFF. */
+
+/* The number of bytes in an XCOFF file's f_magic field. */
+#define F_MAGIC_SIZE 2
+
+/* The format of a 32-bit XCOFF file header. */
+struct external_filehdr_32
+{
+ /* The magic number. */
+ char f_magic[F_MAGIC_SIZE];
+
+ /* The number of sections. */
+ char f_nscns[2];
+
+ /* Time & date stamp. */
+ char f_timdat[4];
+
+ /* The offset of the symbol table from the start of the file. */
+ char f_symptr[4];
+
+ /* The number of entries in the symbol table. */
+ char f_nsyms[4];
+
+ /* The size of the auxillary header. */
+ char f_opthdr[2];
+
+ /* Flags. */
+ char f_flags[2];
+};
+
+/* The format of a 64-bit XCOFF file header. */
+struct external_filehdr_64
+{
+ /* The magic number. */
+ char f_magic[F_MAGIC_SIZE];
+
+ /* The number of sections. */
+ char f_nscns[2];
+
+ /* Time & date stamp. */
+ char f_timdat[4];
+
+ /* The offset of the symbol table from the start of the file. */
+ char f_symptr[8];
+
+ /* The size of the auxillary header. */
+ char f_opthdr[2];
+
+ /* Flags. */
+ char f_flags[2];
+
+ /* The number of entries in the symbol table. */
+ char f_nsyms[4];
+};
+
+/* An internal representation of the XCOFF file header. */
+struct internal_filehdr
+{
+ unsigned short f_magic;
+ unsigned short f_nscns;
+ long f_timdat;
+ bfd_vma f_symptr;
+ long f_nsyms;
+ unsigned short f_opthdr;
+ unsigned short f_flags;
+};
+
+/* Symbol classes have their names in the debug section if this flag
+ is set. */
+#define DBXMASK 0x80
+
+/* The format of an XCOFF symbol-table entry. */
+struct external_syment
+{
+ union {
+ struct {
+ union {
+ /* The name of the symbol. There is an implicit null character
+ after the end of the array. */
+ char n_name[8];
+ struct {
+ /* If n_zeroes is zero, n_offset is the offset the name from
+ the start of the string table. */
+ char n_zeroes[4];
+ char n_offset[4];
+ } u;
+ } u;
+
+ /* The symbol's value. */
+ char n_value[4];
+ } xcoff32;
+ struct {
+ /* The symbol's value. */
+ char n_value[8];
+
+ /* The offset of the symbol from the start of the string table. */
+ char n_offset[4];
+ } xcoff64;
+ } u;
+
+ /* The number of the section to which this symbol belongs. */
+ char n_scnum[2];
+
+ /* The type of symbol. (It can be interpreted as an n_lang
+ and an n_cpu byte, but we don't care about that here.) */
+ char n_type[2];
+
+ /* The class of symbol (a C_* value). */
+ char n_sclass[1];
+
+ /* The number of auxillary symbols attached to this entry. */
+ char n_numaux[1];
+};
+
+/* Definitions required by collect2. */
+#define C_EXT 2
+
+#define F_SHROBJ 0x2000
+
+#define N_UNDEF ((short) 0)
+#define N_TMASK 060
+#define N_BTSHFT 4
+
+#define DT_NON 0
+#define DT_FCN 2
+
+/* -------------------------------------------------------------------------
+ Local code.
+ ------------------------------------------------------------------------- */
+
+/* An internal representation of an XCOFF symbol-table entry,
+ which is associated with the API-defined SYMENT type. */
+struct internal_syment
+{
+ char n_name[9];
+ unsigned int n_zeroes;
+ bfd_vma n_offset;
+ bfd_vma n_value;
+ short n_scnum;
+ unsigned short n_flags;
+ unsigned short n_type;
+ unsigned char n_sclass;
+ unsigned char n_numaux;
+};
+typedef struct internal_syment SYMENT;
+
+/* The internal representation of the API-defined LDFILE type. */
+struct internal_ldfile
+{
+ /* The file handle for the associated file, or -1 if it hasn't been
+ opened yet. */
+ int fd;
+
+ /* The start of the current XCOFF object, if one has been mapped
+ into memory. Null otherwise. */
+ char *object;
+
+ /* The offset of OBJECT from the start of the containing page. */
+ size_t page_offset;
+
+ /* The size of the file pointed to by OBJECT. Valid iff OFFSET
+ is nonnull. */
+ size_t object_size;
+
+ /* The offset of the next member in an archive after OBJECT,
+ or -1 if this isn't an archive. Valid iff OFFSET is nonnull. */
+ off_t next_member;
+
+ /* The parsed version of the XCOFF file header. */
+ struct internal_filehdr filehdr;
+};
+typedef struct internal_ldfile LDFILE;
+
+/* The API allows the file header to be directly accessed via this macro. */
+#define HEADER(FILE) ((FILE)->filehdr)
+
+/* API-defined return codes. SUCCESS must be > 0 and FAILURE must be <= 0. */
+#define SUCCESS 1
+#define FAILURE 0
+
+/* API-defined functions. */
+extern LDFILE *ldopen (char *, LDFILE *);
+extern char *ldgetname (LDFILE *, SYMENT *);
+extern int ldtbread (LDFILE *, long, SYMENT *);
+extern int ldclose (LDFILE *);
+
+#endif
diff --git a/gcc/collect2.c b/gcc/collect2.c
index 277ddd6dc4c..9848b903580 100644
--- a/gcc/collect2.c
+++ b/gcc/collect2.c
@@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
#define COLLECT
#include "collect2.h"
+#include "collect2-aix.h"
#include "demangle.h"
#include "obstack.h"
#include "intl.h"
@@ -54,7 +55,9 @@ along with GCC; see the file COPYING3. If not see
cross-versions are in the proper directories. */
#ifdef CROSS_DIRECTORY_STRUCTURE
+#ifndef CROSS_AIX_SUPPORT
#undef OBJECT_FORMAT_COFF
+#endif
#undef MD_EXEC_PREFIX
#undef REAL_LD_FILE_NAME
#undef REAL_NM_FILE_NAME
@@ -72,6 +75,7 @@ along with GCC; see the file COPYING3. If not see
#ifdef OBJECT_FORMAT_COFF
+#ifndef CROSS_DIRECTORY_STRUCTURE
#include <a.out.h>
#include <ar.h>
@@ -86,6 +90,7 @@ along with GCC; see the file COPYING3. If not see
#endif
#include <ldfcn.h>
+#endif
/* Some systems have an ISCOFF macro, but others do not. In some cases
the macro may be wrong. MY_ISCOFF is defined in tm.h files for machines
@@ -212,6 +217,14 @@ static char *response_file; /* Name of any current response file */
struct obstack temporary_obstack;
char * temporary_firstobj;
+/* A string that must be prepended to a target OS path in order to find
+ it on the host system. */
+#ifdef TARGET_SYSTEM_ROOT
+static const char *target_system_root = TARGET_SYSTEM_ROOT;
+#else
+static const char *target_system_root = "";
+#endif
+
/* Structure to hold all the directories in which to search for files to
execute. */
@@ -857,9 +870,12 @@ main (int argc, char **argv)
/* Do not invoke xcalloc before this point, since locale needs to be
set first, in case a diagnostic is issued. */
- ld1 = (const char **)(ld1_argv = XCNEWVEC (char *, argc+4));
- ld2 = (const char **)(ld2_argv = XCNEWVEC (char *, argc+11));
- object = (const char **)(object_lst = XCNEWVEC (char *, argc));
+ ld1_argv = XCNEWVEC (char *, argc + 4);
+ ld1 = CONST_CAST2 (const char **, char **, ld1_argv);
+ ld2_argv = XCNEWVEC (char *, argc + 11);
+ ld2 = CONST_CAST2 (const char **, char **, ld2_argv);
+ object_lst = XCNEWVEC (char *, argc);
+ object = CONST_CAST2 (const char **, char **, object_lst);
#ifdef DEBUG
debug = 1;
@@ -904,7 +920,8 @@ main (int argc, char **argv)
-fno-exceptions -w */
num_c_args += 5;
- c_ptr = (const char **) (c_argv = XCNEWVEC (char *, num_c_args));
+ c_argv = XCNEWVEC (char *, num_c_args);
+ c_ptr = CONST_CAST2 (const char **, char **, c_argv);
if (argc < 2)
fatal ("no arguments");
@@ -1215,6 +1232,8 @@ main (int argc, char **argv)
ld1--;
ld2--;
}
+ else if (strncmp (arg, "--sysroot=", 10) == 0)
+ target_system_root = arg + 10;
break;
}
}
@@ -1406,7 +1425,8 @@ main (int argc, char **argv)
if (strip_flag)
{
char **real_strip_argv = XCNEWVEC (char *, 3);
- const char ** strip_argv = (const char **) real_strip_argv;
+ const char ** strip_argv = CONST_CAST2 (const char **, char **,
+ real_strip_argv);
strip_argv[0] = strip_file_name;
strip_argv[1] = output_file;
@@ -2090,7 +2110,7 @@ scan_prog_file (const char *prog_name, enum pass which_pass)
void (*quit_handler) (int);
#endif
char *real_nm_argv[4];
- const char **nm_argv = (const char **) real_nm_argv;
+ const char **nm_argv = CONST_CAST2 (const char **, char**, real_nm_argv);
int argc = 0;
struct pex_obj *pex;
const char *errmsg;
@@ -2404,7 +2424,7 @@ scan_libraries (const char *prog_name)
# define GCC_SYMZERO(X) 0
/* 0757 = U803XTOCMAGIC (AIX 4.3) and 0767 = U64_TOCMAGIC (AIX V5) */
-#ifdef _AIX51
+#if TARGET_AIX_VERSION >= 51
# define GCC_CHECK_HDR(X) \
((HEADER (X).f_magic == U802TOCMAGIC && ! aix64_flag) \
|| (HEADER (X).f_magic == 0767 && aix64_flag))
@@ -2443,9 +2463,19 @@ static int ignore_library (const char *);
static int
ignore_library (const char *name)
{
- const char *const *p = &aix_std_libs[0];
- while (*p++ != NULL)
- if (! strcmp (name, *p)) return 1;
+ const char *const *p;
+ size_t length;
+
+ if (target_system_root[0] != '\0')
+ {
+ length = strlen (target_system_root);
+ if (strncmp (name, target_system_root, length) != 0)
+ return 0;
+ name += length;
+ }
+ for (p = &aix_std_libs[0]; *p != NULL; ++p)
+ if (strcmp (name, *p) == 0)
+ return 1;
return 0;
}
#endif /* COLLECT_EXPORT_LIST */
diff --git a/gcc/combine.c b/gcc/combine.c
index 7cdf396a66c..0f8b0874143 100644
--- a/gcc/combine.c
+++ b/gcc/combine.c
@@ -12144,6 +12144,7 @@ move_deaths (rtx x, rtx maybe_kill_insn, int from_luid, rtx to_insn,
return;
if (where_dead
+ && BLOCK_FOR_INSN (where_dead) == BLOCK_FOR_INSN (to_insn)
&& DF_INSN_LUID (where_dead) >= from_luid
&& DF_INSN_LUID (where_dead) < DF_INSN_LUID (to_insn))
{
diff --git a/gcc/common.opt b/gcc/common.opt
index 4894ef67290..8a36e499bb8 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -536,6 +536,10 @@ fdwarf2-cfi-asm
Common Report Var(flag_dwarf2_cfi_asm) Init(HAVE_GAS_CFI_DIRECTIVE)
Enable CFI tables via GAS assembler directives.
+fdump-unnumbered-links
+Common Report Var(flag_dump_unnumbered_links) VarExists
+Suppress output of previous and next insn numbers in debugging dumps
+
fearly-inlining
Common Report Var(flag_early_inlining) Init(1) Optimization
Perform early inlining
@@ -1123,8 +1127,8 @@ Common Report Var(flag_see) Init(0)
Eliminate redundant sign extensions using LCM.
fshow-column
-Common C ObjC C++ ObjC++ Report Var(flag_show_column) Init(0)
-Show column numbers in diagnostics, when available. Default off
+Common C ObjC C++ ObjC++ Report Var(flag_show_column) Init(1)
+Show column numbers in diagnostics, when available. Default on
fsignaling-nans
Common Report Var(flag_signaling_nans) Optimization
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 3763bd9ed32..98d4b1ed843 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -475,7 +475,8 @@ case ${target} in
exit 1
;;
esac
- fbsd_tm_file="${fbsd_tm_file} freebsd-spec.h freebsd.h"
+ fbsd_tm_file="${fbsd_tm_file} freebsd-spec.h freebsd.h freebsd-stdint.h"
+ use_gcc_stdint=wrap
;;
*-*-linux* | frv-*-*linux* | *-*-kfreebsd*-gnu | *-*-knetbsd*-gnu | *-*-gnu* | *-*-kopensolaris*-gnu)
extra_parts="crtbegin.o crtbeginS.o crtbeginT.o crtend.o crtendS.o"
@@ -1315,8 +1316,7 @@ i[34567]86-*-mingw* | x86_64-*-mingw*)
default_use_cxa_atexit=yes
use_gcc_stdint=wrap
case ${enable_threads} in
- "" | yes | win32)
- thread_file='win32'
+ "" | yes | win32) thread_file='win32'
tmake_file="${tmake_file} i386/t-gthr-win32"
;;
esac
@@ -3127,6 +3127,9 @@ case ${target} in
i[34567]86-*-linux* | x86_64-*-linux* | i[34567]86-*-kfreebsd*-gnu | x86_64-*-kfreebsd*-gnu)
tmake_file="${tmake_file} i386/t-fprules-softfp soft-fp/t-softfp i386/t-linux"
;;
+ i[34567]86-*-cygwin*)
+ tmake_file="${tmake_file} i386/t-fprules-softfp soft-fp/t-softfp"
+ ;;
ia64*-*-linux*)
tmake_file="${tmake_file} ia64/t-fprules-softfp soft-fp/t-softfp"
;;
diff --git a/gcc/config.in b/gcc/config.in
index d7aeb5950b9..870772d9c71 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -856,6 +856,13 @@
#endif
+/* Define if your assembler supports specifying the alignment of objects
+ allocated using the GAS .comm command. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_GAS_ALIGNED_COMM
+#endif
+
+
/* Define if your assembler supports .balign and .p2align. */
#ifndef USED_FOR_TARGET
#undef HAVE_GAS_BALIGN_AND_P2ALIGN
@@ -1397,6 +1404,12 @@
#endif
+/* Define if mpc is in use. */
+#ifndef USED_FOR_TARGET
+#undef HAVE_mpc
+#endif
+
+
/* Define as const if the declaration of iconv() needs const. */
#ifndef USED_FOR_TARGET
#undef ICONV_CONST
diff --git a/gcc/config/alpha/x-alpha b/gcc/config/alpha/x-alpha
index 27b5f466903..ecca70424af 100644
--- a/gcc/config/alpha/x-alpha
+++ b/gcc/config/alpha/x-alpha
@@ -1,3 +1,3 @@
driver-alpha.o: $(srcdir)/config/alpha/driver-alpha.c \
$(CONFIG_H) $(SYSTEM_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index eda5ceaace9..24a94a6ebfb 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -12822,22 +12822,23 @@ arm_get_frame_offsets (void)
{
int reg = -1;
- for (i = 4; i <= (TARGET_THUMB1 ? LAST_LO_REGNUM : 11); i++)
+ /* If it is safe to use r3, then do so. This sometimes
+ generates better code on Thumb-2 by avoiding the need to
+ use 32-bit push/pop instructions. */
+ if (!crtl->tail_call_emit
+ && arm_size_return_regs () <= 12)
{
- if ((offsets->saved_regs_mask & (1 << i)) == 0)
- {
- reg = i;
- break;
- }
- }
-
- if (reg == -1 && arm_size_return_regs () <= 12
- && !crtl->tail_call_emit)
- {
- /* Push/pop an argument register (r3) if all callee saved
- registers are already being pushed. */
reg = 3;
}
+ else
+ for (i = 4; i <= (TARGET_THUMB1 ? LAST_LO_REGNUM : 11); i++)
+ {
+ if ((offsets->saved_regs_mask & (1 << i)) == 0)
+ {
+ reg = i;
+ break;
+ }
+ }
if (reg != -1)
{
@@ -16984,7 +16985,7 @@ thumb_pushpop (FILE *f, unsigned long mask, int push, int *cfa_offset,
if (push && pushed_words && dwarf2out_do_frame ())
{
- char *l = dwarf2out_cfi_label ();
+ char *l = dwarf2out_cfi_label (false);
int pushed_mask = real_regs;
*cfa_offset += pushed_words * 4;
@@ -17880,7 +17881,7 @@ thumb1_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
the stack pointer. */
if (dwarf2out_do_frame ())
{
- char *l = dwarf2out_cfi_label ();
+ char *l = dwarf2out_cfi_label (false);
cfa_offset = cfa_offset + crtl->args.pretend_args_size;
dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
@@ -17929,7 +17930,7 @@ thumb1_output_function_prologue (FILE *f, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
if (dwarf2out_do_frame ())
{
- char *l = dwarf2out_cfi_label ();
+ char *l = dwarf2out_cfi_label (false);
cfa_offset = cfa_offset + 16;
dwarf2out_def_cfa (l, SP_REGNUM, cfa_offset);
diff --git a/gcc/config/arm/lib1funcs.asm b/gcc/config/arm/lib1funcs.asm
index b1f2bcc74b9..cc5b94e91fe 100644
--- a/gcc/config/arm/lib1funcs.asm
+++ b/gcc/config/arm/lib1funcs.asm
@@ -1096,6 +1096,27 @@ LSYM(Lover12):
FUNC_END div0
#endif /* L_dvmd_lnx */
+#ifdef L_clear_cache
+#if defined __ARM_EABI__ && defined __linux__
+@ EABI GNU/Linux call to cacheflush syscall.
+ FUNC_START clear_cache
+ push {r7}
+#if __ARM_ARCH__ >= 7 || defined(__ARM_ARCH_6T2__)
+ movw r7, #2
+ movt r7, #0xf
+#else
+ mov r7, #0xf0000
+ add r7, r7, #2
+#endif
+ mov r2, #0
+ swi 0
+ pop {r7}
+ RET
+ FUNC_END clear_cache
+#else
+#error "This is only for ARM EABI GNU/Linux"
+#endif
+#endif /* L_clear_cache */
/* ------------------------------------------------------------------------ */
/* Dword shift operations. */
/* All the following Dword shift variants rely on the fact that
diff --git a/gcc/config/arm/linux-eabi.h b/gcc/config/arm/linux-eabi.h
index 4174d70db4d..85410c09fa4 100644
--- a/gcc/config/arm/linux-eabi.h
+++ b/gcc/config/arm/linux-eabi.h
@@ -72,16 +72,8 @@
do not use -lfloat. */
#undef LIBGCC_SPEC
-/* Clear the instruction cache from `beg' to `end'. This makes an
- inline system call to SYS_cacheflush. */
+/* Clear the instruction cache from `beg' to `end'. This is
+ implemented in lib1funcs.asm, so ensure an error if this definition
+ is used. */
#undef CLEAR_INSN_CACHE
-#define CLEAR_INSN_CACHE(BEG, END) \
-{ \
- register unsigned long _beg __asm ("a1") = (unsigned long) (BEG); \
- register unsigned long _end __asm ("a2") = (unsigned long) (END); \
- register unsigned long _flg __asm ("a3") = 0; \
- register unsigned long _scno __asm ("r7") = 0xf0002; \
- __asm __volatile ("swi 0 @ sys_cacheflush" \
- : "=r" (_beg) \
- : "0" (_beg), "r" (_end), "r" (_flg), "r" (_scno)); \
-}
+#define CLEAR_INSN_CACHE(BEG, END) not used
diff --git a/gcc/config/arm/t-arm b/gcc/config/arm/t-arm
index 83b874c040e..c47297f828b 100644
--- a/gcc/config/arm/t-arm
+++ b/gcc/config/arm/t-arm
@@ -1,6 +1,6 @@
# Rules common to all arm targets
#
-# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -44,5 +44,5 @@ $(srcdir)/config/arm/arm-tune.md: $(srcdir)/config/arm/gentune.sh \
arm-c.o: $(srcdir)/config/arm/arm-c.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/arm-c.c
-
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/arm/arm-c.c
diff --git a/gcc/config/arm/t-linux-eabi b/gcc/config/arm/t-linux-eabi
index ebd177bf7f5..b8a5ce04e65 100644
--- a/gcc/config/arm/t-linux-eabi
+++ b/gcc/config/arm/t-linux-eabi
@@ -24,8 +24,8 @@ TARGET_LIBGCC2_CFLAGS = -fPIC
MULTILIB_OPTIONS =
MULTILIB_DIRNAMES =
-# Use a version of div0 which raises SIGFPE.
-LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx
+# Use a version of div0 which raises SIGFPE, and a special __clear_cache.
+LIB1ASMFUNCS := $(filter-out _dvmd_tls,$(LIB1ASMFUNCS)) _dvmd_lnx _clear_cache
# Multilib the standard Linux files. Don't include crti.o or crtn.o,
# which are provided by glibc.
diff --git a/gcc/config/arm/t-pe b/gcc/config/arm/t-pe
index 9b8f4a6160b..e965a1c61c2 100644
--- a/gcc/config/arm/t-pe
+++ b/gcc/config/arm/t-pe
@@ -1,5 +1,5 @@
-# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006,
-# 2008 Free Software Foundation, Inc.
+# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2008, 2009
+# Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -41,7 +41,8 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/arm/pe.c
MULTILIB_OPTIONS = mhard-float mthumb
MULTILIB_DIRNAMES = fpu thumb
diff --git a/gcc/config/arm/t-wince-pe b/gcc/config/arm/t-wince-pe
index d41ff14e4f3..4fcb48376bd 100644
--- a/gcc/config/arm/t-wince-pe
+++ b/gcc/config/arm/t-wince-pe
@@ -1,4 +1,4 @@
-# Copyright (C) 2003, 2004, 2006, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2003, 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -40,7 +40,8 @@ dp-bit.c: $(srcdir)/config/fp-bit.c
pe.o: $(srcdir)/config/arm/pe.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/arm/pe.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/arm/pe.c
MULTILIB_OPTIONS = mhard-float
MULTILIB_DIRNAMES = fpu
diff --git a/gcc/config/arm/thumb2.md b/gcc/config/arm/thumb2.md
index 82d3413c7be..6ed6fb36cf4 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -849,30 +849,69 @@
;; Zero and sign extension instructions.
-(define_insn "*thumb2_zero_extendsidi2"
+(define_insn_and_split "*thumb2_zero_extendsidi2"
[(set (match_operand:DI 0 "s_register_operand" "=r")
(zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
"TARGET_THUMB2"
- "*
- /* ??? Output both instructions unconditionally, otherwise the conditional
- execution insn counter gets confused.
- if (REGNO (operands[1])
- != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) */
- output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
- return \"mov%?\\t%R0, #0\";
+ "mov%?\\t%Q0, %1\;mov%?\\t%R0, #0"
+ "&& reload_completed"
+ [(set (match_dup 0) (match_dup 1))]
+ "
+ {
+ rtx lo_part = gen_lowpart (SImode, operands[0]);
+ if (!REG_P (lo_part) || REGNO (lo_part) != REGNO (operands[1]))
+ emit_move_insn (lo_part, operands[1]);
+ operands[0] = gen_highpart (SImode, operands[0]);
+ operands[1] = const0_rtx;
+ }
"
[(set_attr "length" "8")
(set_attr "ce_count" "2")
(set_attr "predicable" "yes")]
)
-(define_insn "*thumb2_zero_extendqidi2"
+(define_insn_and_split "*thumb2_zero_extendhidi2"
+ [(set (match_operand:DI 0 "s_register_operand" "=r,r")
+ (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_THUMB2"
+ "@
+ uxth%?\\t%Q0, %1\;mov%?\\t%R0, #0
+ ldr%(h%)\\t%Q0, %1\;mov%?\\t%R0, #0"
+ "&& reload_completed"
+ [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
+ (set (match_dup 2) (match_dup 3))]
+ "
+ {
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[3] = const0_rtx;
+ }
+ "
+ [(set_attr "length" "8")
+ (set_attr "ce_count" "2")
+ (set_attr "predicable" "yes")
+ (set_attr "type" "*,load_byte")
+ (set_attr "pool_range" "*,4092")
+ (set_attr "neg_pool_range" "*,250")]
+)
+
+(define_insn_and_split "*thumb2_zero_extendqidi2"
[(set (match_operand:DI 0 "s_register_operand" "=r,r")
(zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
"TARGET_THUMB2"
"@
- and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
+ uxtb%?\\t%Q0, %1\;mov%?\\t%R0, #0
ldr%(b%)\\t%Q0, %1\;mov%?\\t%R0, #0"
+ "&& reload_completed"
+ [(set (match_dup 0) (zero_extend:SI (match_dup 1)))
+ (set (match_dup 2) (match_dup 3))]
+ "
+ {
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ operands[3] = const0_rtx;
+ }
+ "
[(set_attr "length" "8")
(set_attr "ce_count" "2")
(set_attr "predicable" "yes")
@@ -881,24 +920,74 @@
(set_attr "neg_pool_range" "*,250")]
)
-(define_insn "*thumb2_extendsidi2"
+(define_insn_and_split "*thumb2_extendsidi2"
[(set (match_operand:DI 0 "s_register_operand" "=r")
(sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
"TARGET_THUMB2"
- "*
- /* ??? Output both instructions unconditionally, otherwise the conditional
- execution insn counter gets confused.
- if (REGNO (operands[1])
- != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0)) */
- output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
- return \"asr%?\\t%R0, %Q0, #31\";
- "
+ "mov%?\\t%Q0, %1\;asr?\\t%R0, %1, #31"
+ "&& reload_completed"
+ [(set (match_dup 0) (ashiftrt:SI (match_dup 1) (const_int 31)))]
+ {
+ rtx lo_part = gen_lowpart (SImode, operands[0]);
+
+ if (!REG_P (lo_part) || REGNO (lo_part) != REGNO (operands[1]))
+ emit_move_insn (lo_part, operands[1]);
+ operands[0] = gen_highpart (SImode, operands[0]);
+ }
[(set_attr "length" "8")
(set_attr "ce_count" "2")
(set_attr "shift" "1")
(set_attr "predicable" "yes")]
)
+(define_insn_and_split "*thumb2_extendhidi2"
+ [(set (match_operand:DI 0 "s_register_operand" "=r,r")
+ (sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_THUMB2"
+ "@
+ sxth%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31
+ ldrsh%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31"
+ "&& reload_completed"
+ [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
+ (set (match_dup 2) (ashiftrt:SI (match_dup 0) (const_int 31)))]
+ "
+ {
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ }
+ "
+ [(set_attr "length" "8")
+ (set_attr "ce_count" "2")
+ (set_attr "predicable" "yes")
+ (set_attr "type" "*,load_byte")
+ (set_attr "pool_range" "*,4092")
+ (set_attr "neg_pool_range" "*,250")]
+)
+
+(define_insn_and_split "*thumb2_extendqidi2"
+ [(set (match_operand:DI 0 "s_register_operand" "=r,r")
+ (sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
+ "TARGET_THUMB2"
+ "@
+ sxtb%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31
+ ldrsb%?\\t%Q0, %1\;asr%?\\t%R0, %Q0, #31"
+ "&& reload_completed"
+ [(set (match_dup 0) (sign_extend:SI (match_dup 1)))
+ (set (match_dup 2) (ashiftrt:SI (match_dup 0) (const_int 31)))]
+ "
+ {
+ operands[2] = gen_highpart (SImode, operands[0]);
+ operands[0] = gen_lowpart (SImode, operands[0]);
+ }
+ "
+ [(set_attr "length" "8")
+ (set_attr "ce_count" "2")
+ (set_attr "predicable" "yes")
+ (set_attr "type" "*,load_byte")
+ (set_attr "pool_range" "*,4092")
+ (set_attr "neg_pool_range" "*,250")]
+)
+
;; All supported Thumb2 implementations are armv6, so only that case is
;; provided.
(define_insn "*thumb2_extendqisi_v6"
diff --git a/gcc/config/bfin/bfin.md b/gcc/config/bfin/bfin.md
index 755a0d3ced6..a3638700a53 100644
--- a/gcc/config/bfin/bfin.md
+++ b/gcc/config/bfin/bfin.md
@@ -141,8 +141,7 @@
(UNSPEC_ONES 12)])
(define_constants
- [(UNSPEC_VOLATILE_EH_RETURN 0)
- (UNSPEC_VOLATILE_CSYNC 1)
+ [(UNSPEC_VOLATILE_CSYNC 1)
(UNSPEC_VOLATILE_SSYNC 2)
(UNSPEC_VOLATILE_LOAD_FUNCDESC 3)
(UNSPEC_VOLATILE_STORE_EH_HANDLER 4)
@@ -2573,8 +2572,7 @@
"bfin_expand_epilogue (0, 0, 1); DONE;")
(define_expand "eh_return"
- [(unspec_volatile [(match_operand:SI 0 "register_operand" "")]
- UNSPEC_VOLATILE_EH_RETURN)]
+ [(use (match_operand:SI 0 "register_operand" ""))]
""
{
emit_insn (gen_eh_store_handler (EH_RETURN_HANDLER_RTX, operands[0]));
@@ -2592,11 +2590,10 @@
[(set_attr "type" "mcst")])
(define_insn_and_split "eh_return_internal"
- [(set (pc)
- (unspec_volatile [(reg:SI REG_P2)] UNSPEC_VOLATILE_EH_RETURN))]
+ [(eh_return)]
""
"#"
- "reload_completed"
+ "epilogue_completed"
[(const_int 1)]
"bfin_expand_epilogue (1, 1, 0); DONE;")
diff --git a/gcc/config/freebsd-stdint.h b/gcc/config/freebsd-stdint.h
new file mode 100644
index 00000000000..2719e41b310
--- /dev/null
+++ b/gcc/config/freebsd-stdint.h
@@ -0,0 +1,56 @@
+/* Definitions for <stdint.h> types for FreeBSD systems.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+ Contributed by Gerald Pfeifer <gerald@pfeifer.com>.
+
+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
+<http://www.gnu.org/licenses/>. */
+
+#define SIG_ATOMIC_TYPE "int"
+
+#define INT8_TYPE "signed char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_LEAST8_TYPE "signed char"
+#define INT_LEAST16_TYPE "short int"
+#define INT_LEAST32_TYPE "int"
+#define INT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT_LEAST8_TYPE "unsigned char"
+#define UINT_LEAST16_TYPE "short unsigned int"
+#define UINT_LEAST32_TYPE "unsigned int"
+#define UINT_LEAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INT_FAST8_TYPE "int"
+#define INT_FAST16_TYPE "int"
+#define INT_FAST32_TYPE "int"
+#define INT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "long long int")
+#define UINT_FAST8_TYPE "unsigned int"
+#define UINT_FAST16_TYPE "unsigned int"
+#define UINT_FAST32_TYPE "unsigned int"
+#define UINT_FAST64_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "long long unsigned int")
+
+#define INTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long int" : "int")
+#define UINTPTR_TYPE (LONG_TYPE_SIZE == 64 ? "long unsigned int" : "unsigned int")
diff --git a/gcc/config/i386/cygming.opt b/gcc/config/i386/cygming.opt
index 7c29eb89b9f..e845a0d5827 100644
--- a/gcc/config/i386/cygming.opt
+++ b/gcc/config/i386/cygming.opt
@@ -45,3 +45,7 @@ Set Windows defines
mwindows
Target
Create GUI application
+
+mpe-aligned-commons
+Target Var(use_pe_aligned_common) Init(HAVE_GAS_ALIGNED_COMM)
+Use the GNU extension to the PE format for aligned common data
diff --git a/gcc/config/i386/driver-i386.c b/gcc/config/i386/driver-i386.c
index 4fc00989694..0364beaebf4 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -378,7 +378,9 @@ const char *host_detect_local_cpu (int argc, const char **argv)
/* Extended features */
unsigned int has_lahf_lm = 0, has_sse4a = 0;
unsigned int has_longmode = 0, has_3dnowp = 0, has_3dnow = 0;
- unsigned int has_movbe = 0;
+ unsigned int has_movbe = 0, has_sse4_1 = 0, has_sse4_2 = 0;
+ unsigned int has_popcnt = 0, has_aes = 0, has_avx = 0;
+ unsigned int has_pclmul = 0;
bool arch;
@@ -415,8 +417,14 @@ const char *host_detect_local_cpu (int argc, const char **argv)
has_sse3 = ecx & bit_SSE3;
has_ssse3 = ecx & bit_SSSE3;
+ has_sse4_1 = ecx & bit_SSE4_1;
+ has_sse4_2 = ecx & bit_SSE4_2;
+ has_avx = ecx & bit_AVX;
has_cmpxchg16b = ecx & bit_CMPXCHG16B;
has_movbe = ecx & bit_MOVBE;
+ has_popcnt = ecx & bit_POPCNT;
+ has_aes = ecx & bit_AES;
+ has_pclmul = ecx & bit_PCLMUL;
has_cmpxchg8b = edx & bit_CMPXCHG8B;
has_cmov = edx & bit_CMOV;
@@ -604,7 +612,19 @@ const char *host_detect_local_cpu (int argc, const char **argv)
if (has_lahf_lm)
options = concat (options, "-msahf ", NULL);
if (has_movbe)
- options = concat (options, "-mmovbe", NULL);
+ options = concat (options, "-mmovbe ", NULL);
+ if (has_aes)
+ options = concat (options, "-maes ", NULL);
+ if (has_pclmul)
+ options = concat (options, "-mpclmul ", NULL);
+ if (has_popcnt)
+ options = concat (options, "-mpopcnt ", NULL);
+ if (has_avx)
+ options = concat (options, "-mavx ", NULL);
+ else if (has_sse4_2)
+ options = concat (options, "-msse4.2 ", NULL);
+ else if (has_sse4_1)
+ options = concat (options, "-msse4.1 ", NULL);
}
done:
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 55ec1d921cb..be9c7ad325c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -7609,6 +7609,9 @@ output_set_got (rtx dest, rtx label ATTRIBUTE_UNUSED)
static rtx
gen_push (rtx arg)
{
+ if (ix86_cfa_state->reg == stack_pointer_rtx)
+ ix86_cfa_state->offset += UNITS_PER_WORD;
+
return gen_rtx_SET (VOIDmode,
gen_rtx_MEM (Pmode,
gen_rtx_PRE_DEC (Pmode,
@@ -7668,8 +7671,7 @@ ix86_save_reg (unsigned int regno, int maybe_eh_return)
}
}
- if (crtl->drap_reg
- && regno == REGNO (crtl->drap_reg))
+ if (crtl->drap_reg && regno == REGNO (crtl->drap_reg))
return 1;
return (df_regs_ever_live_p (regno)
@@ -7998,6 +8000,49 @@ ix86_emit_save_sse_regs_using_mov (rtx pointer, HOST_WIDE_INT offset)
}
}
+static GTY(()) rtx queued_cfa_restores;
+
+/* Add a REG_CFA_RESTORE REG note to INSN or queue them until next stack
+ manipulation insn. Don't add it if the previously
+ saved value will be left untouched within stack red-zone till return,
+ as unwinders can find the same value in the register and
+ on the stack. */
+
+static void
+ix86_add_cfa_restore_note (rtx insn, rtx reg, HOST_WIDE_INT red_offset)
+{
+ if (TARGET_RED_ZONE
+ && !TARGET_64BIT_MS_ABI
+ && red_offset + RED_ZONE_SIZE >= 0
+ && crtl->args.pops_args < 65536)
+ return;
+
+ if (insn)
+ {
+ add_reg_note (insn, REG_CFA_RESTORE, reg);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else
+ queued_cfa_restores
+ = alloc_reg_note (REG_CFA_RESTORE, reg, queued_cfa_restores);
+}
+
+/* Add queued REG_CFA_RESTORE notes if any to INSN. */
+
+static void
+ix86_add_queued_cfa_restore_notes (rtx insn)
+{
+ rtx last;
+ if (!queued_cfa_restores)
+ return;
+ for (last = queued_cfa_restores; XEXP (last, 1); last = XEXP (last, 1))
+ ;
+ XEXP (last, 1) = REG_NOTES (insn);
+ REG_NOTES (insn) = queued_cfa_restores;
+ queued_cfa_restores = NULL_RTX;
+ RTX_FRAME_RELATED_P (insn) = 1;
+}
+
/* Expand prologue or epilogue stack adjustment.
The pattern exist to put a dependency on all ebp-based memory accesses.
STYLE should be negative if instructions should be marked as frame related,
@@ -8005,7 +8050,8 @@ ix86_emit_save_sse_regs_using_mov (rtx pointer, HOST_WIDE_INT offset)
otherwise. */
static void
-pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, int style)
+pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset,
+ int style, bool set_cfa)
{
rtx insn;
@@ -8028,7 +8074,24 @@ pro_epilogue_adjust_stack (rtx dest, rtx src, rtx offset, int style)
insn = emit_insn (gen_pro_epilogue_adjust_stack_rex64_2 (dest, src, r11,
offset));
}
- if (style < 0)
+
+ if (style >= 0)
+ ix86_add_queued_cfa_restore_notes (insn);
+
+ if (set_cfa)
+ {
+ rtx r;
+
+ gcc_assert (ix86_cfa_state->reg == src);
+ ix86_cfa_state->offset += INTVAL (offset);
+ ix86_cfa_state->reg = dest;
+
+ r = gen_rtx_PLUS (Pmode, src, offset);
+ r = gen_rtx_SET (VOIDmode, dest, r);
+ add_reg_note (insn, REG_CFA_ADJUST_CFA, r);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else if (style < 0)
RTX_FRAME_RELATED_P (insn) = 1;
}
@@ -8164,30 +8227,6 @@ ix86_internal_arg_pointer (void)
return virtual_incoming_args_rtx;
}
-/* Handle the TARGET_DWARF_HANDLE_FRAME_UNSPEC hook.
- This is called from dwarf2out.c to emit call frame instructions
- for frame-related insns containing UNSPECs and UNSPEC_VOLATILEs. */
-static void
-ix86_dwarf_handle_frame_unspec (const char *label, rtx pattern, int index)
-{
- rtx unspec = SET_SRC (pattern);
- gcc_assert (GET_CODE (unspec) == UNSPEC);
-
- switch (index)
- {
- case UNSPEC_REG_SAVE:
- dwarf2out_reg_save_reg (label, XVECEXP (unspec, 0, 0),
- SET_DEST (pattern));
- break;
- case UNSPEC_DEF_CFA:
- dwarf2out_def_cfa (label, REGNO (SET_DEST (pattern)),
- INTVAL (XVECEXP (unspec, 0, 0)));
- break;
- default:
- gcc_unreachable ();
- }
-}
-
/* Finalize stack_realign_needed flag, which will guide prologue/epilogue
to be generated in correct form. */
static void
@@ -8231,6 +8270,10 @@ ix86_expand_prologue (void)
/* DRAP should not coexist with stack_realign_fp */
gcc_assert (!(crtl->drap_reg && stack_realign_fp));
+ /* Initialize CFA state for before the prologue. */
+ ix86_cfa_state->reg = stack_pointer_rtx;
+ ix86_cfa_state->offset = INCOMING_FRAME_SP_OFFSET;
+
ix86_compute_frame_layout (&frame);
/* Emit prologue code to adjust stack alignment and setup DRAP, in case
@@ -8260,6 +8303,7 @@ ix86_expand_prologue (void)
insn = emit_insn (gen_rtx_SET (VOIDmode, y, x));
RTX_FRAME_RELATED_P (insn) = 1;
+ ix86_cfa_state->reg = crtl->drap_reg;
/* Align the stack. */
insn = emit_insn ((*ix86_gen_andsp) (stack_pointer_rtx,
@@ -8288,6 +8332,9 @@ ix86_expand_prologue (void)
insn = emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx);
RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (ix86_cfa_state->reg == stack_pointer_rtx)
+ ix86_cfa_state->reg = hard_frame_pointer_rtx;
}
if (stack_realign_fp)
@@ -8326,7 +8373,8 @@ ix86_expand_prologue (void)
;
else if (! TARGET_STACK_PROBE || allocate < CHECK_STACK_LIMIT)
pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (-allocate), -1);
+ GEN_INT (-allocate), -1,
+ ix86_cfa_state->reg == stack_pointer_rtx);
else
{
/* Only valid for Win32. */
@@ -8354,10 +8402,15 @@ ix86_expand_prologue (void)
else
insn = gen_allocate_stack_worker_32 (eax, eax);
insn = emit_insn (insn);
- RTX_FRAME_RELATED_P (insn) = 1;
- t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-allocate));
- t = gen_rtx_SET (VOIDmode, stack_pointer_rtx, t);
- add_reg_note (insn, REG_FRAME_RELATED_EXPR, t);
+
+ if (ix86_cfa_state->reg == stack_pointer_rtx)
+ {
+ ix86_cfa_state->offset += allocate;
+ t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-allocate));
+ t = gen_rtx_SET (VOIDmode, stack_pointer_rtx, t);
+ add_reg_note (insn, REG_CFA_ADJUST_CFA, t);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
if (eax_live)
{
@@ -8464,18 +8517,104 @@ ix86_expand_prologue (void)
emit_insn (gen_cld ());
}
+/* Emit code to restore REG using a POP insn. */
+
+static void
+ix86_emit_restore_reg_using_pop (rtx reg, HOST_WIDE_INT red_offset)
+{
+ rtx insn = emit_insn (ix86_gen_pop1 (reg));
+
+ if (ix86_cfa_state->reg == crtl->drap_reg
+ && REGNO (reg) == REGNO (crtl->drap_reg))
+ {
+ /* Previously we'd represented the CFA as an expression
+ like *(%ebp - 8). We've just popped that value from
+ the stack, which means we need to reset the CFA to
+ the drap register. This will remain until we restore
+ the stack pointer. */
+ add_reg_note (insn, REG_CFA_DEF_CFA, reg);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ return;
+ }
+
+ if (ix86_cfa_state->reg == stack_pointer_rtx)
+ {
+ ix86_cfa_state->offset -= UNITS_PER_WORD;
+ add_reg_note (insn, REG_CFA_ADJUST_CFA,
+ copy_rtx (XVECEXP (PATTERN (insn), 0, 1)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ /* When the frame pointer is the CFA, and we pop it, we are
+ swapping back to the stack pointer as the CFA. This happens
+ for stack frames that don't allocate other data, so we assume
+ the stack pointer is now pointing at the return address, i.e.
+ the function entry state, which makes the offset be 1 word. */
+ else if (ix86_cfa_state->reg == hard_frame_pointer_rtx
+ && reg == hard_frame_pointer_rtx)
+ {
+ ix86_cfa_state->reg = stack_pointer_rtx;
+ ix86_cfa_state->offset = UNITS_PER_WORD;
+
+ add_reg_note (insn, REG_CFA_DEF_CFA,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ GEN_INT (UNITS_PER_WORD)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+
+ ix86_add_cfa_restore_note (insn, reg, red_offset);
+}
+
+/* Emit code to restore saved registers using POP insns. */
+
+static void
+ix86_emit_restore_regs_using_pop (HOST_WIDE_INT red_offset)
+{
+ int regno;
+
+ for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+ if (!SSE_REGNO_P (regno) && ix86_save_reg (regno, false))
+ {
+ ix86_emit_restore_reg_using_pop (gen_rtx_REG (Pmode, regno),
+ red_offset);
+ red_offset += UNITS_PER_WORD;
+ }
+}
+
+/* Emit code and notes for the LEAVE instruction. */
+
+static void
+ix86_emit_leave (HOST_WIDE_INT red_offset)
+{
+ rtx insn = emit_insn (ix86_gen_leave ());
+
+ ix86_add_queued_cfa_restore_notes (insn);
+
+ if (ix86_cfa_state->reg == hard_frame_pointer_rtx)
+ {
+ add_reg_note (insn, REG_CFA_ADJUST_CFA,
+ copy_rtx (XVECEXP (PATTERN (insn), 0, 0)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+ ix86_add_cfa_restore_note (insn, hard_frame_pointer_rtx, red_offset);
+ }
+}
+
/* Emit code to restore saved registers using MOV insns. First register
is restored from POINTER + OFFSET. */
static void
ix86_emit_restore_regs_using_mov (rtx pointer, HOST_WIDE_INT offset,
+ HOST_WIDE_INT red_offset,
int maybe_eh_return)
{
- int regno;
+ unsigned int regno;
rtx base_address = gen_rtx_MEM (Pmode, pointer);
+ rtx insn;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (!SSE_REGNO_P (regno) && ix86_save_reg (regno, maybe_eh_return))
{
+ rtx reg = gen_rtx_REG (Pmode, regno);
+
/* Ensure that adjust_address won't be forced to produce pointer
out of range allowed by x86-64 instruction set. */
if (TARGET_64BIT && offset != trunc_int_for_mode (offset, SImode))
@@ -8488,9 +8627,25 @@ ix86_emit_restore_regs_using_mov (rtx pointer, HOST_WIDE_INT offset,
base_address = gen_rtx_MEM (Pmode, r11);
offset = 0;
}
- emit_move_insn (gen_rtx_REG (Pmode, regno),
- adjust_address (base_address, Pmode, offset));
+ insn = emit_move_insn (reg,
+ adjust_address (base_address, Pmode, offset));
offset += UNITS_PER_WORD;
+
+ if (ix86_cfa_state->reg == crtl->drap_reg
+ && regno == REGNO (crtl->drap_reg))
+ {
+ /* Previously we'd represented the CFA as an expression
+ like *(%ebp - 8). We've just popped that value from
+ the stack, which means we need to reset the CFA to
+ the drap register. This will remain until we restore
+ the stack pointer. */
+ add_reg_note (insn, REG_CFA_DEF_CFA, reg);
+ RTX_FRAME_RELATED_P (insn) = 1;
+ }
+ else
+ ix86_add_cfa_restore_note (NULL_RTX, reg, red_offset);
+
+ red_offset += UNITS_PER_WORD;
}
}
@@ -8498,15 +8653,18 @@ ix86_emit_restore_regs_using_mov (rtx pointer, HOST_WIDE_INT offset,
is restored from POINTER + OFFSET. */
static void
ix86_emit_restore_sse_regs_using_mov (rtx pointer, HOST_WIDE_INT offset,
+ HOST_WIDE_INT red_offset,
int maybe_eh_return)
{
int regno;
rtx base_address = gen_rtx_MEM (TImode, pointer);
- rtx mem;
+ rtx mem, insn;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
if (SSE_REGNO_P (regno) && ix86_save_reg (regno, maybe_eh_return))
{
+ rtx reg = gen_rtx_REG (TImode, regno);
+
/* Ensure that adjust_address won't be forced to produce pointer
out of range allowed by x86-64 instruction set. */
if (TARGET_64BIT && offset != trunc_int_for_mode (offset, SImode))
@@ -8521,8 +8679,12 @@ ix86_emit_restore_sse_regs_using_mov (rtx pointer, HOST_WIDE_INT offset,
}
mem = adjust_address (base_address, TImode, offset);
set_mem_align (mem, 128);
- emit_move_insn (gen_rtx_REG (TImode, regno), mem);
+ insn = emit_move_insn (reg, mem);
offset += 16;
+
+ ix86_add_cfa_restore_note (NULL_RTX, reg, red_offset);
+
+ red_offset += 16;
}
}
@@ -8531,10 +8693,11 @@ ix86_emit_restore_sse_regs_using_mov (rtx pointer, HOST_WIDE_INT offset,
void
ix86_expand_epilogue (int style)
{
- int regno;
int sp_valid;
struct ix86_frame frame;
- HOST_WIDE_INT offset;
+ HOST_WIDE_INT offset, red_offset;
+ struct machine_cfa_state cfa_state_save = *ix86_cfa_state;
+ bool using_drap;
ix86_finalize_stack_realign_flags ();
@@ -8550,6 +8713,9 @@ ix86_expand_epilogue (int style)
if (frame_pointer_needed && frame.red_zone_size)
emit_insn (gen_memory_blockage ());
+ using_drap = crtl->drap_reg && crtl->stack_realign_needed;
+ gcc_assert (!using_drap || ix86_cfa_state->reg == crtl->drap_reg);
+
/* Calculate start of saved registers relative to ebp. Special care
must be taken for the normal return case of a function using
eh_return: the eax and edx registers are marked as saved, but not
@@ -8560,6 +8726,19 @@ ix86_expand_epilogue (int style)
offset *= -UNITS_PER_WORD;
offset -= frame.nsseregs * 16 + frame.padding0;
+ /* Calculate start of saved registers relative to esp on entry of the
+ function. When realigning stack, this needs to be the most negative
+ value possible at runtime. */
+ red_offset = offset;
+ if (using_drap)
+ red_offset -= crtl->stack_alignment_needed / BITS_PER_UNIT
+ + UNITS_PER_WORD;
+ else if (stack_realign_fp)
+ red_offset -= crtl->stack_alignment_needed / BITS_PER_UNIT
+ - UNITS_PER_WORD;
+ if (frame_pointer_needed)
+ red_offset -= UNITS_PER_WORD;
+
/* If we're only restoring one register and sp is not valid then
using a move instruction to restore the register since it's
less work than reloading sp and popping the register.
@@ -8574,7 +8753,8 @@ ix86_expand_epilogue (int style)
|| (TARGET_EPILOGUE_USING_MOVE
&& cfun->machine->use_fast_prologue_epilogue
&& ((frame.nregs + frame.nsseregs) > 1 || frame.to_allocate))
- || (frame_pointer_needed && !(frame.nregs + frame.nsseregs) && frame.to_allocate)
+ || (frame_pointer_needed && !(frame.nregs + frame.nsseregs)
+ && frame.to_allocate)
|| (frame_pointer_needed && TARGET_USE_LEAVE
&& cfun->machine->use_fast_prologue_epilogue
&& (frame.nregs + frame.nsseregs) == 1)
@@ -8594,22 +8774,32 @@ ix86_expand_epilogue (int style)
|| stack_realign_fp)
{
ix86_emit_restore_sse_regs_using_mov (stack_pointer_rtx,
- frame.to_allocate, style == 2);
+ frame.to_allocate, red_offset,
+ style == 2);
ix86_emit_restore_regs_using_mov (stack_pointer_rtx,
frame.to_allocate
+ frame.nsseregs * 16
+ + frame.padding0,
+ red_offset
+ + frame.nsseregs * 16
+ frame.padding0, style == 2);
}
else
{
ix86_emit_restore_sse_regs_using_mov (hard_frame_pointer_rtx,
- offset, style == 2);
+ offset, red_offset,
+ style == 2);
ix86_emit_restore_regs_using_mov (hard_frame_pointer_rtx,
offset
+ frame.nsseregs * 16
+ + frame.padding0,
+ red_offset
+ + frame.nsseregs * 16
+ frame.padding0, style == 2);
}
+ red_offset -= offset;
+
/* eh_return epilogues need %ecx added to the stack pointer. */
if (style == 2)
{
@@ -8622,13 +8812,29 @@ ix86_expand_epilogue (int style)
{
tmp = gen_rtx_PLUS (Pmode, hard_frame_pointer_rtx, sa);
tmp = plus_constant (tmp, UNITS_PER_WORD);
- emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
+ tmp = emit_insn (gen_rtx_SET (VOIDmode, sa, tmp));
tmp = gen_rtx_MEM (Pmode, hard_frame_pointer_rtx);
- emit_move_insn (hard_frame_pointer_rtx, tmp);
+ tmp = emit_move_insn (hard_frame_pointer_rtx, tmp);
+
+ /* Note that we use SA as a temporary CFA, as the return
+ address is at the proper place relative to it. We
+ pretend this happens at the FP restore insn because
+ prior to this insn the FP would be stored at the wrong
+ offset relative to SA, and after this insn we have no
+ other reasonable register to use for the CFA. We don't
+ bother resetting the CFA to the SP for the duration of
+ the return insn. */
+ add_reg_note (tmp, REG_CFA_DEF_CFA,
+ plus_constant (sa, UNITS_PER_WORD));
+ ix86_add_queued_cfa_restore_notes (tmp);
+ add_reg_note (tmp, REG_CFA_RESTORE, hard_frame_pointer_rtx);
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ ix86_cfa_state->reg = sa;
+ ix86_cfa_state->offset = UNITS_PER_WORD;
pro_epilogue_adjust_stack (stack_pointer_rtx, sa,
- const0_rtx, style);
+ const0_rtx, style, false);
}
else
{
@@ -8637,7 +8843,18 @@ ix86_expand_epilogue (int style)
+ frame.nregs * UNITS_PER_WORD
+ frame.nsseregs * 16
+ frame.padding0));
- emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx, tmp));
+ tmp = emit_insn (gen_rtx_SET (VOIDmode, stack_pointer_rtx, tmp));
+ ix86_add_queued_cfa_restore_notes (tmp);
+
+ gcc_assert (ix86_cfa_state->reg == stack_pointer_rtx);
+ if (ix86_cfa_state->offset != UNITS_PER_WORD)
+ {
+ ix86_cfa_state->offset = UNITS_PER_WORD;
+ add_reg_note (tmp, REG_CFA_DEF_CFA,
+ plus_constant (stack_pointer_rtx,
+ UNITS_PER_WORD));
+ RTX_FRAME_RELATED_P (tmp) = 1;
+ }
}
}
else if (!frame_pointer_needed)
@@ -8646,18 +8863,18 @@ ix86_expand_epilogue (int style)
+ frame.nregs * UNITS_PER_WORD
+ frame.nsseregs * 16
+ frame.padding0),
- style);
+ style, !using_drap);
/* If not an i386, mov & pop is faster than "leave". */
else if (TARGET_USE_LEAVE || optimize_function_for_size_p (cfun)
|| !cfun->machine->use_fast_prologue_epilogue)
- emit_insn ((*ix86_gen_leave) ());
+ ix86_emit_leave (red_offset);
else
{
pro_epilogue_adjust_stack (stack_pointer_rtx,
hard_frame_pointer_rtx,
- const0_rtx, style);
+ const0_rtx, style, !using_drap);
- emit_insn ((*ix86_gen_pop1) (hard_frame_pointer_rtx));
+ ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx, red_offset);
}
}
else
@@ -8675,32 +8892,36 @@ ix86_expand_epilogue (int style)
gcc_assert (!stack_realign_fp);
pro_epilogue_adjust_stack (stack_pointer_rtx,
hard_frame_pointer_rtx,
- GEN_INT (offset), style);
+ GEN_INT (offset), style, false);
ix86_emit_restore_sse_regs_using_mov (stack_pointer_rtx,
- frame.to_allocate, style == 2);
+ frame.to_allocate, red_offset,
+ style == 2);
pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
- GEN_INT (frame.nsseregs * 16), style);
+ GEN_INT (frame.nsseregs * 16),
+ style, false);
}
else if (frame.to_allocate || frame.nsseregs)
{
ix86_emit_restore_sse_regs_using_mov (stack_pointer_rtx,
- frame.to_allocate,
+ frame.to_allocate, red_offset,
style == 2);
pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
GEN_INT (frame.to_allocate
+ frame.nsseregs * 16
- + frame.padding0), style);
+ + frame.padding0), style,
+ !using_drap && !frame_pointer_needed);
}
- for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (!SSE_REGNO_P (regno) && ix86_save_reg (regno, false))
- emit_insn ((*ix86_gen_pop1) (gen_rtx_REG (Pmode, regno)));
+ ix86_emit_restore_regs_using_pop (red_offset + frame.nsseregs * 16
+ + frame.padding0);
+ red_offset -= offset;
+
if (frame_pointer_needed)
{
/* Leave results in shorter dependency chains on CPUs that are
able to grok it fast. */
if (TARGET_USE_LEAVE)
- emit_insn ((*ix86_gen_leave) ());
+ ix86_emit_leave (red_offset);
else
{
/* For stack realigned really happens, recover stack
@@ -8709,47 +8930,71 @@ ix86_expand_epilogue (int style)
if (stack_realign_fp)
pro_epilogue_adjust_stack (stack_pointer_rtx,
hard_frame_pointer_rtx,
- const0_rtx, style);
- emit_insn ((*ix86_gen_pop1) (hard_frame_pointer_rtx));
+ const0_rtx, style, !using_drap);
+ ix86_emit_restore_reg_using_pop (hard_frame_pointer_rtx,
+ red_offset);
}
}
}
- if (crtl->drap_reg && crtl->stack_realign_needed)
+ if (using_drap)
{
int param_ptr_offset = (call_used_regs[REGNO (crtl->drap_reg)]
? 0 : UNITS_PER_WORD);
+ rtx insn;
+
gcc_assert (stack_realign_drap);
- emit_insn ((*ix86_gen_add3) (stack_pointer_rtx,
- crtl->drap_reg,
- GEN_INT (-(UNITS_PER_WORD
- + param_ptr_offset))));
- if (!call_used_regs[REGNO (crtl->drap_reg)])
- emit_insn ((*ix86_gen_pop1) (crtl->drap_reg));
-
+
+ insn = emit_insn ((*ix86_gen_add3) (stack_pointer_rtx,
+ crtl->drap_reg,
+ GEN_INT (-(UNITS_PER_WORD
+ + param_ptr_offset))));
+
+ ix86_cfa_state->reg = stack_pointer_rtx;
+ ix86_cfa_state->offset = UNITS_PER_WORD + param_ptr_offset;
+
+ add_reg_note (insn, REG_CFA_DEF_CFA,
+ gen_rtx_PLUS (Pmode, ix86_cfa_state->reg,
+ GEN_INT (ix86_cfa_state->offset)));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ if (param_ptr_offset)
+ ix86_emit_restore_reg_using_pop (crtl->drap_reg, -UNITS_PER_WORD);
}
/* Sibcall epilogues don't want a return instruction. */
if (style == 0)
- return;
+ {
+ *ix86_cfa_state = cfa_state_save;
+ return;
+ }
if (crtl->args.pops_args && crtl->args.size)
{
rtx popc = GEN_INT (crtl->args.pops_args);
- /* i386 can only pop 64K bytes. If asked to pop more, pop
- return address, do explicit add, and jump indirectly to the
- caller. */
+ /* i386 can only pop 64K bytes. If asked to pop more, pop return
+ address, do explicit add, and jump indirectly to the caller. */
if (crtl->args.pops_args >= 65536)
{
rtx ecx = gen_rtx_REG (SImode, CX_REG);
+ rtx insn;
/* There is no "pascal" calling convention in any 64bit ABI. */
gcc_assert (!TARGET_64BIT);
- emit_insn (gen_popsi1 (ecx));
- emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, popc));
+ insn = emit_insn (gen_popsi1 (ecx));
+ ix86_cfa_state->offset -= UNITS_PER_WORD;
+
+ add_reg_note (insn, REG_CFA_ADJUST_CFA,
+ copy_rtx (XVECEXP (PATTERN (insn), 0, 1)));
+ add_reg_note (insn, REG_CFA_REGISTER,
+ gen_rtx_SET (VOIDmode, ecx, pc_rtx));
+ RTX_FRAME_RELATED_P (insn) = 1;
+
+ pro_epilogue_adjust_stack (stack_pointer_rtx, stack_pointer_rtx,
+ popc, -1, true);
emit_jump_insn (gen_return_indirect_internal (ecx));
}
else
@@ -8757,6 +9002,10 @@ ix86_expand_epilogue (int style)
}
else
emit_jump_insn (gen_return_internal ());
+
+ /* Restore the state back to the state from the prologue,
+ so that it's correct for the next epilogue. */
+ *ix86_cfa_state = cfa_state_save;
}
/* Reset from the function's potential modifications. */
@@ -8900,6 +9149,10 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
base_reg = base && GET_CODE (base) == SUBREG ? SUBREG_REG (base) : base;
index_reg = index && GET_CODE (index) == SUBREG ? SUBREG_REG (index) : index;
+ /* Avoid useless 0 displacement. */
+ if (disp == const0_rtx && (base || index))
+ disp = NULL_RTX;
+
/* Allow arg pointer and stack pointer as index if there is not scaling. */
if (base_reg && index_reg && scale == 1
&& (index_reg == arg_pointer_rtx
@@ -8911,10 +9164,16 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
tmp = base_reg, base_reg = index_reg, index_reg = tmp;
}
- /* Special case: %ebp cannot be encoded as a base without a displacement. */
- if ((base_reg == hard_frame_pointer_rtx
- || base_reg == frame_pointer_rtx
- || base_reg == arg_pointer_rtx) && !disp)
+ /* Special case: %ebp cannot be encoded as a base without a displacement.
+ Similarly %r13. */
+ if (!disp
+ && base_reg
+ && (base_reg == hard_frame_pointer_rtx
+ || base_reg == frame_pointer_rtx
+ || base_reg == arg_pointer_rtx
+ || (REG_P (base_reg)
+ && (REGNO (base_reg) == HARD_FRAME_POINTER_REGNUM
+ || REGNO (base_reg) == R13_REG))))
disp = const0_rtx;
/* Special case: on K6, [%esi] makes the instruction vector decoded.
@@ -8928,7 +9187,7 @@ ix86_decompose_address (rtx addr, struct ix86_address *out)
disp = const0_rtx;
/* Special case: encode reg+reg instead of reg*2. */
- if (!base && index && scale && scale == 2)
+ if (!base && index && scale == 2)
base = index, base_reg = index_reg, scale = 1;
/* Special case: scaling cannot be encoded without base or displacement. */
@@ -19351,9 +19610,33 @@ memory_address_length (rtx addr)
len = 1;
}
- /* Direct Addressing. */
+ /* Direct Addressing. In 64-bit mode mod 00 r/m 5
+ is not disp32, but disp32(%rip), so for disp32
+ SIB byte is needed, unless print_operand_address
+ optimizes it into disp32(%rip) or (%rip) is implied
+ by UNSPEC. */
else if (disp && !base && !index)
- len = 4;
+ {
+ len = 4;
+ if (TARGET_64BIT)
+ {
+ rtx symbol = disp;
+
+ if (GET_CODE (disp) == CONST)
+ symbol = XEXP (disp, 0);
+ if (GET_CODE (symbol) == PLUS
+ && CONST_INT_P (XEXP (symbol, 1)))
+ symbol = XEXP (symbol, 0);
+
+ if (GET_CODE (symbol) != LABEL_REF
+ && (GET_CODE (symbol) != SYMBOL_REF
+ || SYMBOL_REF_TLS_MODEL (symbol) != 0)
+ && (GET_CODE (symbol) != UNSPEC
+ || (XINT (symbol, 1) != UNSPEC_GOTPCREL
+ && XINT (symbol, 1) != UNSPEC_GOTNTPOFF)))
+ len += 1;
+ }
+ }
else
{
@@ -19368,7 +19651,7 @@ memory_address_length (rtx addr)
/* ebp always wants a displacement. Similarly r13. */
else if (REG_P (base)
&& (REGNO (base) == BP_REG || REGNO (base) == R13_REG))
- len = 1;
+ len = 1;
/* An index requires the two-byte modrm form.... */
if (index
@@ -19380,6 +19663,16 @@ memory_address_length (rtx addr)
len += 1;
}
+ switch (parts.seg)
+ {
+ case SEG_FS:
+ case SEG_GS:
+ len += 1;
+ break;
+ default:
+ break;
+ }
+
return len;
}
@@ -19394,30 +19687,50 @@ ix86_attr_length_immediate_default (rtx insn, int shortform)
for (i = recog_data.n_operands - 1; i >= 0; --i)
if (CONSTANT_P (recog_data.operand[i]))
{
+ enum attr_mode mode = get_attr_mode (insn);
+
gcc_assert (!len);
- if (shortform && satisfies_constraint_K (recog_data.operand[i]))
- len = 1;
- else
+ if (shortform && CONST_INT_P (recog_data.operand[i]))
{
- switch (get_attr_mode (insn))
+ HOST_WIDE_INT ival = INTVAL (recog_data.operand[i]);
+ switch (mode)
{
- case MODE_QI:
- len+=1;
- break;
- case MODE_HI:
- len+=2;
- break;
- case MODE_SI:
- len+=4;
- break;
- /* Immediates for DImode instructions are encoded as 32bit sign extended values. */
- case MODE_DI:
- len+=4;
- break;
- default:
- fatal_insn ("unknown insn mode", insn);
+ case MODE_QI:
+ len = 1;
+ continue;
+ case MODE_HI:
+ ival = trunc_int_for_mode (ival, HImode);
+ break;
+ case MODE_SI:
+ ival = trunc_int_for_mode (ival, SImode);
+ break;
+ default:
+ break;
+ }
+ if (IN_RANGE (ival, -128, 127))
+ {
+ len = 1;
+ continue;
}
}
+ switch (mode)
+ {
+ case MODE_QI:
+ len = 1;
+ break;
+ case MODE_HI:
+ len = 2;
+ break;
+ case MODE_SI:
+ len = 4;
+ break;
+ /* Immediates for DImode instructions are encoded as 32bit sign extended values. */
+ case MODE_DI:
+ len = 4;
+ break;
+ default:
+ fatal_insn ("unknown insn mode", insn);
+ }
}
return len;
}
@@ -19452,8 +19765,22 @@ ix86_attr_length_address_default (rtx insn)
for (i = recog_data.n_operands - 1; i >= 0; --i)
if (MEM_P (recog_data.operand[i]))
{
+ constrain_operands_cached (reload_completed);
+ if (which_alternative != -1)
+ {
+ const char *constraints = recog_data.constraints[i];
+ int alt = which_alternative;
+
+ while (*constraints == '=' || *constraints == '+')
+ constraints++;
+ while (alt-- > 0)
+ while (*constraints++ != ',')
+ ;
+ /* Skip ignored operands. */
+ if (*constraints == 'X')
+ continue;
+ }
return memory_address_length (XEXP (recog_data.operand[i], 0));
- break;
}
return 0;
}
@@ -19482,7 +19809,8 @@ ix86_attr_length_vex_default (rtx insn, int has_0f_opcode,
if (REG_P (recog_data.operand[i]))
{
/* REX.W bit uses 3 byte VEX prefix. */
- if (GET_MODE (recog_data.operand[i]) == DImode)
+ if (GET_MODE (recog_data.operand[i]) == DImode
+ && GENERAL_REG_P (recog_data.operand[i]))
return 3 + 1;
}
else
@@ -30282,8 +30610,6 @@ ix86_enum_va_list (int idx, const char **pname, tree *ptree)
#define TARGET_UPDATE_STACK_BOUNDARY ix86_update_stack_boundary
#undef TARGET_GET_DRAP_RTX
#define TARGET_GET_DRAP_RTX ix86_get_drap_rtx
-#undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
-#define TARGET_DWARF_HANDLE_FRAME_UNSPEC ix86_dwarf_handle_frame_unspec
#undef TARGET_STRICT_ARGUMENT_NAMING
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 1d7acf66efb..72dcf3265f7 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -2393,6 +2393,15 @@ enum ix86_stack_slot
#define FASTCALL_PREFIX '@'
+/* Machine specific CFA tracking during prologue/epilogue generation. */
+
+#ifndef USED_FOR_TARGET
+struct GTY(()) machine_cfa_state
+{
+ rtx reg;
+ HOST_WIDE_INT offset;
+};
+
struct GTY(()) machine_function {
struct stack_local_entry *stack_locals;
const char *some_ld_name;
@@ -2419,8 +2428,10 @@ struct GTY(()) machine_function {
int tls_descriptor_call_expanded_p;
/* This value is used for amd64 targets and specifies the current abi
to be used. MS_ABI means ms abi. Otherwise SYSV_ABI means sysv abi. */
- enum calling_abi call_abi;
+ enum calling_abi call_abi;
+ struct machine_cfa_state cfa;
};
+#endif
#define ix86_stack_locals (cfun->machine->stack_locals)
#define ix86_varargs_gpr_size (cfun->machine->varargs_gpr_size)
@@ -2436,6 +2447,7 @@ struct GTY(()) machine_function {
REG_SP is live. */
#define ix86_current_function_calls_tls_descriptor \
(ix86_tls_descriptor_calls_expanded_in_cfun && df_regs_ever_live_p (SP_REG))
+#define ix86_cfa_state (&cfun->machine->cfa)
/* Control behavior of x86_file_start. */
#define X86_FILE_START_VERSION_DIRECTIVE false
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index dbe781deb84..20413966e84 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -101,7 +101,6 @@
(UNSPEC_ADD_CARRY 34)
(UNSPEC_FLDCW 35)
(UNSPEC_REP 36)
- (UNSPEC_EH_RETURN 37)
(UNSPEC_LD_MPIC 38) ; load_macho_picbase
(UNSPEC_TRUNC_NOOP 39)
@@ -416,16 +415,23 @@
;; Set when length prefix is used.
(define_attr "prefix_data16" ""
- (if_then_else (ior (eq_attr "mode" "HI")
- (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF,TI")))
- (const_int 1)
- (const_int 0)))
+ (cond [(eq_attr "type" "ssemuladd,sse4arg,sseiadd1,ssecvt1")
+ (const_int 0)
+ (eq_attr "mode" "HI")
+ (const_int 1)
+ (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF,TI"))
+ (const_int 1)
+ ]
+ (const_int 0)))
;; Set when string REP prefix is used.
(define_attr "prefix_rep" ""
- (if_then_else (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
- (const_int 1)
- (const_int 0)))
+ (cond [(eq_attr "type" "ssemuladd,sse4arg,sseiadd1,ssecvt1")
+ (const_int 0)
+ (and (eq_attr "unit" "sse") (eq_attr "mode" "SF,DF"))
+ (const_int 1)
+ ]
+ (const_int 0)))
;; Set when 0f opcode prefix is used.
(define_attr "prefix_0f" ""
@@ -440,7 +446,8 @@
(cond [(ne (symbol_ref "!TARGET_64BIT") (const_int 0))
(const_int 0)
(and (eq_attr "mode" "DI")
- (eq_attr "type" "!push,pop,call,callv,leave,ibr"))
+ (and (eq_attr "type" "!push,pop,call,callv,leave,ibr")
+ (eq_attr "unit" "!mmx")))
(const_int 1)
(and (eq_attr "mode" "QI")
(ne (symbol_ref "x86_extended_QIreg_mentioned_p (insn)")
@@ -455,8 +462,17 @@
]
(const_int 0)))
-;; There are also additional prefixes in SSSE3.
-(define_attr "prefix_extra" "" (const_int 0))
+;; There are also additional prefixes in 3DNOW, SSSE3 or SSE5.
+;; ssemuladd,sse4arg default to 0f24/0f25 and DREX byte,
+;; sseiadd1,ssecvt1 to 0f7a with no DREX byte.
+;; 3DNOW has 0f0f prefix, SSSE3 and SSE4_{1,2} 0f38/0f3a.
+(define_attr "prefix_extra" ""
+ (cond [(eq_attr "type" "ssemuladd,sse4arg")
+ (const_int 2)
+ (eq_attr "type" "sseiadd1,ssecvt1")
+ (const_int 1)
+ ]
+ (const_int 0)))
;; Prefix used: original, VEX or maybe VEX.
(define_attr "prefix" "orig,vex,maybe_vex"
@@ -464,15 +480,16 @@
(const_string "vex")
(const_string "orig")))
-;; There is a 8bit immediate for VEX.
-(define_attr "prefix_vex_imm8" "" (const_int 0))
-
;; VEX W bit is used.
(define_attr "prefix_vex_w" "" (const_int 0))
;; The length of VEX prefix
+;; Only instructions with 0f prefix can have 2 byte VEX prefix,
+;; 0f38/0f3a prefixes can't. In i386.md 0f3[8a] is
+;; still prefix_0f 1, with prefix_extra 1.
(define_attr "length_vex" ""
- (if_then_else (eq_attr "prefix_0f" "1")
+ (if_then_else (and (eq_attr "prefix_0f" "1")
+ (eq_attr "prefix_extra" "0"))
(if_then_else (eq_attr "prefix_vex_w" "1")
(symbol_ref "ix86_attr_length_vex_default (insn, 1, 1)")
(symbol_ref "ix86_attr_length_vex_default (insn, 1, 0)"))
@@ -487,8 +504,9 @@
(eq_attr "unit" "i387")
(const_int 0)
(and (eq_attr "type" "incdec")
- (ior (match_operand:SI 1 "register_operand" "")
- (match_operand:HI 1 "register_operand" "")))
+ (and (eq (symbol_ref "TARGET_64BIT") (const_int 0))
+ (ior (match_operand:SI 1 "register_operand" "")
+ (match_operand:HI 1 "register_operand" ""))))
(const_int 0)
(and (eq_attr "type" "push")
(not (match_operand 1 "memory_operand" "")))
@@ -534,7 +552,7 @@
(and (eq_attr "prefix" "maybe_vex")
(ne (symbol_ref "TARGET_AVX") (const_int 0))))
(plus (attr "length_vex")
- (plus (attr "prefix_vex_imm8")
+ (plus (attr "length_immediate")
(plus (attr "modrm")
(attr "length_address"))))]
(plus (plus (attr "modrm")
@@ -1155,6 +1173,7 @@
"!TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
"cmp{b}\t{%1, %h0|%h0, %1}"
[(set_attr "type" "icmp")
+ (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_insn "cmpqi_ext_3_insn_rex64"
@@ -1169,6 +1188,7 @@
"TARGET_64BIT && ix86_match_ccmode (insn, CCmode)"
"cmp{b}\t{%1, %h0|%h0, %1}"
[(set_attr "type" "icmp")
+ (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_insn "*cmpqi_ext_4"
@@ -1516,7 +1536,7 @@
(unspec:HI [(reg:CCFP FPSR_REG)] UNSPEC_FNSTSW))]
"TARGET_80387"
"fnstsw\t%0"
- [(set_attr "length" "2")
+ [(set (attr "length") (symbol_ref "ix86_attr_length_address_default (insn) + 2"))
(set_attr "mode" "SI")
(set_attr "unit" "i387")])
@@ -1556,6 +1576,17 @@
(if_then_else (match_operand:SF 1 "" "")
(const_string "SF")
(const_string "DF")))
+ (set (attr "prefix_rep")
+ (if_then_else (eq_attr "type" "ssecomi")
+ (const_string "0")
+ (const_string "*")))
+ (set (attr "prefix_data16")
+ (cond [(eq_attr "type" "fcmp")
+ (const_string "*")
+ (eq_attr "mode" "DF")
+ (const_string "1")
+ ]
+ (const_string "0")))
(set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "direct")])
@@ -1573,6 +1604,11 @@
(if_then_else (match_operand:SF 1 "" "")
(const_string "SF")
(const_string "DF")))
+ (set_attr "prefix_rep" "0")
+ (set (attr "prefix_data16")
+ (if_then_else (eq_attr "mode" "DF")
+ (const_string "1")
+ (const_string "0")))
(set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "direct")])
@@ -1610,6 +1646,17 @@
(if_then_else (match_operand:SF 1 "" "")
(const_string "SF")
(const_string "DF")))
+ (set (attr "prefix_rep")
+ (if_then_else (eq_attr "type" "ssecomi")
+ (const_string "0")
+ (const_string "*")))
+ (set (attr "prefix_data16")
+ (cond [(eq_attr "type" "fcmp")
+ (const_string "*")
+ (eq_attr "mode" "DF")
+ (const_string "1")
+ ]
+ (const_string "0")))
(set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "direct")])
@@ -1627,6 +1674,11 @@
(if_then_else (match_operand:SF 1 "" "")
(const_string "SF")
(const_string "DF")))
+ (set_attr "prefix_rep" "0")
+ (set (attr "prefix_data16")
+ (if_then_else (eq_attr "mode" "DF")
+ (const_string "1")
+ (const_string "0")))
(set_attr "athlon_decode" "vector")
(set_attr "amdfam10_decode" "direct")])
@@ -1802,6 +1854,10 @@
(if_then_else (eq_attr "alternative" "0,1,2,3,4,5")
(const_string "orig")
(const_string "maybe_vex")))
+ (set (attr "prefix_data16")
+ (if_then_else (and (eq_attr "type" "ssemov") (eq_attr "mode" "SI"))
+ (const_string "1")
+ (const_string "*")))
(set (attr "mode")
(cond [(eq_attr "alternative" "2,3")
(const_string "DI")
@@ -2651,6 +2707,8 @@
(and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
(const_string "8")
(const_string "*")))
+ (set_attr "prefix_rex" "*,*,*,*,*,*,*,1,*,1,*,*,*,*,*,*,*,*,*")
+ (set_attr "prefix_data16" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,1,*,*,*")
(set (attr "prefix")
(if_then_else (eq_attr "alternative" "11,12,13,14,15,16")
(const_string "maybe_vex")
@@ -3235,6 +3293,10 @@
(if_then_else (eq_attr "alternative" "0,1,2,3,4")
(const_string "orig")
(const_string "maybe_vex")))
+ (set (attr "prefix_data16")
+ (if_then_else (eq_attr "mode" "V1DF")
+ (const_string "1")
+ (const_string "*")))
(set (attr "mode")
(cond [(eq_attr "alternative" "0,1,2")
(const_string "DF")
@@ -3369,6 +3431,10 @@
(if_then_else (eq_attr "alternative" "0,1,2,3,4")
(const_string "orig")
(const_string "maybe_vex")))
+ (set (attr "prefix_data16")
+ (if_then_else (eq_attr "mode" "V1DF")
+ (const_string "1")
+ (const_string "*")))
(set (attr "mode")
(cond [(eq_attr "alternative" "0,1,2")
(const_string "DF")
@@ -3489,6 +3555,10 @@
}
}
[(set_attr "type" "fmov,fmov,fmov,multi,multi,sselog1,ssemov,ssemov,ssemov")
+ (set (attr "prefix_data16")
+ (if_then_else (eq_attr "mode" "V1DF")
+ (const_string "1")
+ (const_string "*")))
(set (attr "mode")
(cond [(eq_attr "alternative" "0,1,2")
(const_string "DF")
@@ -4194,7 +4264,7 @@
"TARGET_64BIT"
"@
{cltq|cdqe}
- movs{lq|x}\t{%1,%0|%0, %1}"
+ movs{lq|x}\t{%1, %0|%0, %1}"
[(set_attr "type" "imovx")
(set_attr "mode" "DI")
(set_attr "prefix_0f" "0")
@@ -4204,7 +4274,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
"TARGET_64BIT"
- "movs{wq|x}\t{%1,%0|%0, %1}"
+ "movs{wq|x}\t{%1, %0|%0, %1}"
[(set_attr "type" "imovx")
(set_attr "mode" "DI")])
@@ -4212,7 +4282,7 @@
[(set (match_operand:DI 0 "register_operand" "=r")
(sign_extend:DI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
"TARGET_64BIT"
- "movs{bq|x}\t{%1,%0|%0, %1}"
+ "movs{bq|x}\t{%1, %0|%0, %1}"
[(set_attr "type" "imovx")
(set_attr "mode" "DI")])
@@ -4300,7 +4370,7 @@
case 0:
return "{cwtl|cwde}";
default:
- return "movs{wl|x}\t{%1,%0|%0, %1}";
+ return "movs{wl|x}\t{%1, %0|%0, %1}";
}
}
[(set_attr "type" "imovx")
@@ -4327,7 +4397,7 @@
case 0:
return "{cwtl|cwde}";
default:
- return "movs{wl|x}\t{%1,%k0|%k0, %1}";
+ return "movs{wl|x}\t{%1, %k0|%k0, %1}";
}
}
[(set_attr "type" "imovx")
@@ -4353,7 +4423,7 @@
case 0:
return "{cbtw|cbw}";
default:
- return "movs{bw|x}\t{%1,%0|%0, %1}";
+ return "movs{bw|x}\t{%1, %0|%0, %1}";
}
}
[(set_attr "type" "imovx")
@@ -4373,7 +4443,7 @@
[(set (match_operand:SI 0 "register_operand" "=r")
(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
""
- "movs{bl|x}\t{%1,%0|%0, %1}"
+ "movs{bl|x}\t{%1, %0|%0, %1}"
[(set_attr "type" "imovx")
(set_attr "mode" "SI")])
@@ -4382,7 +4452,7 @@
(zero_extend:DI
(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))))]
"TARGET_64BIT"
- "movs{bl|x}\t{%1,%k0|%k0, %1}"
+ "movs{bl|x}\t{%1, %k0|%k0, %1}"
[(set_attr "type" "imovx")
(set_attr "mode" "SI")])
@@ -4994,6 +5064,7 @@
"%vcvtts<ssemodefsuffix>2si{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "sseicvt")
(set_attr "prefix" "maybe_vex")
+ (set_attr "prefix_rex" "1")
(set_attr "mode" "<MODE>")
(set_attr "athlon_decode" "double,vector")
(set_attr "amdfam10_decode" "double,double")])
@@ -5268,7 +5339,7 @@
(unspec:HI [(reg:HI FPCR_REG)] UNSPEC_FSTCW))]
"TARGET_80387"
"fnstcw\t%0"
- [(set_attr "length" "2")
+ [(set (attr "length") (symbol_ref "ix86_attr_length_address_default (insn) + 2"))
(set_attr "mode" "HI")
(set_attr "unit" "i387")])
@@ -5277,7 +5348,7 @@
(unspec:HI [(match_operand:HI 0 "memory_operand" "m")] UNSPEC_FLDCW))]
"TARGET_80387"
"fldcw\t%0"
- [(set_attr "length" "2")
+ [(set (attr "length") (symbol_ref "ix86_attr_length_address_default (insn) + 2"))
(set_attr "mode" "HI")
(set_attr "unit" "i387")
(set_attr "athlon_decode" "vector")
@@ -6650,7 +6721,7 @@
(const_string "alu")))
(set (attr "length_immediate")
(if_then_else
- (and (eq_attr "type" "alu") (match_operand 2 "constm128_operand" ""))
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
(const_string "1")
(const_string "*")))
(set_attr "mode" "DI")])
@@ -7121,7 +7192,7 @@
(const_string "alu")))
(set (attr "length_immediate")
(if_then_else
- (and (eq_attr "type" "alu") (match_operand 2 "constm128_operand" ""))
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
(const_string "1")
(const_string "*")))
(set_attr "mode" "SI")])
@@ -7409,10 +7480,10 @@
(const_string "alu")))
(set (attr "length_immediate")
(if_then_else
- (and (eq_attr "type" "alu") (match_operand 2 "constm128_operand" ""))
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
(const_string "1")
(const_string "*")))
- (set_attr "mode" "SI")])
+ (set_attr "mode" "HI")])
(define_insn "*addhi_5"
@@ -7808,6 +7879,7 @@
(if_then_else (match_operand:QI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_insn "*addqi_ext_1_rex64"
@@ -7844,6 +7916,7 @@
(if_then_else (match_operand:QI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_insn "*addqi_ext_2"
@@ -9308,6 +9381,7 @@
[(set_attr "type" "test")
(set_attr "mode" "QI")
(set_attr "length_immediate" "1")
+ (set_attr "modrm" "1")
(set_attr "pent_pair" "np")])
(define_insn "*testqi_ext_1"
@@ -9534,9 +9608,9 @@
operands[1] = gen_lowpart (mode, operands[1]);
if (mode == QImode)
- return "movz{bq|x}\t{%1,%0|%0, %1}";
+ return "movz{bl|x}\t{%1, %k0|%k0, %1}";
else
- return "movz{wq|x}\t{%1,%0|%0, %1}";
+ return "movz{wl|x}\t{%1, %k0|%k0, %1}";
}
default:
@@ -9549,7 +9623,14 @@
}
[(set_attr "type" "alu,alu,alu,imovx")
(set_attr "length_immediate" "*,*,*,0")
- (set_attr "mode" "SI,DI,DI,DI")])
+ (set (attr "prefix_rex")
+ (if_then_else
+ (and (eq_attr "type" "imovx")
+ (and (ne (symbol_ref "INTVAL (operands[2]) == 0xff") (const_int 0))
+ (match_operand 1 "ext_QIreg_nomode_operand" "")))
+ (const_string "1")
+ (const_string "*")))
+ (set_attr "mode" "SI,DI,DI,SI")])
(define_insn "*anddi_2"
[(set (reg FLAGS_REG)
@@ -9598,9 +9679,9 @@
operands[1] = gen_lowpart (mode, operands[1]);
if (mode == QImode)
- return "movz{bl|x}\t{%1,%0|%0, %1}";
+ return "movz{bl|x}\t{%1, %0|%0, %1}";
else
- return "movz{wl|x}\t{%1,%0|%0, %1}";
+ return "movz{wl|x}\t{%1, %0|%0, %1}";
}
default:
@@ -9609,6 +9690,13 @@
}
}
[(set_attr "type" "alu,alu,imovx")
+ (set (attr "prefix_rex")
+ (if_then_else
+ (and (eq_attr "type" "imovx")
+ (and (ne (symbol_ref "INTVAL (operands[2]) == 0xff") (const_int 0))
+ (match_operand 1 "ext_QIreg_nomode_operand" "")))
+ (const_string "1")
+ (const_string "*")))
(set_attr "length_immediate" "*,*,0")
(set_attr "mode" "SI")])
@@ -9717,6 +9805,12 @@
}
[(set_attr "type" "alu,alu,imovx")
(set_attr "length_immediate" "*,*,0")
+ (set (attr "prefix_rex")
+ (if_then_else
+ (and (eq_attr "type" "imovx")
+ (match_operand 1 "ext_QIreg_nomode_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "HI,HI,SI")])
(define_insn "*andhi_2"
@@ -9836,6 +9930,7 @@
"and{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
(set_attr "length_immediate" "1")
+ (set_attr "modrm" "1")
(set_attr "mode" "QI")])
;; Generated by peephole translating test to and. This shows up
@@ -9864,6 +9959,7 @@
"and{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
(set_attr "length_immediate" "1")
+ (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_insn "*andqi_ext_1"
@@ -10238,6 +10334,7 @@
"or{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
(set_attr "length_immediate" "1")
+ (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_insn "*iorqi_ext_1"
@@ -10568,6 +10665,7 @@
"xor{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
(set_attr "length_immediate" "1")
+ (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_insn "*xorqi_ext_1"
@@ -10686,6 +10784,7 @@
"!TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
"xor{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
+ (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_insn "*xorqi_cc_ext_1_rex64"
@@ -10707,6 +10806,7 @@
"TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)"
"xor{b}\t{%2, %h0|%h0, %2}"
[(set_attr "type" "alu")
+ (set_attr "modrm" "1")
(set_attr "mode" "QI")])
(define_expand "xorqi_cc_ext_1"
@@ -11509,6 +11609,7 @@
}
[(set_attr "type" "sseishft")
(set_attr "prefix" "vex")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "sse2_ashlti3"
@@ -11522,6 +11623,7 @@
}
[(set_attr "type" "sseishft")
(set_attr "prefix_data16" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "*ashlti3_1"
@@ -13361,6 +13463,7 @@
}
[(set_attr "type" "sseishft")
(set_attr "prefix" "vex")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "sse2_lshrti3"
@@ -13374,6 +13477,7 @@
}
[(set_attr "type" "sseishft")
(set_attr "prefix_data16" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "*lshrti3_1"
@@ -14446,7 +14550,8 @@
"TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
"bts{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
- (set_attr "prefix_0f" "1")])
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")])
(define_insn "*btrq"
[(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
@@ -14457,7 +14562,8 @@
"TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
"btr{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
- (set_attr "prefix_0f" "1")])
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")])
(define_insn "*btcq"
[(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
@@ -14468,7 +14574,8 @@
"TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
"btc{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
- (set_attr "prefix_0f" "1")])
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")])
;; Allow Nocona to avoid these instructions if a register is available.
@@ -14580,7 +14687,8 @@
"TARGET_64BIT && (TARGET_USE_BT || optimize_function_for_size_p (cfun))"
"bt{q}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
- (set_attr "prefix_0f" "1")])
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")])
(define_insn "*btsi"
[(set (reg:CCC FLAGS_REG)
@@ -14593,7 +14701,8 @@
"TARGET_USE_BT || optimize_function_for_size_p (cfun)"
"bt{l}\t{%1, %0|%0, %1}"
[(set_attr "type" "alu1")
- (set_attr "prefix_0f" "1")])
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "SI")])
;; Store-flag instructions.
@@ -14706,6 +14815,7 @@
"vcmp%D1s<ssemodefsuffix>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "ssecmp")
(set_attr "prefix" "vex")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<MODE>")])
(define_insn "*sse_setcc<mode>"
@@ -14716,6 +14826,7 @@
"SSE_FLOAT_MODE_P (<MODE>mode) && !TARGET_SSE5"
"cmp%D1s<ssemodefsuffix>\t{%3, %0|%0, %3}"
[(set_attr "type" "ssecmp")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<MODE>")])
(define_insn "*sse5_setcc<mode>"
@@ -14726,6 +14837,7 @@
"TARGET_SSE5"
"com%Y1s<ssemodefsuffix>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "sse4arg")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<MODE>")])
@@ -15821,7 +15933,8 @@
"TARGET_64BIT"
"lea{q}\t{_GLOBAL_OFFSET_TABLE_(%%rip), %0|%0, _GLOBAL_OFFSET_TABLE_[rip]}"
[(set_attr "type" "lea")
- (set_attr "length" "6")])
+ (set_attr "length_address" "4")
+ (set_attr "mode" "DI")])
(define_insn "set_rip_rex64"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -15829,7 +15942,8 @@
"TARGET_64BIT"
"lea{q}\t{%l1(%%rip), %0|%0, %l1[rip]}"
[(set_attr "type" "lea")
- (set_attr "length" "6")])
+ (set_attr "length_address" "4")
+ (set_attr "mode" "DI")])
(define_insn "set_got_offset_rex64"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -15839,7 +15953,9 @@
"TARGET_64BIT"
"movabs{q}\t{$_GLOBAL_OFFSET_TABLE_-%l1, %0|%0, OFFSET FLAT:_GLOBAL_OFFSET_TABLE_-%l1}"
[(set_attr "type" "imov")
- (set_attr "length" "11")])
+ (set_attr "length_immediate" "0")
+ (set_attr "length_address" "8")
+ (set_attr "mode" "DI")])
(define_expand "epilogue"
[(const_int 0)]
@@ -15865,21 +15981,16 @@
tmp = gen_rtx_MEM (Pmode, tmp);
emit_move_insn (tmp, ra);
- if (Pmode == SImode)
- emit_jump_insn (gen_eh_return_si (sa));
- else
- emit_jump_insn (gen_eh_return_di (sa));
+ emit_jump_insn (gen_eh_return_internal ());
emit_barrier ();
DONE;
})
-(define_insn_and_split "eh_return_<mode>"
- [(set (pc)
- (unspec [(match_operand:P 0 "register_operand" "c")]
- UNSPEC_EH_RETURN))]
+(define_insn_and_split "eh_return_internal"
+ [(eh_return)]
""
"#"
- "reload_completed"
+ "epilogue_completed"
[(const_int 0)]
"ix86_expand_epilogue (2); DONE;")
@@ -15962,7 +16073,9 @@
(ctz:SI (match_dup 1)))]
""
"bsf{l}\t{%1, %0|%0, %1}"
- [(set_attr "prefix_0f" "1")])
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "SI")])
(define_expand "ffsdi2"
[(set (match_dup 2) (const_int -1))
@@ -15988,7 +16101,9 @@
(ctz:DI (match_dup 1)))]
"TARGET_64BIT"
"bsf{q}\t{%1, %0|%0, %1}"
- [(set_attr "prefix_0f" "1")])
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")])
(define_insn "ctzsi2"
[(set (match_operand:SI 0 "register_operand" "=r")
@@ -15996,7 +16111,9 @@
(clobber (reg:CC FLAGS_REG))]
""
"bsf{l}\t{%1, %0|%0, %1}"
- [(set_attr "prefix_0f" "1")])
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "SI")])
(define_insn "ctzdi2"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -16004,7 +16121,9 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"bsf{q}\t{%1, %0|%0, %1}"
- [(set_attr "prefix_0f" "1")])
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")
+ (set_attr "mode" "DI")])
(define_expand "clzsi2"
[(parallel
@@ -16041,7 +16160,8 @@
(clobber (reg:CC FLAGS_REG))]
""
"bsr{l}\t{%1, %0|%0, %1}"
- [(set_attr "prefix_0f" "1")
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")
(set_attr "mode" "SI")])
(define_insn "popcount<mode>2"
@@ -16225,7 +16345,8 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT"
"bsr{q}\t{%1, %0|%0, %1}"
- [(set_attr "prefix_0f" "1")
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")
(set_attr "mode" "DI")])
(define_expand "clzhi2"
@@ -16263,7 +16384,8 @@
(clobber (reg:CC FLAGS_REG))]
""
"bsr{w}\t{%1, %0|%0, %1}"
- [(set_attr "prefix_0f" "1")
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")
(set_attr "mode" "HI")])
(define_expand "paritydi2"
@@ -19363,6 +19485,7 @@
"TARGET_USE_FANCY_MATH_387"
"fxam\n\tfnstsw\t%0"
[(set_attr "type" "multi")
+ (set_attr "length" "4")
(set_attr "unit" "i387")
(set_attr "mode" "<MODE>")])
@@ -22316,6 +22439,7 @@
}
[(set_attr "type" "sse")
(set_attr "atom_sse_attr" "prefetch")
+ (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
(set_attr "memory" "none")])
(define_insn "*prefetch_sse_rex"
@@ -22335,6 +22459,7 @@
}
[(set_attr "type" "sse")
(set_attr "atom_sse_attr" "prefetch")
+ (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
(set_attr "memory" "none")])
(define_insn "*prefetch_3dnow"
@@ -22349,6 +22474,7 @@
return "prefetchw\t%a0";
}
[(set_attr "type" "mmx")
+ (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
(set_attr "memory" "none")])
(define_insn "*prefetch_3dnow_rex"
@@ -22363,6 +22489,7 @@
return "prefetchw\t%a0";
}
[(set_attr "type" "mmx")
+ (set (attr "length_address") (symbol_ref "memory_address_length (operands[0])"))
(set_attr "memory" "none")])
(define_expand "stack_protect_set"
@@ -22520,6 +22647,14 @@
[(set_attr "type" "sselog1")
(set_attr "prefix_rep" "1")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_data16")
+ (if_then_else (match_operand:HI 2 "" "")
+ (const_string "1")
+ (const_string "*")))
+ (set (attr "prefix_rex")
+ (if_then_else (match_operand:QI 2 "ext_QIreg_operand" "")
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "SI")])
(define_insn "sse4_2_crc32di"
diff --git a/gcc/config/i386/mingw-tls.c b/gcc/config/i386/mingw-tls.c
new file mode 100644
index 00000000000..7a5c7758b2e
--- /dev/null
+++ b/gcc/config/i386/mingw-tls.c
@@ -0,0 +1,233 @@
+/* Catch and clean up data allocated in TLS.
+ Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+ 2009 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
+
+/* This part is based on the implementation of Mumit Khan <khan@nanotech.wisc.edu>
+ * provided to mingw under public domain and ported for libgcc by Kai Tietz.
+ */
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+#include <stdlib.h>
+
+/* The list of threads active with key/dtor pairs. */
+typedef struct __mingwthr_key {
+ DWORD key;
+ void (*dtor) (void *);
+ struct __mingwthr_key *next;
+} __mingwthr_key_t;
+
+#if defined(_WIN32) && !defined(__CYGWIN__)
+
+/* Possibly we could define this here for none MT too and avoid use of
+ mingwthrd.a at all, but well ... */
+#ifdef SHARED
+__declspec(dllexport)
+int _CRT_MT = 1;
+#else
+#if 0
+int _CRT_MT = 0;
+#endif
+#endif
+
+/* Static functions for libgcc. */
+#ifndef SHARED
+
+int __mingwthr_key_dtor (DWORD,void (*dtor)(void *));
+int __mingwthr_remove_key_dtor (DWORD);
+
+
+int
+__mingwthr_key_dtor (DWORD key __attribute__ ((__unused__)),
+ void (*dtor) (void *) __attribute__ ((__unused__)))
+{
+ return 0;
+}
+
+int
+__mingwthr_remove_key_dtor (DWORD key __attribute__ ((__unused__)))
+{
+ return 0;
+}
+
+#else
+/* Shared functions for libgcc. */
+
+/* Prototypes. */
+__declspec(dllexport) int __mingwthr_key_dtor (DWORD key, void (*) (void *));
+__declspec(dllexport) int __mingwthr_remove_key_dtor (DWORD);
+BOOL APIENTRY DllMain (HANDLE, DWORD, LPVOID);
+
+
+/* To protect the thread/key association data structure modifications. */
+static CRITICAL_SECTION __mingwthr_cs;
+static __mingwthr_key_t *key_dtor_list;
+
+/*
+ * __mingwthr_key_add:
+ *
+ * Add key/dtor association for this thread. If the thread entry does not
+ * exist, create a new one and add to the head of the threads list; add
+ * the new assoc at the head of the keys list.
+ *
+ */
+
+static int
+___mingwthr_add_key_dtor (DWORD key, void (*dtor) (void *))
+{
+ __mingwthr_key_t *new_key;
+
+ new_key = (__mingwthr_key_t *) calloc (1, sizeof (__mingwthr_key_t));
+ if (new_key == NULL)
+ return -1;
+
+ new_key->key = key;
+ new_key->dtor = dtor;
+
+ EnterCriticalSection (&__mingwthr_cs);
+
+ new_key->next = key_dtor_list;
+ key_dtor_list = new_key;
+
+ LeaveCriticalSection (&__mingwthr_cs);
+
+ return 0;
+}
+
+static int
+___mingwthr_remove_key_dtor (DWORD key)
+{
+ __mingwthr_key_t *prev_key;
+ __mingwthr_key_t *cur_key;
+
+ EnterCriticalSection (&__mingwthr_cs);
+
+ prev_key = NULL;
+ cur_key = key_dtor_list;
+
+ while (cur_key != NULL)
+ {
+ if( cur_key->key == key )
+ {
+ /* take key/dtor out of list */
+ if (prev_key == NULL)
+ key_dtor_list = cur_key->next;
+ else
+ prev_key->next = cur_key->next;
+
+ free (cur_key);
+ break;
+ }
+
+ prev_key = cur_key;
+ cur_key = cur_key->next;
+ }
+
+ LeaveCriticalSection (&__mingwthr_cs);
+
+ return 0;
+}
+
+/*
+ * __mingwthr_run_key_dtors (void):
+ *
+ * Callback from DllMain when thread detaches to clean up the key
+ * storage.
+ *
+ * Note that this does not delete the key itself, but just runs
+ * the dtor if the current value are both non-NULL. Note that the
+ * keys with NULL dtors are not added by __mingwthr_key_dtor, the
+ * only public interface, so we don't need to check.
+ *
+ */
+
+static void
+__mingwthr_run_key_dtors (void)
+{
+ __mingwthr_key_t *keyp;
+
+ EnterCriticalSection (&__mingwthr_cs);
+
+ for (keyp = key_dtor_list; keyp; )
+ {
+ LPVOID value = TlsGetValue (keyp->key);
+ if (GetLastError () == ERROR_SUCCESS)
+ {
+ if (value)
+ (*keyp->dtor) (value);
+ }
+ keyp = keyp->next;
+ }
+
+ LeaveCriticalSection (&__mingwthr_cs);
+}
+
+/*
+ * __mingwthr_register_key_dtor (DWORD key, void (*dtor) (void *))
+ *
+ * Public interface called by C++ exception handling mechanism in
+ * libgcc (cf: __gthread_key_create).
+ *
+ */
+
+__declspec(dllexport)
+int
+__mingwthr_key_dtor (DWORD key, void (*dtor) (void *))
+{
+ if (dtor)
+ return ___mingwthr_add_key_dtor (key, dtor);
+
+ return 0;
+}
+
+__declspec(dllexport)
+int
+__mingwthr_remove_key_dtor (DWORD key)
+{
+ return ___mingwthr_remove_key_dtor (key);
+}
+
+BOOL APIENTRY
+DllMain (HANDLE hDllHandle __attribute__ ((__unused__)),
+ DWORD reason /* Reason this function is being called. */,
+ LPVOID reserved __attribute__ ((__unused__)))
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ InitializeCriticalSection (&__mingwthr_cs);
+ break;
+
+ case DLL_PROCESS_DETACH:
+ __mingwthr_run_key_dtors ();
+ DeleteCriticalSection (&__mingwthr_cs);
+ break;
+
+ case DLL_THREAD_ATTACH:
+ break;
+
+ case DLL_THREAD_DETACH:
+ __mingwthr_run_key_dtors ();
+ break;
+ }
+ return TRUE;
+}
+#endif
+#endif
diff --git a/gcc/config/i386/mmx.md b/gcc/config/i386/mmx.md
index 5184b1d7f5c..dea9322f9a8 100644
--- a/gcc/config/i386/mmx.md
+++ b/gcc/config/i386/mmx.md
@@ -1,5 +1,5 @@
;; GCC machine description for MMX and 3dNOW! instructions
-;; Copyright (C) 2005, 2007, 2008
+;; Copyright (C) 2005, 2007, 2008, 2009
;; Free Software Foundation, Inc.
;;
;; This file is part of GCC.
@@ -85,6 +85,12 @@
%vmovq\t{%1, %0|%0, %1}"
[(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,ssemov")
(set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*")
+ (set_attr "prefix_rep" "*,*,*,*,*,1,1,*,1,*,*,*")
+ (set_attr "prefix_data16" "*,*,*,*,*,*,*,*,*,1,1,1")
+ (set (attr "prefix_rex")
+ (if_then_else (eq_attr "alternative" "8,9")
+ (symbol_ref "x86_extended_reg_mentioned_p (insn)")
+ (const_string "*")))
(set (attr "prefix")
(if_then_else (eq_attr "alternative" "7,8,9,10,11")
(const_string "maybe_vex")
@@ -111,6 +117,7 @@
#"
[(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,*,*")
(set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*")
+ (set_attr "prefix_rep" "*,*,*,1,1,*,*,*,*,*")
(set (attr "prefix")
(if_then_else (eq_attr "alternative" "5,6,7")
(const_string "vex")
@@ -141,6 +148,8 @@
#"
[(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,sselog1,ssemov,ssemov,ssemov,*,*")
(set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*,*,*,*")
+ (set_attr "prefix_rep" "*,*,*,1,1,*,1,*,*,*,*,*,*,*")
+ (set_attr "prefix_data16" "*,*,*,*,*,*,*,1,*,*,*,*,*,*")
(set_attr "mode" "DI,DI,DI,DI,DI,TI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
(define_expand "movv2sf"
@@ -175,6 +184,8 @@
vmovq\t{%1, %0|%0, %1}"
[(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,sselog1,ssemov,ssemov,ssemov,ssemov")
(set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*,*")
+ (set_attr "prefix_rep" "*,*,*,*,*,1,1,*,*,*,*,*,*")
+ (set_attr "length_vex" "*,*,*,*,*,*,*,*,*,*,*,4,4")
(set (attr "prefix")
(if_then_else (eq_attr "alternative" "7,8,9,10,11,12")
(const_string "vex")
@@ -204,6 +215,7 @@
movd\t{%1, %0|%0, %1}"
[(set_attr "type" "imov,imov,mmx,mmxmov,mmxmov,ssecvt,ssecvt,ssemov,sselog1,ssemov,ssemov,ssemov,ssemov")
(set_attr "unit" "*,*,*,*,*,mmx,mmx,*,*,*,*,*,*")
+ (set_attr "prefix_rep" "*,*,*,*,*,1,1,*,*,*,*,*,*")
(set_attr "mode" "DI,DI,DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
(define_insn "*movv2sf_internal_avx"
@@ -227,6 +239,7 @@
#"
[(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,*,*")
(set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*")
+ (set_attr "prefix_rep" "*,*,*,1,1,*,*,*,*,*,*")
(set (attr "prefix")
(if_then_else (eq_attr "alternative" "5,6,7,8")
(const_string "vex")
@@ -254,6 +267,7 @@
#"
[(set_attr "type" "mmx,mmxmov,mmxmov,ssecvt,ssecvt,sselog1,ssemov,ssemov,ssemov,*,*")
(set_attr "unit" "*,*,*,mmx,mmx,*,*,*,*,*,*")
+ (set_attr "prefix_rep" "*,*,*,1,1,*,*,*,*,*,*")
(set_attr "mode" "DI,DI,DI,DI,DI,V4SF,V4SF,V2SF,V2SF,DI,DI")])
;; %%% This multiword shite has got to go.
@@ -313,6 +327,7 @@
"TARGET_3DNOW && ix86_binary_operator_ok (PLUS, V2SFmode, operands)"
"pfadd\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxadd")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_expand "mmx_subv2sf3"
@@ -338,6 +353,7 @@
pfsub\t{%2, %0|%0, %2}
pfsubr\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxadd")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_expand "mmx_mulv2sf3"
@@ -354,6 +370,7 @@
"TARGET_3DNOW && ix86_binary_operator_ok (MULT, V2SFmode, operands)"
"pfmul\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxmul")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
;; ??? For !flag_finite_math_only, the representation with SMIN/SMAX
@@ -381,6 +398,7 @@
&& ix86_binary_operator_ok (<CODE>, V2SFmode, operands)"
"pf<maxminfprefix>\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxadd")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "*mmx_<code>v2sf3"
@@ -391,6 +409,7 @@
"TARGET_3DNOW"
"pf<maxminfprefix>\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxadd")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_rcpv2sf2"
@@ -400,6 +419,7 @@
"TARGET_3DNOW"
"pfrcp\t{%1, %0|%0, %1}"
[(set_attr "type" "mmx")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_rcpit1v2sf3"
@@ -410,6 +430,7 @@
"TARGET_3DNOW"
"pfrcpit1\t{%2, %0|%0, %2}"
[(set_attr "type" "mmx")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_rcpit2v2sf3"
@@ -420,6 +441,7 @@
"TARGET_3DNOW"
"pfrcpit2\t{%2, %0|%0, %2}"
[(set_attr "type" "mmx")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_rsqrtv2sf2"
@@ -429,6 +451,7 @@
"TARGET_3DNOW"
"pfrsqrt\t{%1, %0|%0, %1}"
[(set_attr "type" "mmx")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_rsqit1v2sf3"
@@ -439,6 +462,7 @@
"TARGET_3DNOW"
"pfrsqit1\t{%2, %0|%0, %2}"
[(set_attr "type" "mmx")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_haddv2sf3"
@@ -457,6 +481,7 @@
"TARGET_3DNOW"
"pfacc\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxadd")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_hsubv2sf3"
@@ -475,6 +500,7 @@
"TARGET_3DNOW_A"
"pfnacc\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxadd")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_addsubv2sf3"
@@ -488,6 +514,7 @@
"TARGET_3DNOW_A"
"pfpnacc\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxadd")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -510,6 +537,7 @@
"TARGET_3DNOW && ix86_binary_operator_ok (EQ, V2SFmode, operands)"
"pfcmpeq\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxcmp")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_gtv2sf3"
@@ -519,6 +547,7 @@
"TARGET_3DNOW"
"pfcmpgt\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxcmp")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_gev2sf3"
@@ -528,6 +557,7 @@
"TARGET_3DNOW"
"pfcmpge\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxcmp")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -542,6 +572,7 @@
"TARGET_3DNOW"
"pf2id\t{%1, %0|%0, %1}"
[(set_attr "type" "mmxcvt")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_pf2iw"
@@ -553,6 +584,7 @@
"TARGET_3DNOW_A"
"pf2iw\t{%1, %0|%0, %1}"
[(set_attr "type" "mmxcvt")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_pi2fw"
@@ -564,6 +596,7 @@
"TARGET_3DNOW_A"
"pi2fw\t{%1, %0|%0, %1}"
[(set_attr "type" "mmxcvt")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "mmx_floatv2si2"
@@ -572,6 +605,7 @@
"TARGET_3DNOW"
"pi2fd\t{%1, %0|%0, %1}"
[(set_attr "type" "mmxcvt")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -587,6 +621,7 @@
"TARGET_3DNOW_A"
"pswapd\t{%1, %0|%0, %1}"
[(set_attr "type" "mmxcvt")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "V2SF")])
(define_insn "*vec_dupv2sf"
@@ -887,6 +922,7 @@
"TARGET_3DNOW && ix86_binary_operator_ok (MULT, V4HImode, operands)"
"pmulhrw\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxmul")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
(define_expand "sse2_umulv1siv1di3"
@@ -965,6 +1001,10 @@
"TARGET_MMX"
"psra<mmxvecsize>\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxshft")
+ (set (attr "length_immediate")
+ (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "DI")])
(define_insn "mmx_lshr<mode>3"
@@ -975,6 +1015,10 @@
"TARGET_MMX"
"psrl<mmxvecsize>\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxshft")
+ (set (attr "length_immediate")
+ (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "DI")])
(define_insn "mmx_ashl<mode>3"
@@ -985,6 +1029,10 @@
"TARGET_MMX"
"psll<mmxvecsize>\t{%2, %0|%0, %2}"
[(set_attr "type" "mmxshft")
+ (set (attr "length_immediate")
+ (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "DI")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -1205,6 +1253,7 @@
return "pinsrw\t{%3, %k2, %0|%0, %k2, %3}";
}
[(set_attr "type" "mmxcvt")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "DI")])
(define_insn "mmx_pextrw"
@@ -1216,6 +1265,7 @@
"TARGET_SSE || TARGET_3DNOW_A"
"pextrw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "mmxcvt")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "DI")])
(define_expand "mmx_pshufw"
@@ -1253,6 +1303,7 @@
return "pshufw\t{%2, %1, %0|%0, %1, %2}";
}
[(set_attr "type" "mmxcvt")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "DI")])
(define_insn "mmx_pswapdv2si2"
@@ -1263,6 +1314,7 @@
"TARGET_3DNOW_A"
"pswapd\t{%1, %0|%0, %1}"
[(set_attr "type" "mmxcvt")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "DI")])
(define_insn "*vec_dupv4hi"
@@ -1273,6 +1325,7 @@
"TARGET_SSE || TARGET_3DNOW_A"
"pshufw\t{$0, %0, %0|%0, %0, 0}"
[(set_attr "type" "mmxcvt")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "DI")])
(define_insn "*vec_dupv2si"
@@ -1345,6 +1398,7 @@
#
#"
[(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")])
(define_split
@@ -1492,6 +1546,11 @@
return "pavgusb\t{%2, %0|%0, %2}";
}
[(set_attr "type" "mmxshft")
+ (set (attr "prefix_extra")
+ (if_then_else
+ (eq (symbol_ref "(TARGET_SSE || TARGET_3DNOW_A)") (const_int 0))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "DI")])
(define_expand "mmx_uavgv4hi3"
@@ -1602,6 +1661,7 @@
"TARGET_MMX"
"emms"
[(set_attr "type" "mmx")
+ (set_attr "modrm" "0")
(set_attr "memory" "unknown")])
(define_insn "mmx_femms"
@@ -1625,4 +1685,5 @@
"TARGET_3DNOW"
"femms"
[(set_attr "type" "mmx")
+ (set_attr "modrm" "0")
(set_attr "memory" "none")])
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 4feb86144a9..2089de768ce 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -84,6 +84,12 @@
&& GET_MODE (op) == QImode
&& REGNO (op) > BX_REG")))
+;; Similarly, but don't check mode of the operand.
+(define_predicate "ext_QIreg_nomode_operand"
+ (and (match_code "reg")
+ (match_test "TARGET_64BIT
+ && REGNO (op) > BX_REG")))
+
;; Return true if op is not xmm0 register.
(define_predicate "reg_not_xmm0_operand"
(and (match_operand 0 "register_operand")
@@ -587,11 +593,6 @@
(and (match_code "const_int")
(match_test "INTVAL (op) == 128")))
-;; Match exactly -128.
-(define_predicate "constm128_operand"
- (and (match_code "const_int")
- (match_test "INTVAL (op) == -128")))
-
;; Match 2, 4, or 8. Used for leal multiplicands.
(define_predicate "const248_operand"
(match_code "const_int")
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index d705fa11cc5..da06d44c41a 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -437,6 +437,7 @@
"TARGET_SSE2"
"movnti\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
+ (set_attr "prefix_data16" "0")
(set_attr "mode" "V2DF")])
(define_insn "avx_lddqu<avxmodesuffix>"
@@ -459,6 +460,7 @@
"lddqu\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
(set_attr "movu" "1")
+ (set_attr "prefix_data16" "0")
(set_attr "prefix_rep" "1")
(set_attr "mode" "TI")])
@@ -1407,6 +1409,7 @@
"TARGET_AVX"
"vcmpp<avxmodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "ssecmp")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
@@ -1423,6 +1426,7 @@
"TARGET_AVX"
"vcmps<ssemodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "ssecmp")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<ssescalarmode>")])
@@ -1437,6 +1441,7 @@
"vcmp%D3p<avxmodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "ssecmp")
(set_attr "prefix" "vex")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<avxvecmode>")])
(define_insn "<sse>_maskcmp<mode>3"
@@ -1448,6 +1453,7 @@
&& !TARGET_SSE5"
"cmp%D3<ssemodesuffixf4>\t{%2, %0|%0, %2}"
[(set_attr "type" "ssecmp")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<MODE>")])
(define_insn "<sse>_vmmaskcmp<mode>3"
@@ -1461,6 +1467,7 @@
"SSE_VEC_FLOAT_MODE_P (<MODE>mode) && !TARGET_SSE5"
"cmp%D3s<ssemodesuffixf2c>\t{%2, %0|%0, %2}"
[(set_attr "type" "ssecmp")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<ssescalarmode>")])
(define_insn "<sse>_comi"
@@ -1476,6 +1483,11 @@
"%vcomis<ssemodefsuffix>\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecomi")
(set_attr "prefix" "maybe_vex")
+ (set_attr "prefix_rep" "0")
+ (set (attr "prefix_data16")
+ (if_then_else (eq_attr "mode" "DF")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "<MODE>")])
(define_insn "<sse>_ucomi"
@@ -1491,6 +1503,11 @@
"%vucomis<ssemodefsuffix>\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecomi")
(set_attr "prefix" "maybe_vex")
+ (set_attr "prefix_rep" "0")
+ (set (attr "prefix_data16")
+ (if_then_else (eq_attr "mode" "DF")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "<MODE>")])
(define_expand "vcond<mode>"
@@ -2222,6 +2239,7 @@
"cvttps2pi\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt")
(set_attr "unit" "mmx")
+ (set_attr "prefix_rep" "0")
(set_attr "mode" "SF")])
(define_insn "*avx_cvtsi2ss"
@@ -2261,6 +2279,7 @@
"TARGET_AVX && TARGET_64BIT"
"vcvtsi2ssq\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseicvt")
+ (set_attr "length_vex" "4")
(set_attr "prefix" "vex")
(set_attr "mode" "SF")])
@@ -2274,6 +2293,7 @@
"TARGET_SSE && TARGET_64BIT"
"cvtsi2ssq\t{%2, %0|%0, %2}"
[(set_attr "type" "sseicvt")
+ (set_attr "prefix_rex" "1")
(set_attr "athlon_decode" "vector,double")
(set_attr "amdfam10_decode" "vector,double")
(set_attr "mode" "SF")])
@@ -2420,6 +2440,7 @@
"cvttps2dq\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt")
(set_attr "prefix_rep" "1")
+ (set_attr "prefix_data16" "0")
(set_attr "mode" "TI")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -2435,6 +2456,7 @@
"cvtpi2pd\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt")
(set_attr "unit" "mmx,*")
+ (set_attr "prefix_data16" "1,*")
(set_attr "mode" "V2DF")])
(define_insn "sse2_cvtpd2pi"
@@ -2495,6 +2517,7 @@
"TARGET_AVX && TARGET_64BIT"
"vcvtsi2sdq\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseicvt")
+ (set_attr "length_vex" "4")
(set_attr "prefix" "vex")
(set_attr "mode" "DF")])
@@ -2508,6 +2531,7 @@
"TARGET_SSE2 && TARGET_64BIT"
"cvtsi2sdq\t{%2, %0|%0, %2}"
[(set_attr "type" "sseicvt")
+ (set_attr "prefix_rex" "1")
(set_attr "mode" "DF")
(set_attr "athlon_decode" "double,direct")
(set_attr "amdfam10_decode" "vector,double")])
@@ -2649,6 +2673,7 @@
: \"cvtpd2dq\t{%1, %0|%0, %1}\";"
[(set_attr "type" "ssecvt")
(set_attr "prefix_rep" "1")
+ (set_attr "prefix_data16" "0")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")
(set_attr "amdfam10_decode" "double")])
@@ -2679,7 +2704,6 @@
"* return TARGET_AVX ? \"vcvttpd2dq{x}\t{%1, %0|%0, %1}\"
: \"cvttpd2dq\t{%1, %0|%0, %1}\";"
[(set_attr "type" "ssecvt")
- (set_attr "prefix_rep" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")
(set_attr "amdfam10_decode" "double")])
@@ -2798,6 +2822,7 @@
[(set_attr "type" "ssecvt")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V2DF")
+ (set_attr "prefix_data16" "0")
(set_attr "amdfam10_decode" "direct")])
(define_expand "vec_unpacks_hi_v4sf"
@@ -3268,6 +3293,7 @@
return "vshufps\t{%3, %2, %1, %0|%0, %1, %2, %3}";
}
[(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -3309,6 +3335,7 @@
return "vshufps\t{%3, %2, %1, %0|%0, %1, %2, %3}";
}
[(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V4SF")])
@@ -3334,6 +3361,7 @@
return "shufps\t{%3, %2, %0|%0, %2, %3}";
}
[(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "V4SF")])
(define_insn "sse_storehps"
@@ -3441,6 +3469,7 @@
vmovlps\t{%2, %1, %0|%0, %1, %2}
vmovlps\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog,ssemov,ssemov")
+ (set_attr "length_immediate" "1,*,*")
(set_attr "prefix" "vex")
(set_attr "mode" "V4SF,V2SF,V2SF")])
@@ -3457,6 +3486,7 @@
movlps\t{%2, %0|%0, %2}
movlps\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog,ssemov,ssemov")
+ (set_attr "length_immediate" "1,*,*")
(set_attr "mode" "V4SF,V2SF,V2SF")])
(define_insn "*avx_movss"
@@ -3489,6 +3519,7 @@
"TARGET_AVX"
"vshufps\t{$0, %1, %1, %0|%0, %1, %1, 0}"
[(set_attr "type" "sselog1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V4SF")])
@@ -3499,6 +3530,7 @@
"TARGET_SSE"
"shufps\t{$0, %0, %0|%0, %0, 0}"
[(set_attr "type" "sselog1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "V4SF")])
(define_insn "*vec_concatv2sf_avx"
@@ -3514,6 +3546,8 @@
punpckldq\t{%2, %0|%0, %2}
movd\t{%1, %0|%0, %1}"
[(set_attr "type" "sselog,sselog,ssemov,mmxcvt,mmxmov")
+ (set_attr "length_immediate" "*,1,*,*,*")
+ (set_attr "prefix_extra" "*,1,*,*,*")
(set (attr "prefix")
(if_then_else (eq_attr "alternative" "3,4")
(const_string "orig")
@@ -3535,7 +3569,9 @@
punpckldq\t{%2, %0|%0, %2}
movd\t{%1, %0|%0, %1}"
[(set_attr "type" "sselog,sselog,ssemov,mmxcvt,mmxmov")
+ (set_attr "prefix_data16" "*,1,*,*,*")
(set_attr "prefix_extra" "*,1,*,*,*")
+ (set_attr "length_immediate" "*,1,*,*,*")
(set_attr "mode" "V4SF,V4SF,SF,DI,DI")])
;; ??? In theory we can match memory for the MMX alternative, but allowing
@@ -3636,6 +3672,8 @@
return "vinsertps\t{%3, %2, %1, %0|%0, %1, %2, %3}";
}
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V4SF")])
@@ -3652,7 +3690,9 @@
return "insertps\t{%3, %2, %0|%0, %2, %3}";
}
[(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "V4SF")])
(define_insn "*avx_insertps"
@@ -3665,6 +3705,8 @@
"vinsertps\t{%3, %2, %1, %0|%0, %1, %2, %3}";
[(set_attr "type" "sselog")
(set_attr "prefix" "vex")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "V4SF")])
(define_insn "sse4_1_insertps"
@@ -3676,7 +3718,9 @@
"TARGET_SSE4_1"
"insertps\t{%3, %2, %0|%0, %2, %3}";
[(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "V4SF")])
(define_split
@@ -3751,6 +3795,8 @@
"TARGET_AVX"
"vextractf128\t{$0x0, %1, %0|%0, %1, 0x0}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,store")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -3763,6 +3809,8 @@
"TARGET_AVX"
"vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,store")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -3776,6 +3824,8 @@
"TARGET_AVX"
"vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,store")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -3789,6 +3839,8 @@
"TARGET_AVX"
"vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,store")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -3804,6 +3856,8 @@
"TARGET_AVX"
"vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,store")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -3819,6 +3873,8 @@
"TARGET_AVX"
"vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,store")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -3838,6 +3894,8 @@
"TARGET_AVX"
"vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,store")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -3857,6 +3915,8 @@
"TARGET_AVX"
"vextractf128\t{$0x1, %1, %0|%0, %1, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,store")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -3869,7 +3929,9 @@
"TARGET_SSE4_1"
"%vextractps\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V4SF")])
@@ -3962,6 +4024,7 @@
movlpd\t{%H1, %0|%0, %H1}
movhpd\t{%1, %0|%0, %1}"
[(set_attr "type" "sselog,ssemov,ssemov")
+ (set_attr "prefix_data16" "*,1,1")
(set_attr "mode" "V2DF,V1DF,V1DF")])
(define_insn "avx_movddup256"
@@ -4082,6 +4145,7 @@
movhpd\t{%2, %0|%0, %2}
movlpd\t{%2, %H0|%H0, %2}"
[(set_attr "type" "sselog,ssemov,ssemov")
+ (set_attr "prefix_data16" "*,1,1")
(set_attr "mode" "V2DF,V1DF,V1DF")])
(define_expand "avx_shufpd256"
@@ -4122,6 +4186,7 @@
return "vshufpd\t{%3, %2, %1, %0|%0, %1, %2, %3}";
}
[(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V4DF")])
@@ -4258,6 +4323,7 @@
return "vshufpd\t{%3, %2, %1, %0|%0, %1, %2, %3}";
}
[(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V2DF")])
@@ -4279,6 +4345,7 @@
return "shufpd\t{%3, %2, %0|%0, %2, %3}";
}
[(set_attr "type" "sselog")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "V2DF")])
;; Avoid combining registers from different units in a single alternative,
@@ -4312,6 +4379,7 @@
#
#"
[(set_attr "type" "ssemov,sselog1,ssemov,fmov,imov")
+ (set_attr "prefix_data16" "1,*,*,*,*")
(set_attr "mode" "V1DF,V2DF,DF,DF,DF")])
(define_split
@@ -4340,6 +4408,7 @@
#
#"
[(set_attr "type" "ssemov,ssemov,ssemov,fmov,imov")
+ (set_attr "prefix_data16" "1,*,*,*,*")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "V1DF,DF,DF,DF,DF")])
@@ -4406,6 +4475,8 @@
#
#"
[(set_attr "type" "ssemov,sselog,sselog,ssemov,fmov,imov")
+ (set_attr "prefix_data16" "1,*,*,*,*,*")
+ (set_attr "length_immediate" "*,*,1,*,*,*")
(set_attr "mode" "V1DF,V2DF,V2DF,DF,DF,DF")])
(define_split
@@ -4469,6 +4540,8 @@
#
#"
[(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov,fmov,imov")
+ (set_attr "prefix_data16" "*,1,*,*,1,*,*,*")
+ (set_attr "length_immediate" "*,*,*,1,*,*,*,*")
(set_attr "mode" "DF,V1DF,V1DF,V2DF,V1DF,DF,DF,DF")])
(define_split
@@ -4544,6 +4617,8 @@
movhps\t{%H1, %0|%0, %H1}
movhps\t{%1, %H0|%H0, %1}"
[(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
+ (set_attr "prefix_data16" "*,1,1,*,*,*")
+ (set_attr "length_immediate" "*,*,*,1,*,*")
(set_attr "mode" "DF,V1DF,V1DF,V2DF,V1DF,V1DF")])
(define_insn "*vec_dupv2df_sse3"
@@ -4603,6 +4678,7 @@
movlhps\t{%2, %0|%0, %2}
movhps\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog,ssemov,ssemov,ssemov,ssemov")
+ (set_attr "prefix_data16" "*,1,*,*,*")
(set_attr "mode" "V2DF,V1DF,DF,V4SF,V2SF")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -4951,6 +5027,7 @@
"TARGET_AVX && ix86_binary_operator_ok (MULT, V4SImode, operands)"
"vpmuldq\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseimul")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -5097,6 +5174,7 @@
"TARGET_AVX && ix86_binary_operator_ok (MULT, V4SImode, operands)"
"vpmulld\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseimul")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -5492,6 +5570,10 @@
"vpsra<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
(set_attr "prefix" "vex")
+ (set (attr "length_immediate")
+ (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "TI")])
(define_insn "ashr<mode>3"
@@ -5503,6 +5585,10 @@
"psra<ssevecsize>\t{%2, %0|%0, %2}"
[(set_attr "type" "sseishft")
(set_attr "prefix_data16" "1")
+ (set (attr "length_immediate")
+ (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "TI")])
(define_insn "*avx_lshr<mode>3"
@@ -5514,6 +5600,10 @@
"vpsrl<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
(set_attr "prefix" "vex")
+ (set (attr "length_immediate")
+ (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "TI")])
(define_insn "lshr<mode>3"
@@ -5525,6 +5615,10 @@
"psrl<ssevecsize>\t{%2, %0|%0, %2}"
[(set_attr "type" "sseishft")
(set_attr "prefix_data16" "1")
+ (set (attr "length_immediate")
+ (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "TI")])
(define_insn "*avx_ashl<mode>3"
@@ -5536,6 +5630,10 @@
"vpsll<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
(set_attr "prefix" "vex")
+ (set (attr "length_immediate")
+ (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "TI")])
(define_insn "ashl<mode>3"
@@ -5547,6 +5645,10 @@
"psll<ssevecsize>\t{%2, %0|%0, %2}"
[(set_attr "type" "sseishft")
(set_attr "prefix_data16" "1")
+ (set (attr "length_immediate")
+ (if_then_else (match_operand 2 "const_int_operand" "")
+ (const_string "1")
+ (const_string "0")))
(set_attr "mode" "TI")])
(define_expand "vec_shl_<mode>"
@@ -5577,6 +5679,12 @@
"TARGET_AVX && ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
"vp<maxminiprefix><ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseiadd")
+ (set (attr "prefix_extra")
+ (if_then_else
+ (ne (symbol_ref "<MODE>mode != ((<CODE> == SMAX || <CODE> == SMIN) ? V8HImode : V16QImode)")
+ (const_int 0))
+ (const_string "1")
+ (const_string "0")))
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -5781,6 +5889,10 @@
"TARGET_AVX && ix86_binary_operator_ok (EQ, <MODE>mode, operands)"
"vpcmpeq<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "ssecmp")
+ (set (attr "prefix_extra")
+ (if_then_else (match_operand:V2DI 0 "" "")
+ (const_string "1")
+ (const_string "*")))
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -5823,6 +5935,10 @@
"TARGET_AVX"
"vpcmpgt<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "ssecmp")
+ (set (attr "prefix_extra")
+ (if_then_else (match_operand:V2DI 0 "" "")
+ (const_string "1")
+ (const_string "*")))
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -5845,6 +5961,7 @@
"TARGET_SSE4_2"
"pcmpgtq\t{%2, %0|%0, %2}"
[(set_attr "type" "ssecmp")
+ (set_attr "prefix_extra" "1")
(set_attr "mode" "TI")])
(define_expand "vcond<mode>"
@@ -6603,6 +6720,11 @@
return "vpinsr<ssevecsize>\t{%3, %k2, %1, %0|%0, %1, %k2, %3}";
}
[(set_attr "type" "sselog")
+ (set (attr "prefix_extra")
+ (if_then_else (match_operand:V8HI 0 "register_operand" "")
+ (const_string "0")
+ (const_string "1")))
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -6620,6 +6742,7 @@
}
[(set_attr "type" "sselog")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "*sse2_pinsrw"
@@ -6636,6 +6759,7 @@
}
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
;; It must come before sse2_loadld since it is preferred.
@@ -6653,6 +6777,7 @@
}
[(set_attr "type" "sselog")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "*avx_pinsrq"
@@ -6668,6 +6793,8 @@
return "vpinsrq\t{%3, %2, %1, %0|%0, %1, %2, %3}";
}
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -6684,7 +6811,9 @@
return "pinsrq\t{%3, %2, %0|%0, %2, %3}";
}
[(set_attr "type" "sselog")
+ (set_attr "prefix_rex" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "*sse4_1_pextrb"
@@ -6697,6 +6826,7 @@
"%vpextrb\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -6709,6 +6839,7 @@
"%vpextrb\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -6722,6 +6853,7 @@
"%vpextrw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -6734,6 +6866,7 @@
"%vpextrw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -6746,6 +6879,7 @@
"%vpextrd\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -6758,7 +6892,9 @@
"TARGET_SSE4_1 && TARGET_64BIT"
"%vpextrq\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_rex" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -6798,7 +6934,8 @@
}
[(set_attr "type" "sselog1")
(set_attr "prefix_data16" "1")
- (set_attr "prefix" "vex")
+ (set_attr "prefix" "maybe_vex")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_expand "sse2_pshuflw"
@@ -6840,8 +6977,10 @@
return "%vpshuflw\t{%2, %1, %0|%0, %1, %2}";
}
[(set_attr "type" "sselog")
+ (set_attr "prefix_data16" "0")
(set_attr "prefix_rep" "1")
(set_attr "prefix" "maybe_vex")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_expand "sse2_pshufhw"
@@ -6884,7 +7023,9 @@
}
[(set_attr "type" "sselog")
(set_attr "prefix_rep" "1")
+ (set_attr "prefix_data16" "0")
(set_attr "prefix" "maybe_vex")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_expand "sse2_loadd"
@@ -7020,6 +7161,7 @@
vmovq\t{%H1, %0|%0, %H1}
vmov{q}\t{%H1, %0|%0, %H1}"
[(set_attr "type" "ssemov,sseishft,ssemov,imov")
+ (set_attr "length_immediate" "*,1,*,*")
(set_attr "memory" "*,none,*,*")
(set_attr "prefix" "vex")
(set_attr "mode" "V2SF,TI,TI,DI")])
@@ -7036,6 +7178,7 @@
movq\t{%H1, %0|%0, %H1}
mov{q}\t{%H1, %0|%0, %H1}"
[(set_attr "type" "ssemov,sseishft,ssemov,imov")
+ (set_attr "length_immediate" "*,1,*,*")
(set_attr "atom_unit" "*,sishuf,*,*")
(set_attr "memory" "*,none,*,*")
(set_attr "mode" "V2SF,TI,TI,DI")])
@@ -7053,6 +7196,7 @@
vpsrldq\t{$8, %1, %0|%0, %1, 8}
vmovq\t{%H1, %0|%0, %H1}"
[(set_attr "type" "ssemov,sseishft,ssemov")
+ (set_attr "length_immediate" "*,1,*")
(set_attr "memory" "*,none,*")
(set_attr "prefix" "vex")
(set_attr "mode" "V2SF,TI,TI")])
@@ -7069,6 +7213,7 @@
psrldq\t{$8, %0|%0, 8}
movq\t{%H1, %0|%0, %H1}"
[(set_attr "type" "ssemov,sseishft,ssemov")
+ (set_attr "length_immediate" "*,1,*")
(set_attr "atom_unit" "*,sishuf,*")
(set_attr "memory" "*,none,*")
(set_attr "mode" "V2SF,TI,TI")])
@@ -7098,6 +7243,7 @@
shufps\t{$0, %0, %0|%0, %0, 0}"
[(set_attr "type" "sselog1")
(set_attr "prefix" "maybe_vex,orig")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI,V4SF")])
(define_insn "*vec_dupv2di_avx"
@@ -7134,6 +7280,8 @@
punpckldq\t{%2, %0|%0, %2}
movd\t{%1, %0|%0, %1}"
[(set_attr "type" "sselog,sselog,ssemov,mmxcvt,mmxmov")
+ (set_attr "prefix_extra" "1,*,*,*,*")
+ (set_attr "length_immediate" "1,*,*,*,*")
(set (attr "prefix")
(if_then_else (eq_attr "alternative" "3,4")
(const_string "orig")
@@ -7154,6 +7302,7 @@
movd\t{%1, %0|%0, %1}"
[(set_attr "type" "sselog,sselog,ssemov,mmxcvt,mmxmov")
(set_attr "prefix_extra" "1,*,*,*,*")
+ (set_attr "length_immediate" "1,*,*,*,*")
(set_attr "mode" "TI,TI,TI,DI,DI")])
;; ??? In theory we can match memory for the MMX alternative, but allowing
@@ -7260,6 +7409,8 @@
vpunpcklqdq\t{%2, %1, %0|%0, %1, %2}
vmovhps\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog,ssemov,ssemov,ssemov,sselog,ssemov")
+ (set_attr "prefix_extra" "1,*,*,*,*,*")
+ (set_attr "length_immediate" "1,*,*,*,*,*")
(set (attr "prefix")
(if_then_else (eq_attr "alternative" "3")
(const_string "orig")
@@ -7281,7 +7432,9 @@
movlhps\t{%2, %0|%0, %2}
movhps\t{%2, %0|%0, %2}"
[(set_attr "type" "sselog,ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
+ (set_attr "prefix_rex" "1,*,1,*,*,*,*")
(set_attr "prefix_extra" "1,*,*,*,*,*,*")
+ (set_attr "length_immediate" "1,*,*,*,*,*,*")
(set_attr "mode" "TI,TI,TI,TI,TI,V4SF,V2SF")])
(define_insn "*vec_concatv2di_rex64_sse"
@@ -7298,6 +7451,7 @@
movlhps\t{%2, %0|%0, %2}
movhps\t{%2, %0|%0, %2}"
[(set_attr "type" "ssemov,ssemov,ssemov,sselog,ssemov,ssemov")
+ (set_attr "prefix_rex" "*,1,*,*,*,*")
(set_attr "mode" "TI,TI,TI,TI,V4SF,V2SF")])
(define_expand "vec_unpacku_hi_v16qi"
@@ -7684,6 +7838,8 @@
"%vmaskmovdqu\t{%2, %1|%1, %2}"
[(set_attr "type" "ssemov")
(set_attr "prefix_data16" "1")
+ ;; The implicit %rdi operand confuses default length_vex computation.
+ (set_attr "length_vex" "3")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -7698,6 +7854,9 @@
"%vmaskmovdqu\t{%2, %1|%1, %2}"
[(set_attr "type" "ssemov")
(set_attr "prefix_data16" "1")
+ ;; The implicit %rdi operand confuses default length_vex computation.
+ (set (attr "length_vex")
+ (symbol_ref ("REGNO (operands[2]) >= FIRST_REX_SSE_REG ? 3 + 1 : 2 + 1")))
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -7736,6 +7895,7 @@
"TARGET_SSE || TARGET_3DNOW_A"
"sfence"
[(set_attr "type" "sse")
+ (set_attr "length_address" "0")
(set_attr "atom_sse_attr" "fence")
(set_attr "memory" "unknown")])
@@ -7763,6 +7923,7 @@
"TARGET_64BIT || TARGET_SSE2"
"mfence"
[(set_attr "type" "sse")
+ (set_attr "length_address" "0")
(set_attr "atom_sse_attr" "fence")
(set_attr "memory" "unknown")])
@@ -7781,6 +7942,7 @@
"TARGET_SSE2"
"lfence"
[(set_attr "type" "sse")
+ (set_attr "length_address" "0")
(set_attr "atom_sse_attr" "lfence")
(set_attr "memory" "unknown")])
@@ -7862,6 +8024,7 @@
"TARGET_AVX"
"vphaddw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -7936,6 +8099,7 @@
[(set_attr "type" "sseiadd")
(set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_insn "*avx_phadddv4si3"
@@ -7962,6 +8126,7 @@
"TARGET_AVX"
"vphaddd\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -8012,6 +8177,7 @@
[(set_attr "type" "sseiadd")
(set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_insn "*avx_phaddswv8hi3"
@@ -8054,6 +8220,7 @@
"TARGET_AVX"
"vphaddsw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -8128,6 +8295,7 @@
[(set_attr "type" "sseiadd")
(set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_insn "*avx_phsubwv8hi3"
@@ -8170,6 +8338,7 @@
"TARGET_AVX"
"vphsubw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -8244,6 +8413,7 @@
[(set_attr "type" "sseiadd")
(set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_insn "*avx_phsubdv4si3"
@@ -8270,6 +8440,7 @@
"TARGET_AVX"
"vphsubd\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -8320,6 +8491,7 @@
[(set_attr "type" "sseiadd")
(set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_insn "*avx_phsubswv8hi3"
@@ -8362,6 +8534,7 @@
"TARGET_AVX"
"vphsubsw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -8436,6 +8609,7 @@
[(set_attr "type" "sseiadd")
(set_attr "atom_unit" "complex")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_insn "*avx_pmaddubsw128"
@@ -8488,6 +8662,7 @@
"TARGET_AVX"
"vpmaddubsw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseiadd")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -8582,6 +8757,7 @@
[(set_attr "type" "sseiadd")
(set_attr "atom_unit" "simul")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_expand "ssse3_pmulhrswv8hi3"
@@ -8624,6 +8800,7 @@
"TARGET_AVX && ix86_binary_operator_ok (MULT, V8HImode, operands)"
"vpmulhrsw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseimul")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -8688,6 +8865,7 @@
"pmulhrsw\t{%2, %0|%0, %2}"
[(set_attr "type" "sseimul")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_insn "*avx_pshufbv16qi3"
@@ -8698,6 +8876,7 @@
"TARGET_AVX"
"vpshufb\t{%2, %1, %0|%0, %1, %2}";
[(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -8722,6 +8901,7 @@
"pshufb\t{%2, %0|%0, %2}";
[(set_attr "type" "sselog1")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_insn "*avx_psign<mode>3"
@@ -8733,6 +8913,7 @@
"TARGET_AVX"
"vpsign<ssevecsize>\t{%2, %1, %0|%0, %1, %2}";
[(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -8759,6 +8940,7 @@
"psign<mmxvecsize>\t{%2, %0|%0, %2}";
[(set_attr "type" "sselog1")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_insn "*avx_palignrti"
@@ -8773,6 +8955,8 @@
return "vpalignr\t{%3, %2, %1, %0|%0, %1, %2, %3}";
}
[(set_attr "type" "sseishft")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -8791,6 +8975,7 @@
(set_attr "atom_unit" "sishuf")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "ssse3_palignrdi"
@@ -8807,6 +8992,8 @@
[(set_attr "type" "sseishft")
(set_attr "atom_unit" "sishuf")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
(define_insn "abs<mode>2"
@@ -8826,7 +9013,9 @@
"TARGET_SSSE3"
"pabs<mmxvecsize>\t{%1, %0|%0, %1}";
[(set_attr "type" "sselog1")
+ (set_attr "prefix_rep" "0")
(set_attr "prefix_extra" "1")
+ (set (attr "prefix_rex") (symbol_ref "x86_extended_reg_mentioned_p (insn)"))
(set_attr "mode" "DI")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -8867,6 +9056,7 @@
"extrq\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "sse")
(set_attr "prefix_data16" "1")
+ (set_attr "length_immediate" "2")
(set_attr "mode" "TI")])
(define_insn "sse4a_extrq"
@@ -8890,7 +9080,9 @@
"TARGET_SSE4A"
"insertq\t{%4, %3, %2, %0|%0, %2, %3, %4}"
[(set_attr "type" "sseins")
+ (set_attr "prefix_data16" "0")
(set_attr "prefix_rep" "1")
+ (set_attr "length_immediate" "2")
(set_attr "mode" "TI")])
(define_insn "sse4a_insertq"
@@ -8901,6 +9093,7 @@
"TARGET_SSE4A"
"insertq\t{%2, %0|%0, %2}"
[(set_attr "type" "sseins")
+ (set_attr "prefix_data16" "0")
(set_attr "prefix_rep" "1")
(set_attr "mode" "TI")])
@@ -8919,6 +9112,8 @@
"TARGET_AVX"
"vblendp<avxmodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "ssemov")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<avxvecmode>")])
@@ -8932,6 +9127,8 @@
"TARGET_AVX"
"vblendvp<avxmodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "ssemov")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<avxvecmode>")])
@@ -8944,7 +9141,9 @@
"TARGET_SSE4_1"
"blendp<ssemodesuffixf2c>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "ssemov")
+ (set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<MODE>")])
(define_insn "sse4_1_blendvp<ssemodesuffixf2c>"
@@ -8957,6 +9156,7 @@
"TARGET_SSE4_1"
"blendvp<ssemodesuffixf2c>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "ssemov")
+ (set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "mode" "<MODE>")])
@@ -8971,6 +9171,8 @@
"vdpp<avxmodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "ssemul")
(set_attr "prefix" "vex")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<avxvecmode>")])
(define_insn "sse4_1_dpp<ssemodesuffixf2c>"
@@ -8983,7 +9185,9 @@
"TARGET_SSE4_1"
"dpp<ssemodesuffixf2c>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "ssemul")
+ (set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<MODE>")])
(define_insn "sse4_1_movntdqa"
@@ -9007,6 +9211,8 @@
"vmpsadbw\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "sselog1")
(set_attr "prefix" "vex")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "sse4_1_mpsadbw"
@@ -9019,6 +9225,7 @@
"mpsadbw\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "sselog1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "*avx_packusdw"
@@ -9031,6 +9238,7 @@
"TARGET_AVX"
"vpackusdw\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -9056,6 +9264,8 @@
"TARGET_AVX"
"vpblendvb\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "ssemov")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -9081,6 +9291,8 @@
"vpblendw\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "ssemov")
(set_attr "prefix" "vex")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "sse4_1_pblendw"
@@ -9093,6 +9305,7 @@
"pblendw\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "ssemov")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "sse4_1_phminposuw"
@@ -9504,6 +9717,7 @@
"TARGET_AVX"
"vtestp<avxmodesuffixf2c>\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecomi")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
@@ -9517,6 +9731,7 @@
"TARGET_AVX"
"vptest\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecomi")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
@@ -9541,6 +9756,8 @@
"TARGET_AVX"
"vroundp<avxmodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "ssecvt")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
@@ -9553,7 +9770,9 @@
"TARGET_ROUND"
"%vroundp<ssemodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "ssecvt")
+ (set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<MODE>")])
@@ -9569,6 +9788,8 @@
"TARGET_AVX"
"vrounds<ssemodesuffixf2c>\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "ssecvt")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
@@ -9584,7 +9805,9 @@
"TARGET_ROUND"
"rounds<ssemodesuffixf2c>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "ssecvt")
+ (set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<MODE>")])
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
@@ -9646,6 +9869,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,load")
(set_attr "mode" "TI")])
@@ -9672,6 +9896,7 @@
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
(set_attr "prefix" "maybe_vex")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,load")
(set_attr "mode" "TI")])
@@ -9697,6 +9922,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "memory" "none,load")
(set_attr "mode" "TI")])
@@ -9721,6 +9947,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,load,none,load")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -9769,6 +9996,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,load")
(set_attr "mode" "TI")])
@@ -9790,6 +10018,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "memory" "none,load")
(set_attr "mode" "TI")])
@@ -9812,6 +10041,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "memory" "none,load")
(set_attr "mode" "TI")])
@@ -9834,6 +10064,7 @@
[(set_attr "type" "sselog")
(set_attr "prefix_data16" "1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "memory" "none,load,none,load")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -10832,6 +11063,8 @@
|| register_operand (operands[2], V16QImode))"
"pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
[(set_attr "type" "sseadd")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
(define_insn "sse5_pperm_sign_v16qi_v8hi"
@@ -10846,6 +11079,8 @@
|| register_operand (operands[2], V16QImode))"
"pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
[(set_attr "type" "sseadd")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
(define_insn "sse5_pperm_zero_v8hi_v4si"
@@ -10860,6 +11095,8 @@
|| register_operand (operands[2], V16QImode))"
"pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
[(set_attr "type" "sseadd")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
(define_insn "sse5_pperm_sign_v8hi_v4si"
@@ -10874,6 +11111,8 @@
|| register_operand (operands[2], V16QImode))"
"pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
[(set_attr "type" "sseadd")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
(define_insn "sse5_pperm_zero_v4si_v2di"
@@ -10888,6 +11127,8 @@
|| register_operand (operands[2], V16QImode))"
"pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
[(set_attr "type" "sseadd")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
(define_insn "sse5_pperm_sign_v4si_v2di"
@@ -10902,6 +11143,8 @@
|| register_operand (operands[2], V16QImode))"
"pperm\t{%3, %1, %0, %0|%0, %0, %1, %3}"
[(set_attr "type" "sseadd")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
;; SSE5 pack instructions that combine two vectors into a smaller vector
@@ -11030,6 +11273,7 @@
"TARGET_SSE5"
"prot<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "sse5_rotr<mode>3"
@@ -11043,6 +11287,7 @@
return \"prot<ssevecsize>\t{%3, %1, %0|%0, %1, %3}\";
}
[(set_attr "type" "sseishft")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_expand "vrotr<mode>3"
@@ -11082,6 +11327,8 @@
"TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1, false)"
"prot<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
;; SSE5 packed shift instructions.
@@ -11135,6 +11382,8 @@
"TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1, false)"
"psha<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
(define_insn "sse5_lshl<mode>3"
@@ -11152,6 +11401,8 @@
"TARGET_SSE5 && ix86_sse5_valid_op_p (operands, insn, 3, true, 1, false)"
"pshl<ssevecsize>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sseishft")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
(set_attr "mode" "TI")])
;; SSE2 doesn't have some shift varients, so define versions for SSE5
@@ -11265,7 +11516,6 @@
"TARGET_SSE5"
"frcz<ssemodesuffixf4>\t{%1, %0|%0, %1}"
[(set_attr "type" "ssecvt1")
- (set_attr "prefix_extra" "1")
(set_attr "mode" "<MODE>")])
;; scalar insns
@@ -11280,7 +11530,6 @@
"TARGET_SSE5"
"frcz<ssemodesuffixf2s>\t{%2, %0|%0, %2}"
[(set_attr "type" "ssecvt1")
- (set_attr "prefix_extra" "1")
(set_attr "mode" "<MODE>")])
(define_insn "sse5_cvtph2ps"
@@ -11329,6 +11578,10 @@
"TARGET_SSE5"
"com%Y1<ssemodesuffixf2s>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "sse4arg")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_rep" "0")
+ (set_attr "prefix_extra" "2")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<ssescalarmode>")])
;; We don't have a comparison operator that always returns true/false, so
@@ -11369,6 +11622,10 @@
return ret;
}
[(set_attr "type" "ssecmp")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_rep" "0")
+ (set_attr "prefix_extra" "2")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<MODE>")])
(define_insn "sse5_maskcmp<mode>3"
@@ -11379,6 +11636,10 @@
"TARGET_SSE5"
"com%Y1<ssemodesuffixf4>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "ssecmp")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_rep" "0")
+ (set_attr "prefix_extra" "2")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "<MODE>")])
(define_insn "sse5_maskcmp<mode>3"
@@ -11389,6 +11650,10 @@
"TARGET_SSE5"
"pcom%Y1<ssevecsize>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "sse4arg")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_rep" "0")
+ (set_attr "prefix_extra" "2")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "sse5_maskcmp_uns<mode>3"
@@ -11399,6 +11664,10 @@
"TARGET_SSE5"
"pcom%Y1u<ssevecsize>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "ssecmp")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_rep" "0")
+ (set_attr "prefix_extra" "2")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
;; Version of pcom*u* that is called from the intrinsics that allows pcomequ*
@@ -11414,6 +11683,9 @@
"TARGET_SSE5"
"pcom%Y1u<ssevecsize>\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "ssecmp")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
;; Pcomtrue and pcomfalse support. These are useless instructions, but are
@@ -11432,6 +11704,9 @@
: "pcomfalse<ssevecsize>\t{%2, %1, %0|%0, %1, %2}");
}
[(set_attr "type" "ssecmp")
+ (set_attr "prefix_data16" "0")
+ (set_attr "prefix_extra" "2")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_insn "*avx_aesenc"
@@ -11442,6 +11717,7 @@
"TARGET_AES && TARGET_AVX"
"vaesenc\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -11464,6 +11740,7 @@
"TARGET_AES && TARGET_AVX"
"vaesenclast\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -11486,6 +11763,7 @@
"TARGET_AES && TARGET_AVX"
"vaesdec\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -11508,6 +11786,7 @@
"TARGET_AES && TARGET_AVX"
"vaesdeclast\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -11542,6 +11821,7 @@
"%vaeskeygenassist\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "TI")])
@@ -11554,6 +11834,8 @@
"TARGET_PCLMUL && TARGET_AVX"
"vpclmulqdq\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "TI")])
@@ -11567,6 +11849,7 @@
"pclmulqdq\t{%3, %2, %0|%0, %2, %3}"
[(set_attr "type" "sselog1")
(set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "mode" "TI")])
(define_expand "avx_vzeroall"
@@ -11597,6 +11880,7 @@
"TARGET_AVX"
"vzeroall"
[(set_attr "type" "sse")
+ (set_attr "modrm" "0")
(set_attr "memory" "none")
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
@@ -11615,6 +11899,7 @@
"TARGET_AVX && !TARGET_64BIT"
"vzeroupper"
[(set_attr "type" "sse")
+ (set_attr "modrm" "0")
(set_attr "memory" "none")
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
@@ -11640,6 +11925,7 @@
"TARGET_AVX && TARGET_64BIT"
"vzeroupper"
[(set_attr "type" "sse")
+ (set_attr "modrm" "0")
(set_attr "memory" "none")
(set_attr "prefix" "vex")
(set_attr "mode" "OI")])
@@ -11653,6 +11939,8 @@
"TARGET_AVX"
"vpermilp<avxmodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
@@ -11665,6 +11953,7 @@
"TARGET_AVX"
"vpermilp<avxmodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
@@ -11678,6 +11967,8 @@
"TARGET_AVX"
"vperm2f128\t{%3, %2, %1, %0|%0, %1, %2, %3}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -11693,6 +11984,7 @@
"TARGET_AVX"
"vbroadcasts<avxmodesuffixf2c>\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<avxscalarmode>")])
@@ -11716,6 +12008,7 @@
"TARGET_AVX"
"vbroadcastss\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "SF")])
@@ -11727,6 +12020,7 @@
"TARGET_AVX"
"vbroadcastf128\t{%1, %0|%0, %1}"
[(set_attr "type" "ssemov")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V4SF")])
@@ -11763,6 +12057,8 @@
"TARGET_AVX"
"vinsertf128\t{$0x0, %2, %1, %0|%0, %1, %2, 0x0}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -11776,6 +12072,8 @@
"TARGET_AVX"
"vinsertf128\t{$0x1, %2, %1, %0|%0, %1, %2, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -11790,6 +12088,8 @@
"TARGET_AVX"
"vinsertf128\t{$0x0, %2, %1, %0|%0, %1, %2, 0x0}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -11804,6 +12104,8 @@
"TARGET_AVX"
"vinsertf128\t{$0x1, %2, %1, %0|%0, %1, %2, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -11820,6 +12122,8 @@
"TARGET_AVX"
"vinsertf128\t{$0x0, %2, %1, %0|%0, %1, %2, 0x0}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -11836,6 +12140,8 @@
"TARGET_AVX"
"vinsertf128\t{$0x1, %2, %1, %0|%0, %1, %2, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -11856,6 +12162,8 @@
"TARGET_AVX"
"vinsertf128\t{$0x0, %2, %1, %0|%0, %1, %2, 0x0}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -11876,6 +12184,8 @@
"TARGET_AVX"
"vinsertf128\t{$0x1, %2, %1, %0|%0, %1, %2, 0x1}"
[(set_attr "type" "sselog")
+ (set_attr "prefix_extra" "1")
+ (set_attr "length_immediate" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "V8SF")])
@@ -11889,6 +12199,7 @@
"TARGET_AVX"
"vmaskmovp<avxmodesuffixf2c>\t{%1, %2, %0|%0, %2, %1}"
[(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
@@ -11902,6 +12213,7 @@
"TARGET_AVX"
"vmaskmovp<avxmodesuffixf2c>\t{%2, %1, %0|%0, %1, %2}"
[(set_attr "type" "sselog1")
+ (set_attr "prefix_extra" "1")
(set_attr "prefix" "vex")
(set_attr "mode" "<MODE>")])
@@ -12012,5 +12324,7 @@
}
}
[(set_attr "type" "sselog,ssemov")
+ (set_attr "prefix_extra" "1,*")
+ (set_attr "length_immediate" "1,*")
(set_attr "prefix" "vex")
(set_attr "mode" "<avxvecmode>")])
diff --git a/gcc/config/i386/t-cygming b/gcc/config/i386/t-cygming
index 2cc3a308d8d..4268633b7c8 100644
--- a/gcc/config/i386/t-cygming
+++ b/gcc/config/i386/t-cygming
@@ -31,26 +31,26 @@ LIBGCC2_INCLUDES = -I$(srcdir)/../winsup/w32api/include
winnt.o: $(srcdir)/config/i386/winnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
$(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/winnt.c
winnt-cxx.o: $(srcdir)/config/i386/winnt-cxx.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
$(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/winnt-cxx.c
winnt-stubs.o: $(srcdir)/config/i386/winnt-stubs.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
$(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/winnt-stubs.c
msformat-c.o: $(srcdir)/config/i386/msformat-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
$(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/msformat-c.c
STMP_FIXINC=stmp-fixinc
diff --git a/gcc/config/i386/t-cygwin b/gcc/config/i386/t-cygwin
index 69d61035211..8fec6f761d7 100644
--- a/gcc/config/i386/t-cygwin
+++ b/gcc/config/i386/t-cygwin
@@ -1,5 +1,5 @@
-# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008,
-# 2009 Free Software Foundation, Inc.
+# Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2008, 2009
+# Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -25,12 +25,12 @@ LIBGCC2_INCLUDES += -I$(srcdir)/../winsup/include \
cygwin1.o: $(srcdir)/config/i386/cygwin1.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/cygwin1.c
cygwin2.o: $(srcdir)/config/i386/cygwin2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/cygwin2.c
# Cygwin-specific parts of LIB_SPEC
diff --git a/gcc/config/i386/t-gthr-win32 b/gcc/config/i386/t-gthr-win32
index 204a485bcd1..e3977ce6336 100644
--- a/gcc/config/i386/t-gthr-win32
+++ b/gcc/config/i386/t-gthr-win32
@@ -1,3 +1,3 @@
# We hide calls to w32api needed for w32 thread support here:
-LIB2FUNCS_EXTRA = $(srcdir)/config/i386/gthr-win32.c
-
+LIB2FUNCS_EXTRA = $(srcdir)/config/i386/gthr-win32.c \
+ $(srcdir)/config/i386/mingw-tls.c
diff --git a/gcc/config/i386/t-i386 b/gcc/config/i386/t-i386
index f79c38b8ec7..01e5ce413e4 100644
--- a/gcc/config/i386/t-i386
+++ b/gcc/config/i386/t-i386
@@ -1,4 +1,4 @@
-# Copyright (C) 2008 Free Software Foundation, Inc.
+# Copyright (C) 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -28,4 +28,5 @@ i386-c.o: $(srcdir)/config/i386/i386-c.c \
$(srcdir)/config/i386/i386-protos.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(TREE_H) $(TM_P_H) $(FLAGS_H) $(C_COMMON_H) $(GGC_H) \
$(TARGET_H) $(TARGET_DEF_H) $(CPPLIB_H) $(C_PRAGMA_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/i386-c.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/i386/i386-c.c
diff --git a/gcc/config/i386/t-interix b/gcc/config/i386/t-interix
index d5fff6167b7..9a25831f135 100644
--- a/gcc/config/i386/t-interix
+++ b/gcc/config/i386/t-interix
@@ -4,4 +4,5 @@ LIB1ASMFUNCS = _chkstk
winnt.o: $(srcdir)/config/i386/winnt.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(RTL_H) $(REGS_H) hard-reg-set.h output.h $(TREE_H) flags.h \
$(TM_P_H) toplev.h $(HASHTAB_H) $(GGC_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/winnt.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/i386/winnt.c
diff --git a/gcc/config/i386/t-netware b/gcc/config/i386/t-netware
index 2d3a828a5e5..405c98f6a8d 100644
--- a/gcc/config/i386/t-netware
+++ b/gcc/config/i386/t-netware
@@ -1,7 +1,8 @@
TARGET_LIBGCC2_CFLAGS = -mpreferred-stack-boundary=2 -fomit-frame-pointer
netware.o: $(srcdir)/config/i386/netware.c $(RTL_H) $(TREE_H) $(CONFIG_H) $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/netware.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/i386/netware.c
# We don't need some of GCC's own include files.
USER_H = $(srcdir)/ginclude/stdarg.h \
diff --git a/gcc/config/i386/t-nwld b/gcc/config/i386/t-nwld
index 2c372f12ad7..e7727911636 100644
--- a/gcc/config/i386/t-nwld
+++ b/gcc/config/i386/t-nwld
@@ -1,4 +1,5 @@
-# Copyright (C) 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -39,7 +40,8 @@ $(T)posixpre.def: $(srcdir)/config/i386/t-nwld
echo "check POSIX_CheckUnload" >>$@
nwld.o: $(srcdir)/config/i386/nwld.c $(RTL_H) $(TREE_H) $(CONFIG_H) $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/i386/nwld.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/i386/nwld.c
s-crt0: $(srcdir)/unwind-dw2-fde.h
diff --git a/gcc/config/i386/winnt.c b/gcc/config/i386/winnt.c
index 3d88517c234..812cf798f76 100644
--- a/gcc/config/i386/winnt.c
+++ b/gcc/config/i386/winnt.c
@@ -499,8 +499,11 @@ i386_pe_asm_output_aligned_decl_common (FILE *stream, tree decl,
{
HOST_WIDE_INT rounded;
- /* Compute as in assemble_noswitch_variable, since we don't actually
- support aligned common. */
+ /* Compute as in assemble_noswitch_variable, since we don't have
+ support for aligned common on older binutils. We must also
+ avoid emitting a common symbol of size zero, as this is the
+ overloaded representation that indicates an undefined external
+ symbol in the PE object file format. */
rounded = size ? size : 1;
rounded += (BIGGEST_ALIGNMENT / BITS_PER_UNIT) - 1;
rounded = (rounded / (BIGGEST_ALIGNMENT / BITS_PER_UNIT)
@@ -510,9 +513,13 @@ i386_pe_asm_output_aligned_decl_common (FILE *stream, tree decl,
fprintf (stream, "\t.comm\t");
assemble_name (stream, name);
- fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START
- " " HOST_WIDE_INT_PRINT_DEC "\n",
- rounded, size);
+ if (use_pe_aligned_common)
+ fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC ", %d\n",
+ size ? size : (HOST_WIDE_INT) 1,
+ exact_log2 (align) - exact_log2 (CHAR_BIT));
+ else
+ fprintf (stream, ", " HOST_WIDE_INT_PRINT_DEC "\t" ASM_COMMENT_START
+ " " HOST_WIDE_INT_PRINT_DEC "\n", rounded, size);
}
/* The Microsoft linker requires that every function be marked as
diff --git a/gcc/config/i386/x-cygwin b/gcc/config/i386/x-cygwin
index cfd7758cfb3..752af76ef6a 100644
--- a/gcc/config/i386/x-cygwin
+++ b/gcc/config/i386/x-cygwin
@@ -1,4 +1,4 @@
host-cygwin.o : $(srcdir)/config/i386/host-cygwin.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) toplev.h diagnostic.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/host-cygwin.c
diff --git a/gcc/config/i386/x-darwin b/gcc/config/i386/x-darwin
index 9a3b0f262ce..f0196bac41d 100644
--- a/gcc/config/i386/x-darwin
+++ b/gcc/config/i386/x-darwin
@@ -1,4 +1,4 @@
host-i386-darwin.o : $(srcdir)/config/i386/host-i386-darwin.c \
$(CONFIG_H) $(SYSTEM_H) coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) \
config/host-darwin.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/i386/x-i386 b/gcc/config/i386/x-i386
index 9f03de4535e..2bf8fed5db5 100644
--- a/gcc/config/i386/x-i386
+++ b/gcc/config/i386/x-i386
@@ -1,4 +1,4 @@
driver-i386.o : $(srcdir)/config/i386/driver-i386.c \
$(srcdir)/config/i386/cpuid.h \
$(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/i386/x-mingw32 b/gcc/config/i386/x-mingw32
index 5023e06cdcd..2a1ca47c7c4 100644
--- a/gcc/config/i386/x-mingw32
+++ b/gcc/config/i386/x-mingw32
@@ -27,5 +27,5 @@ WERROR_FLAGS += -Wno-format
host-mingw32.o : $(srcdir)/config/i386/host-mingw32.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h hosthooks.h hosthooks-def.h toplev.h $(DIAGNOSTIC_H) $(HOOKS_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/i386/host-mingw32.c
diff --git a/gcc/config/ia64/div.md b/gcc/config/ia64/div.md
index 583e9e3dbee..f443a28e7ec 100644
--- a/gcc/config/ia64/div.md
+++ b/gcc/config/ia64/div.md
@@ -222,6 +222,32 @@
operands[2] = gen_rtx_REG (<MODE>mode, REGNO (operands[1]));
})
+;; Float to integer truncations using an alternative status register.
+
+(define_insn "fix_truncrfdi2_alts"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (fix:DI (match_operand:RF 1 "fr_register_operand" "f")))
+ (use (match_operand:SI 2 "const_int_operand" ""))]
+ ""
+ "fcvt.fx.trunc.s%2 %0 = %1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "fixuns_truncrfdi2_alts"
+ [(set (match_operand:DI 0 "fr_register_operand" "=f")
+ (unsigned_fix:DI (match_operand:RF 1 "fr_register_operand" "f")))
+ (use (match_operand:SI 2 "const_int_operand" ""))]
+ ""
+ "fcvt.fxu.trunc.s%2 %0 = %1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
+(define_insn "setf_exp_rf"
+ [(set (match_operand:RF 0 "fr_register_operand" "=f")
+ (unspec:RF [(match_operand:DI 1 "register_operand" "r")]
+ UNSPEC_SETF_EXP))]
+ ""
+ "setf.exp %0 = %1"
+ [(set_attr "itanium_class" "frfr")])
+
;; Reciprocal approximation
(define_insn "recip_approx_rf"
@@ -237,6 +263,23 @@
[(set_attr "itanium_class" "fmisc")
(set_attr "predicable" "no")])
+;; Single precision floating point division
+
+(define_expand "divsf3"
+ [(set (match_operand:SF 0 "fr_register_operand" "")
+ (div:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "")
+ (match_operand:SF 2 "fr_reg_or_fp01_operand" "")))]
+ "TARGET_INLINE_FLOAT_DIV"
+{
+ rtx insn;
+ if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
+ insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
+ else
+ insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
+ emit_insn (insn);
+ DONE;
+})
+
;; Single precision floating point division (maximum throughput algorithm).
(define_expand "divsf3_internal_thr"
@@ -334,6 +377,22 @@
DONE;
})
+;; Double precision floating point division
+
+(define_expand "divdf3"
+ [(set (match_operand:DF 0 "fr_register_operand" "")
+ (div:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "")
+ (match_operand:DF 2 "fr_reg_or_fp01_operand" "")))]
+ "TARGET_INLINE_FLOAT_DIV"
+{
+ rtx insn;
+ if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
+ insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
+ else
+ insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
+ emit_insn (insn);
+ DONE;
+})
;; Double precision floating point division (maximum throughput algorithm).
@@ -454,7 +513,7 @@
;; Extended precision floating point division.
-(define_expand "divxf3_internal"
+(define_expand "divxf3"
[(set (match_operand:XF 0 "fr_register_operand" "")
(div:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "")
(match_operand:XF 2 "fr_reg_or_fp01_operand" "")))]
@@ -520,6 +579,340 @@
})
+;; Integer division operations
+
+(define_expand "divsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (div:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx op1_rf, op2_rf, op0_rf, op0_di;
+
+ op0_rf = gen_reg_rtx (RFmode);
+ op0_di = gen_reg_rtx (DImode);
+
+ if (! register_operand (operands[1], SImode))
+ operands[1] = force_reg (SImode, operands[1]);
+ op1_rf = gen_reg_rtx (RFmode);
+ expand_float (op1_rf, operands[1], 0);
+
+ if (! register_operand (operands[2], SImode))
+ operands[2] = force_reg (SImode, operands[2]);
+ op2_rf = gen_reg_rtx (RFmode);
+ expand_float (op2_rf, operands[2], 0);
+
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
+ CONST1_RTX (SImode)));
+
+ emit_insn (gen_divsi3_internal (op0_rf, op1_rf, op2_rf));
+
+ emit_insn (gen_fix_truncrfdi2_alts (op0_di, op0_rf, const1_rtx));
+ emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
+ DONE;
+})
+
+(define_expand "modsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (mod:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx op2_neg, op1_di, div;
+
+ div = gen_reg_rtx (SImode);
+ emit_insn (gen_divsi3 (div, operands[1], operands[2]));
+
+ op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
+
+ /* This is a trick to get us to reuse the value that we're sure to
+ have already copied to the FP regs. */
+ op1_di = gen_reg_rtx (DImode);
+ convert_move (op1_di, operands[1], 0);
+
+ emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
+ gen_lowpart (SImode, op1_di)));
+ DONE;
+})
+
+(define_expand "udivsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (udiv:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx op1_rf, op2_rf, op0_rf, op0_di;
+
+ op0_rf = gen_reg_rtx (RFmode);
+ op0_di = gen_reg_rtx (DImode);
+
+ if (! register_operand (operands[1], SImode))
+ operands[1] = force_reg (SImode, operands[1]);
+ op1_rf = gen_reg_rtx (RFmode);
+ expand_float (op1_rf, operands[1], 1);
+
+ if (! register_operand (operands[2], SImode))
+ operands[2] = force_reg (SImode, operands[2]);
+ op2_rf = gen_reg_rtx (RFmode);
+ expand_float (op2_rf, operands[2], 1);
+
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
+ CONST1_RTX (SImode)));
+
+ emit_insn (gen_divsi3_internal (op0_rf, op1_rf, op2_rf));
+
+ emit_insn (gen_fixuns_truncrfdi2_alts (op0_di, op0_rf, const1_rtx));
+ emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
+ DONE;
+})
+
+(define_expand "umodsi3"
+ [(set (match_operand:SI 0 "register_operand" "")
+ (umod:SI (match_operand:SI 1 "general_operand" "")
+ (match_operand:SI 2 "general_operand" "")))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx op2_neg, op1_di, div;
+
+ div = gen_reg_rtx (SImode);
+ emit_insn (gen_udivsi3 (div, operands[1], operands[2]));
+
+ op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
+
+ /* This is a trick to get us to reuse the value that we're sure to
+ have already copied to the FP regs. */
+ op1_di = gen_reg_rtx (DImode);
+ convert_move (op1_di, operands[1], 1);
+
+ emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
+ gen_lowpart (SImode, op1_di)));
+ DONE;
+})
+
+(define_expand "divsi3_internal"
+ [(set (match_operand:RF 0 "fr_register_operand" "")
+ (float:RF (div:SI (match_operand:RF 1 "fr_register_operand" "")
+ (match_operand:RF 2 "fr_register_operand" ""))))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx a = operands[1];
+ rtx b = operands[2];
+ rtx y = gen_reg_rtx (RFmode);
+ rtx e = gen_reg_rtx (RFmode);
+ rtx e1 = gen_reg_rtx (RFmode);
+ rtx q = gen_reg_rtx (RFmode);
+ rtx q1 = gen_reg_rtx (RFmode);
+ rtx cond = gen_reg_rtx (BImode);
+ rtx zero = CONST0_RTX (RFmode);
+ rtx one = CONST1_RTX (RFmode);
+ rtx status1 = CONST1_RTX (SImode);
+ rtx trunc_off = CONST2_RTX (SImode);
+ rtx twon34_exp = gen_reg_rtx (DImode);
+ rtx twon34 = gen_reg_rtx (RFmode);
+
+ /* Load cosntant 2**(-34) */
+ emit_move_insn (twon34_exp, GEN_INT (65501));
+ emit_insn (gen_setf_exp_rf (twon34, twon34_exp));
+
+ /* y = 1 / b */
+ emit_insn (gen_recip_approx_rf (y, a, b, cond, status1));
+ /* e = 1 - (b * y) */
+ emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
+ /* q = a * y */
+ emit_insn (gen_mulrf3_cond (q, cond, a, y, zero, status1, trunc_off));
+ /* q1 = q + (q * e) */
+ emit_insn (gen_m2addrf4_cond (q1, cond, q, q, e, zero, status1, trunc_off));
+ /* e1 = (2**-34) + (e * e) */
+ emit_insn (gen_m2addrf4_cond (e1, cond, twon34, e, e, zero, status1, trunc_off));
+ /* q2 = q1 + (e1 * q1) */
+ emit_insn (gen_m2addrf4_cond (operands[0], cond, q1, e1, q1, y, status1, trunc_off));
+ DONE;
+})
+
+(define_expand "divdi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (div:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx op1_rf, op2_rf, op0_rf;
+
+ op0_rf = gen_reg_rtx (RFmode);
+
+ if (! register_operand (operands[1], DImode))
+ operands[1] = force_reg (DImode, operands[1]);
+ op1_rf = gen_reg_rtx (RFmode);
+ expand_float (op1_rf, operands[1], 0);
+
+ if (! register_operand (operands[2], DImode))
+ operands[2] = force_reg (DImode, operands[2]);
+ op2_rf = gen_reg_rtx (RFmode);
+ expand_float (op2_rf, operands[2], 0);
+
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
+ CONST1_RTX (DImode)));
+
+ if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
+ emit_insn (gen_divdi3_internal_lat (op0_rf, op1_rf, op2_rf));
+ else
+ emit_insn (gen_divdi3_internal_thr (op0_rf, op1_rf, op2_rf));
+
+ emit_insn (gen_fix_truncrfdi2_alts (operands[0], op0_rf, const1_rtx));
+ DONE;
+})
+
+(define_expand "moddi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (mod:SI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx op2_neg, div;
+
+ div = gen_reg_rtx (DImode);
+ emit_insn (gen_divdi3 (div, operands[1], operands[2]));
+
+ op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
+
+ emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
+ DONE;
+})
+
+(define_expand "udivdi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (udiv:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx op1_rf, op2_rf, op0_rf;
+
+ op0_rf = gen_reg_rtx (RFmode);
+
+ if (! register_operand (operands[1], DImode))
+ operands[1] = force_reg (DImode, operands[1]);
+ op1_rf = gen_reg_rtx (RFmode);
+ expand_float (op1_rf, operands[1], 1);
+
+ if (! register_operand (operands[2], DImode))
+ operands[2] = force_reg (DImode, operands[2]);
+ op2_rf = gen_reg_rtx (RFmode);
+ expand_float (op2_rf, operands[2], 1);
+
+ emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
+ CONST1_RTX (DImode)));
+
+ if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
+ emit_insn (gen_divdi3_internal_lat (op0_rf, op1_rf, op2_rf));
+ else
+ emit_insn (gen_divdi3_internal_thr (op0_rf, op1_rf, op2_rf));
+
+ emit_insn (gen_fixuns_truncrfdi2_alts (operands[0], op0_rf, const1_rtx));
+ DONE;
+})
+
+(define_expand "umoddi3"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (umod:DI (match_operand:DI 1 "general_operand" "")
+ (match_operand:DI 2 "general_operand" "")))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx op2_neg, div;
+
+ div = gen_reg_rtx (DImode);
+ emit_insn (gen_udivdi3 (div, operands[1], operands[2]));
+
+ op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
+
+ emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
+ DONE;
+})
+
+(define_expand "divdi3_internal_lat"
+ [(set (match_operand:RF 0 "fr_register_operand" "")
+ (float:RF (div:DI (match_operand:RF 1 "fr_register_operand" "")
+ (match_operand:RF 2 "fr_register_operand" ""))))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx a = operands[1];
+ rtx b = operands[2];
+ rtx y = gen_reg_rtx (RFmode);
+ rtx y1 = gen_reg_rtx (RFmode);
+ rtx y2 = gen_reg_rtx (RFmode);
+ rtx e = gen_reg_rtx (RFmode);
+ rtx e1 = gen_reg_rtx (RFmode);
+ rtx q = gen_reg_rtx (RFmode);
+ rtx q1 = gen_reg_rtx (RFmode);
+ rtx q2 = gen_reg_rtx (RFmode);
+ rtx r = gen_reg_rtx (RFmode);
+ rtx cond = gen_reg_rtx (BImode);
+ rtx zero = CONST0_RTX (RFmode);
+ rtx one = CONST1_RTX (RFmode);
+ rtx status1 = CONST1_RTX (SImode);
+ rtx trunc_off = CONST2_RTX (SImode);
+
+ /* y = 1 / b */
+ emit_insn (gen_recip_approx_rf (y, a, b, cond, status1));
+ /* e = 1 - (b * y) */
+ emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
+ /* q = a * y */
+ emit_insn (gen_mulrf3_cond (q, cond, a, y, zero, status1, trunc_off));
+ /* q1 = q + (q * e) */
+ emit_insn (gen_m2addrf4_cond (q1, cond, q, q, e, zero, status1, trunc_off));
+ /* e1 = e * e */
+ emit_insn (gen_mulrf3_cond (e1, cond, e, e, zero, status1, trunc_off));
+ /* q2 = q1 + (e1 * q1) */
+ emit_insn (gen_m2addrf4_cond (q2, cond, q1, e1, q1, zero, status1, trunc_off));
+ /* y1 = y + (y * e) */
+ emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e, zero, status1, trunc_off));
+ /* r = a - (b * q2) */
+ emit_insn (gen_m2subrf4_cond (r, cond, a, b, q2, zero, status1, trunc_off));
+ /* y2 = y1 + (y1 * e1) */
+ emit_insn (gen_m2addrf4_cond (y2, cond, y1, y1, e1, zero, status1, trunc_off));
+ /* q3 = q2 + (r * y2) */
+ emit_insn (gen_m2addrf4_cond (operands[0], cond, q2, r, y2, y, status1, trunc_off));
+ DONE;
+})
+
+(define_expand "divdi3_internal_thr"
+ [(set (match_operand:RF 0 "fr_register_operand" "")
+ (float:RF (div:DI (match_operand:RF 1 "fr_register_operand" "")
+ (match_operand:RF 2 "fr_register_operand" ""))))]
+ "TARGET_INLINE_INT_DIV"
+{
+ rtx a = operands[1];
+ rtx b = operands[2];
+ rtx y = gen_reg_rtx (RFmode);
+ rtx y1 = gen_reg_rtx (RFmode);
+ rtx y2 = gen_reg_rtx (RFmode);
+ rtx e = gen_reg_rtx (RFmode);
+ rtx e1 = gen_reg_rtx (RFmode);
+ rtx q2 = gen_reg_rtx (RFmode);
+ rtx r = gen_reg_rtx (RFmode);
+ rtx cond = gen_reg_rtx (BImode);
+ rtx zero = CONST0_RTX (RFmode);
+ rtx one = CONST1_RTX (RFmode);
+ rtx status1 = CONST1_RTX (SImode);
+ rtx trunc_off = CONST2_RTX (SImode);
+
+ /* y = 1 / b */
+ emit_insn (gen_recip_approx_rf (y, a, b, cond, status1));
+ /* e = 1 - (b * y) */
+ emit_insn (gen_m2subrf4_cond (e, cond, one, b, y, zero, status1, trunc_off));
+ /* y1 = y + (y * e) */
+ emit_insn (gen_m2addrf4_cond (y1, cond, y, y, e, zero, status1, trunc_off));
+ /* e1 = e * e */
+ emit_insn (gen_mulrf3_cond (e1, cond, e, e, zero, status1, trunc_off));
+ /* y2 = y1 + (y1 * e1) */
+ emit_insn (gen_m2addrf4_cond (y2, cond, y1, y1, e1, zero, status1, trunc_off));
+ /* q2 = y2 * a */
+ emit_insn (gen_mulrf3_cond (q2, cond, y2, a, zero, status1, trunc_off));
+ /* r = a - (b * q2) */
+ emit_insn (gen_m2subrf4_cond (r, cond, a, b, q2, zero, status1, trunc_off));
+ /* q3 = q2 + (r * y2) */
+ emit_insn (gen_m2addrf4_cond (operands[0], cond, q2, r, y2, y, status1, trunc_off));
+ DONE;
+})
+
;; SQRT operations
@@ -535,6 +928,20 @@
[(set_attr "itanium_class" "fmisc")
(set_attr "predicable" "no")])
+(define_expand "sqrtsf2"
+ [(set (match_operand:SF 0 "fr_register_operand" "=&f")
+ (sqrt:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
+ "TARGET_INLINE_SQRT"
+{
+ rtx insn;
+ if (TARGET_INLINE_SQRT == INL_MIN_LAT)
+ insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]);
+ else
+ insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
+ emit_insn (insn);
+ DONE;
+})
+
(define_expand "sqrtsf2_internal_thr"
[(set (match_operand:SF 0 "fr_register_operand" "")
(sqrt:SF (match_operand:SF 1 "fr_register_operand" "")))]
@@ -662,6 +1069,22 @@
DONE;
})
+(define_expand "sqrtdf2"
+ [(set (match_operand:DF 0 "fr_register_operand" "=&f")
+ (sqrt:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
+ "TARGET_INLINE_SQRT"
+{
+ rtx insn;
+#if 0
+ if (TARGET_INLINE_SQRT == INL_MIN_LAT)
+ insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]);
+ else
+#endif
+ insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
+ emit_insn (insn);
+ DONE;
+})
+
(define_expand "sqrtdf2_internal_thr"
[(set (match_operand:DF 0 "fr_register_operand" "")
(sqrt:DF (match_operand:DF 1 "fr_register_operand" "")))]
@@ -727,7 +1150,7 @@
DONE;
})
-(define_expand "sqrtxf2_internal"
+(define_expand "sqrtxf2"
[(set (match_operand:XF 0 "fr_register_operand" "")
(sqrt:XF (match_operand:XF 1 "fr_register_operand" "")))]
"TARGET_INLINE_SQRT"
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index d20ae6948cf..f9c6de2dbe4 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -1234,6 +1234,13 @@
;; Convert between signed integer types and floating point.
+(define_insn "floatdirf2"
+ [(set (match_operand:RF 0 "fr_register_operand" "=f")
+ (float:RF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.xf %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
(define_insn "floatdixf2"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(float:XF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
@@ -1262,12 +1269,11 @@
"fcvt.fx.trunc %0 = %F1"
[(set_attr "itanium_class" "fcvtfx")])
-(define_insn "fix_truncxfdi2_alts"
+(define_insn "fix_truncrfdi2"
[(set (match_operand:DI 0 "fr_register_operand" "=f")
- (fix:DI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))
- (use (match_operand:SI 2 "const_int_operand" ""))]
+ (fix:DI (match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")))]
""
- "fcvt.fx.trunc.s%2 %0 = %F1"
+ "fcvt.fx.trunc %0 = %F1"
[(set_attr "itanium_class" "fcvtfx")])
;; Convert between unsigned integer types and floating point.
@@ -1293,6 +1299,13 @@
"fcvt.xuf %0 = %F1"
[(set_attr "itanium_class" "fcvtfx")])
+(define_insn "floatunsdirf2"
+ [(set (match_operand:RF 0 "fr_register_operand" "=f")
+ (unsigned_float:RF (match_operand:DI 1 "fr_reg_or_fp01_operand" "fG")))]
+ ""
+ "fcvt.xuf %0 = %F1"
+ [(set_attr "itanium_class" "fcvtfx")])
+
(define_insn "fixuns_truncsfdi2"
[(set (match_operand:DI 0 "fr_register_operand" "=f")
(unsigned_fix:DI (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
@@ -1314,12 +1327,11 @@
"fcvt.fxu.trunc %0 = %F1"
[(set_attr "itanium_class" "fcvtfx")])
-(define_insn "fixuns_truncxfdi2_alts"
+(define_insn "fixuns_truncrfdi2"
[(set (match_operand:DI 0 "fr_register_operand" "=f")
- (unsigned_fix:DI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))
- (use (match_operand:SI 2 "const_int_operand" ""))]
+ (unsigned_fix:DI (match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")))]
""
- "fcvt.fxu.trunc.s%2 %0 = %F1"
+ "fcvt.fxu.trunc %0 = %F1"
[(set_attr "itanium_class" "fcvtfx")])
;; ::::::::::::::::::::
@@ -2176,169 +2188,6 @@
(match_dup 1) (match_dup 2)))]
""
{ operands[3] = gen_reg_rtx (BImode); })
-
-(define_expand "divsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (div:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
- "TARGET_INLINE_INT_DIV"
-{
- rtx op1_xf, op2_xf, op0_xf, op0_di, twon34, twon34_exp;
-
- op0_xf = gen_reg_rtx (XFmode);
- op0_di = gen_reg_rtx (DImode);
-
- if (CONSTANT_P (operands[1]))
- operands[1] = force_reg (SImode, operands[1]);
- op1_xf = gen_reg_rtx (XFmode);
- expand_float (op1_xf, operands[1], 0);
-
- if (CONSTANT_P (operands[2]))
- operands[2] = force_reg (SImode, operands[2]);
- op2_xf = gen_reg_rtx (XFmode);
- expand_float (op2_xf, operands[2], 0);
-
- /* 2^-34 */
- twon34_exp = gen_reg_rtx (DImode);
- emit_move_insn (twon34_exp, GEN_INT (65501));
- twon34 = gen_reg_rtx (XFmode);
- emit_insn (gen_setf_exp_xf (twon34, twon34_exp));
-
- emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
- CONST1_RTX (SImode)));
-
- emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34));
-
- emit_insn (gen_fix_truncxfdi2_alts (op0_di, op0_xf, const1_rtx));
- emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
- DONE;
-})
-
-(define_expand "modsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (mod:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
- "TARGET_INLINE_INT_DIV"
-{
- rtx op2_neg, op1_di, div;
-
- div = gen_reg_rtx (SImode);
- emit_insn (gen_divsi3 (div, operands[1], operands[2]));
-
- op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
-
- /* This is a trick to get us to reuse the value that we're sure to
- have already copied to the FP regs. */
- op1_di = gen_reg_rtx (DImode);
- convert_move (op1_di, operands[1], 0);
-
- emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
- gen_lowpart (SImode, op1_di)));
- DONE;
-})
-
-(define_expand "udivsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (udiv:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
- "TARGET_INLINE_INT_DIV"
-{
- rtx op1_xf, op2_xf, op0_xf, op0_di, twon34, twon34_exp;
-
- op0_xf = gen_reg_rtx (XFmode);
- op0_di = gen_reg_rtx (DImode);
-
- if (CONSTANT_P (operands[1]))
- operands[1] = force_reg (SImode, operands[1]);
- op1_xf = gen_reg_rtx (XFmode);
- expand_float (op1_xf, operands[1], 1);
-
- if (CONSTANT_P (operands[2]))
- operands[2] = force_reg (SImode, operands[2]);
- op2_xf = gen_reg_rtx (XFmode);
- expand_float (op2_xf, operands[2], 1);
-
- /* 2^-34 */
- twon34_exp = gen_reg_rtx (DImode);
- emit_move_insn (twon34_exp, GEN_INT (65501));
- twon34 = gen_reg_rtx (XFmode);
- emit_insn (gen_setf_exp_xf (twon34, twon34_exp));
-
- emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (SImode),
- CONST1_RTX (SImode)));
-
- emit_insn (gen_divsi3_internal (op0_xf, op1_xf, op2_xf, twon34));
-
- emit_insn (gen_fixuns_truncxfdi2_alts (op0_di, op0_xf, const1_rtx));
- emit_move_insn (operands[0], gen_lowpart (SImode, op0_di));
- DONE;
-})
-
-(define_expand "umodsi3"
- [(set (match_operand:SI 0 "register_operand" "")
- (umod:SI (match_operand:SI 1 "general_operand" "")
- (match_operand:SI 2 "general_operand" "")))]
- "TARGET_INLINE_INT_DIV"
-{
- rtx op2_neg, op1_di, div;
-
- div = gen_reg_rtx (SImode);
- emit_insn (gen_udivsi3 (div, operands[1], operands[2]));
-
- op2_neg = expand_unop (SImode, neg_optab, operands[2], NULL_RTX, 0);
-
- /* This is a trick to get us to reuse the value that we're sure to
- have already copied to the FP regs. */
- op1_di = gen_reg_rtx (DImode);
- convert_move (op1_di, operands[1], 1);
-
- emit_insn (gen_maddsi4 (operands[0], div, op2_neg,
- gen_lowpart (SImode, op1_di)));
- DONE;
-})
-
-(define_insn_and_split "divsi3_internal"
- [(set (match_operand:XF 0 "fr_register_operand" "=&f")
- (float:XF (div:SI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG"))))
- (clobber (match_scratch:XF 4 "=&f"))
- (clobber (match_scratch:XF 5 "=&f"))
- (clobber (match_scratch:BI 6 "=c"))
- (use (match_operand:XF 3 "fr_register_operand" "f"))]
- "TARGET_INLINE_INT_DIV"
- "#"
- "&& reload_completed"
- [(parallel [(set (match_dup 0) (unspec:XF [(const_int 1) (match_dup 2)]
- UNSPEC_FR_RECIP_APPROX_RES))
- (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)]
- UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 5)
- (minus:XF (match_dup 7)
- (mult:XF (match_dup 2) (match_dup 0))))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4)
- (plus:XF (mult:XF (match_dup 5) (match_dup 4))
- (match_dup 4)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 5)
- (plus:XF (mult:XF (match_dup 5) (match_dup 5))
- (match_dup 3)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 0)
- (plus:XF (mult:XF (match_dup 5) (match_dup 4))
- (match_dup 4)))
- (use (const_int 1))]))
- ]
- "operands[7] = CONST1_RTX (XFmode);"
- [(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
@@ -2612,215 +2461,6 @@
""
"getf.exp %0 = %F1"
[(set_attr "itanium_class" "frfr")])
-
-(define_expand "divdi3"
- [(set (match_operand:DI 0 "register_operand" "")
- (div:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:DI 2 "general_operand" "")))]
- "TARGET_INLINE_INT_DIV"
-{
- rtx op1_xf, op2_xf, op0_xf;
-
- op0_xf = gen_reg_rtx (XFmode);
-
- if (CONSTANT_P (operands[1]))
- operands[1] = force_reg (DImode, operands[1]);
- op1_xf = gen_reg_rtx (XFmode);
- expand_float (op1_xf, operands[1], 0);
-
- if (CONSTANT_P (operands[2]))
- operands[2] = force_reg (DImode, operands[2]);
- op2_xf = gen_reg_rtx (XFmode);
- expand_float (op2_xf, operands[2], 0);
-
- emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
- CONST1_RTX (DImode)));
-
- if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
- emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf));
- else
- emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf));
-
- emit_insn (gen_fix_truncxfdi2_alts (operands[0], op0_xf, const1_rtx));
- DONE;
-})
-
-(define_expand "moddi3"
- [(set (match_operand:DI 0 "register_operand" "")
- (mod:SI (match_operand:DI 1 "general_operand" "")
- (match_operand:DI 2 "general_operand" "")))]
- "TARGET_INLINE_INT_DIV"
-{
- rtx op2_neg, div;
-
- div = gen_reg_rtx (DImode);
- emit_insn (gen_divdi3 (div, operands[1], operands[2]));
-
- op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
-
- emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
- DONE;
-})
-
-(define_expand "udivdi3"
- [(set (match_operand:DI 0 "register_operand" "")
- (udiv:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:DI 2 "general_operand" "")))]
- "TARGET_INLINE_INT_DIV"
-{
- rtx op1_xf, op2_xf, op0_xf;
-
- op0_xf = gen_reg_rtx (XFmode);
-
- if (CONSTANT_P (operands[1]))
- operands[1] = force_reg (DImode, operands[1]);
- op1_xf = gen_reg_rtx (XFmode);
- expand_float (op1_xf, operands[1], 1);
-
- if (CONSTANT_P (operands[2]))
- operands[2] = force_reg (DImode, operands[2]);
- op2_xf = gen_reg_rtx (XFmode);
- expand_float (op2_xf, operands[2], 1);
-
- emit_insn (gen_cond_trap (EQ, operands[2], CONST0_RTX (DImode),
- CONST1_RTX (DImode)));
-
- if (TARGET_INLINE_INT_DIV == INL_MIN_LAT)
- emit_insn (gen_divdi3_internal_lat (op0_xf, op1_xf, op2_xf));
- else
- emit_insn (gen_divdi3_internal_thr (op0_xf, op1_xf, op2_xf));
-
- emit_insn (gen_fixuns_truncxfdi2_alts (operands[0], op0_xf, const1_rtx));
- DONE;
-})
-
-(define_expand "umoddi3"
- [(set (match_operand:DI 0 "register_operand" "")
- (umod:DI (match_operand:DI 1 "general_operand" "")
- (match_operand:DI 2 "general_operand" "")))]
- "TARGET_INLINE_INT_DIV"
-{
- rtx op2_neg, div;
-
- div = gen_reg_rtx (DImode);
- emit_insn (gen_udivdi3 (div, operands[1], operands[2]));
-
- op2_neg = expand_unop (DImode, neg_optab, operands[2], NULL_RTX, 0);
-
- emit_insn (gen_madddi4 (operands[0], div, op2_neg, operands[1]));
- DONE;
-})
-
-(define_insn_and_split "divdi3_internal_lat"
- [(set (match_operand:XF 0 "fr_register_operand" "=&f")
- (float:XF (div:SI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG"))))
- (clobber (match_scratch:XF 3 "=&f"))
- (clobber (match_scratch:XF 4 "=&f"))
- (clobber (match_scratch:XF 5 "=&f"))
- (clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_INT_DIV == INL_MIN_LAT"
- "#"
- "&& reload_completed"
- [(parallel [(set (match_dup 0) (unspec:XF [(const_int 1) (match_dup 2)]
- UNSPEC_FR_RECIP_APPROX_RES))
- (set (match_dup 6) (unspec:BI [(match_dup 1) (match_dup 2)]
- UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 3)
- (minus:XF (match_dup 7)
- (mult:XF (match_dup 2) (match_dup 0))))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4) (mult:XF (match_dup 1) (match_dup 0)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 5) (mult:XF (match_dup 3) (match_dup 3)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4)
- (plus:XF (mult:XF (match_dup 3) (match_dup 4))
- (match_dup 4)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 0)
- (plus:XF (mult:XF (match_dup 3) (match_dup 0))
- (match_dup 0)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 3)
- (plus:XF (mult:XF (match_dup 5) (match_dup 4))
- (match_dup 4)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 0)
- (plus:XF (mult:XF (match_dup 5) (match_dup 0))
- (match_dup 0)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4)
- (minus:XF (match_dup 1)
- (mult:XF (match_dup 2) (match_dup 3))))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 0)
- (plus:XF (mult:XF (match_dup 4) (match_dup 0))
- (match_dup 3)))
- (use (const_int 1))]))
- ]
- "operands[7] = CONST1_RTX (XFmode);"
- [(set_attr "predicable" "no")])
-
-(define_insn_and_split "divdi3_internal_thr"
- [(set (match_operand:XF 0 "fr_register_operand" "=&f")
- (float:XF (div:SI (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:XF 2 "fr_reg_or_fp01_operand" "fG"))))
- (clobber (match_scratch:XF 3 "=&f"))
- (clobber (match_scratch:XF 4 "=f"))
- (clobber (match_scratch:BI 5 "=c"))]
- "TARGET_INLINE_INT_DIV == INL_MAX_THR"
- "#"
- "&& reload_completed"
- [(parallel [(set (match_dup 0) (unspec:XF [(const_int 1) (match_dup 2)]
- UNSPEC_FR_RECIP_APPROX_RES))
- (set (match_dup 5) (unspec:BI [(match_dup 1) (match_dup 2)]
- UNSPEC_FR_RECIP_APPROX))
- (use (const_int 1))])
- (cond_exec (ne (match_dup 5) (const_int 0))
- (parallel [(set (match_dup 3)
- (minus:XF (match_dup 6)
- (mult:XF (match_dup 2) (match_dup 0))))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 5) (const_int 0))
- (parallel [(set (match_dup 0)
- (plus:XF (mult:XF (match_dup 3) (match_dup 0))
- (match_dup 0)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 5) (const_int 0))
- (parallel [(set (match_dup 3) (mult:XF (match_dup 3) (match_dup 3)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 5) (const_int 0))
- (parallel [(set (match_dup 0)
- (plus:XF (mult:XF (match_dup 3) (match_dup 0))
- (match_dup 0)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 5) (const_int 0))
- (parallel [(set (match_dup 3) (mult:XF (match_dup 0) (match_dup 1)))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 5) (const_int 0))
- (parallel [(set (match_dup 4)
- (minus:XF (match_dup 1)
- (mult:XF (match_dup 2) (match_dup 3))))
- (use (const_int 1))]))
- (cond_exec (ne (match_dup 5) (const_int 0))
- (parallel [(set (match_dup 0)
- (plus:XF (mult:XF (match_dup 4) (match_dup 0))
- (match_dup 3)))
- (use (const_int 1))]))
- ]
- "operands[6] = CONST1_RTX (XFmode);"
- [(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
@@ -3135,56 +2775,6 @@
"TARGET_FUSED_MADD"
"fnma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
-
-(define_insn "*nmaddsf4_alts"
- [(set (match_operand:SF 0 "fr_register_operand" "=f")
- (minus:SF (match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")
- (mult:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:SF 2 "fr_reg_or_fp01_operand" "fG"))))
- (use (match_operand:SI 4 "const_int_operand" ""))]
- ""
- "fnma.s.s%4 %0 = %F1, %F2, %F3"
- [(set_attr "itanium_class" "fmac")])
-
-(define_expand "divsf3"
- [(set (match_operand:SF 0 "fr_register_operand" "")
- (div:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "")
- (match_operand:SF 2 "fr_reg_or_fp01_operand" "")))]
- "TARGET_INLINE_FLOAT_DIV"
-{
- rtx insn;
- if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
- insn = gen_divsf3_internal_lat (operands[0], operands[1], operands[2]);
- else
- insn = gen_divsf3_internal_thr (operands[0], operands[1], operands[2]);
- emit_insn (insn);
- DONE;
-})
-
-(define_insn "setf_exp_xf"
- [(set (match_operand:XF 0 "fr_register_operand" "=f")
- (unspec:XF [(match_operand:DI 1 "register_operand" "r")]
- UNSPEC_SETF_EXP))]
- ""
- "setf.exp %0 = %1"
- [(set_attr "itanium_class" "frfr")])
-
-
-;; Inline square root.
-
-(define_expand "sqrtsf2"
- [(set (match_operand:SF 0 "fr_register_operand" "=&f")
- (sqrt:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))]
- "TARGET_INLINE_SQRT"
-{
- rtx insn;
- if (TARGET_INLINE_SQRT == INL_MIN_LAT)
- insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]);
- else
- insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
- emit_insn (insn);
- DONE;
-})
;; ::::::::::::::::::::
;; ::
@@ -3362,16 +2952,6 @@
"fnma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
-(define_insn "*nmadddf4_alts"
- [(set (match_operand:DF 0 "fr_register_operand" "=f")
- (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
- (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))))
- (use (match_operand:SI 4 "const_int_operand" ""))]
- ""
- "fnma.d.s%4 %0 = %F1, %F2, %F3"
- [(set_attr "itanium_class" "fmac")])
-
(define_insn "*nmadddf4_truncsf"
[(set (match_operand:SF 0 "fr_register_operand" "=f")
(float_truncate:SF
@@ -3381,50 +2961,6 @@
"TARGET_FUSED_MADD"
"fnma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
-
-(define_insn "*nmadddf4_truncsf_alts"
- [(set (match_operand:SF 0 "fr_register_operand" "=f")
- (float_truncate:SF
- (minus:DF (match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")
- (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
- (match_operand:DF 2 "fr_reg_or_fp01_operand" "fG")))))
- (use (match_operand:SI 4 "const_int_operand" ""))]
- ""
- "fnma.s.s%4 %0 = %F1, %F2, %F3"
- [(set_attr "itanium_class" "fmac")])
-
-(define_expand "divdf3"
- [(set (match_operand:DF 0 "fr_register_operand" "")
- (div:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "")
- (match_operand:DF 2 "fr_reg_or_fp01_operand" "")))]
- "TARGET_INLINE_FLOAT_DIV"
-{
- rtx insn;
- if (TARGET_INLINE_FLOAT_DIV == INL_MIN_LAT)
- insn = gen_divdf3_internal_lat (operands[0], operands[1], operands[2]);
- else
- insn = gen_divdf3_internal_thr (operands[0], operands[1], operands[2]);
- emit_insn (insn);
- DONE;
-})
-
-;; Inline square root.
-
-(define_expand "sqrtdf2"
- [(set (match_operand:DF 0 "fr_register_operand" "=&f")
- (sqrt:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))]
- "TARGET_INLINE_SQRT"
-{
- rtx insn;
-#if 0
- if (TARGET_INLINE_SQRT == INL_MIN_LAT)
- insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]);
- else
-#endif
- insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
- emit_insn (insn);
- DONE;
-})
;; ::::::::::::::::::::
;; ::
@@ -3510,35 +3046,6 @@
"fmpy.d %0 = %F1, %F2"
[(set_attr "itanium_class" "fmac")])
-(define_insn "*mulxf3_alts"
- [(set (match_operand:XF 0 "fr_register_operand" "=f")
- (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")))
- (use (match_operand:SI 3 "const_int_operand" ""))]
- ""
- "fmpy.s%3 %0 = %F1, %F2"
- [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*mulxf3_truncsf_alts"
- [(set (match_operand:SF 0 "fr_register_operand" "=f")
- (float_truncate:SF
- (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))
- (use (match_operand:SI 3 "const_int_operand" ""))]
- ""
- "fmpy.s.s%3 %0 = %F1, %F2"
- [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*mulxf3_truncdf_alts"
- [(set (match_operand:DF 0 "fr_register_operand" "=f")
- (float_truncate:DF
- (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))))
- (use (match_operand:SI 3 "const_int_operand" ""))]
- ""
- "fmpy.d.s%3 %0 = %F1, %F2"
- [(set_attr "itanium_class" "fmac")])
-
(define_insn "absxf2"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(abs:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")))]
@@ -3623,38 +3130,6 @@
"fma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
-(define_insn "*maddxf4_alts"
- [(set (match_operand:XF 0 "fr_register_operand" "=f")
- (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")))
- (use (match_operand:SI 4 "const_int_operand" ""))]
- ""
- "fma.s%4 %0 = %F1, %F2, %F3"
- [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*maddxf4_alts_truncsf"
- [(set (match_operand:SF 0 "fr_register_operand" "=f")
- (float_truncate:SF
- (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))
- (use (match_operand:SI 4 "const_int_operand" ""))]
- ""
- "fma.s.s%4 %0 = %F1, %F2, %F3"
- [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*maddxf4_alts_truncdf"
- [(set (match_operand:DF 0 "fr_register_operand" "=f")
- (float_truncate:DF
- (plus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG"))
- (match_operand:XF 3 "xfreg_or_fp01_operand" "fG"))))
- (use (match_operand:SI 4 "const_int_operand" ""))]
- ""
- "fma.d.s%4 %0 = %F1, %F2, %F3"
- [(set_attr "itanium_class" "fmac")])
-
(define_insn "*msubxf4"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(minus:XF (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
@@ -3743,81 +3218,6 @@
"TARGET_FUSED_MADD"
"fnma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
-
-(define_insn "*nmaddxf4_alts"
- [(set (match_operand:XF 0 "fr_register_operand" "=f")
- (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
- (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
- )))
- (use (match_operand:SI 4 "const_int_operand" ""))]
- ""
- "fnma.s%4 %0 = %F1, %F2, %F3"
- [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*nmaddxf4_truncsf_alts"
- [(set (match_operand:SF 0 "fr_register_operand" "=f")
- (float_truncate:SF
- (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
- (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
- ))))
- (use (match_operand:SI 4 "const_int_operand" ""))]
- ""
- "fnma.s.s%4 %0 = %F1, %F2, %F3"
- [(set_attr "itanium_class" "fmac")])
-
-(define_insn "*nmaddxf4_truncdf_alts"
- [(set (match_operand:DF 0 "fr_register_operand" "=f")
- (float_truncate:DF
- (minus:XF (match_operand:XF 3 "xfreg_or_fp01_operand" "fG")
- (mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
- (match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
- ))))
- (use (match_operand:SI 4 "const_int_operand" ""))]
- ""
- "fnma.d.s%4 %0 = %F1, %F2, %F3"
- [(set_attr "itanium_class" "fmac")])
-
-(define_expand "divxf3"
- [(set (match_operand:XF 0 "fr_register_operand" "")
- (div:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "")
- (match_operand:XF 2 "fr_reg_or_fp01_operand" "")))]
- "TARGET_INLINE_FLOAT_DIV"
-{
- /* There is only one divxf3 sequence, not two like for divsf and divdf. */
- emit_insn (gen_divxf3_internal (operands[0], operands[1], operands[2]));
- DONE;
-})
-
-;; Inline square root.
-
-(define_expand "sqrtxf2"
- [(set (match_operand:XF 0 "fr_register_operand" "=&f")
- (sqrt:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))]
- "TARGET_INLINE_SQRT"
-{
- rtx insn;
- insn = gen_sqrtxf2_internal (operands[0], operands[1]);
- emit_insn (insn);
- DONE;
-})
-
-;; ??? frcpa works like cmp.foo.unc.
-
-(define_insn "*recip_approx"
- [(set (match_operand:XF 0 "fr_register_operand" "=f")
- (unspec:XF [(const_int 1)
- (match_operand:XF 3 "fr_reg_or_fp01_operand" "fG")]
- UNSPEC_FR_RECIP_APPROX_RES))
- (set (match_operand:BI 1 "register_operand" "=c")
- (unspec:BI [(match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")
- (match_dup 3)] UNSPEC_FR_RECIP_APPROX))
- (use (match_operand:SI 4 "const_int_operand" ""))]
- ""
- "frcpa.s%4 %0, %1 = %F2, %F3"
- [(set_attr "itanium_class" "fmisc")
- (set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
diff --git a/gcc/config/ia64/t-ia64 b/gcc/config/ia64/t-ia64
index 4f78c64df70..db7a8298d17 100644
--- a/gcc/config/ia64/t-ia64
+++ b/gcc/config/ia64/t-ia64
@@ -1,5 +1,5 @@
-# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
-# 2008 Free Software Foundation, Inc.
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -47,7 +47,8 @@ LIB2ADDEH = $(srcdir)/config/ia64/unwind-ia64.c $(srcdir)/unwind-sjlj.c \
ia64-c.o: $(srcdir)/config/ia64/ia64-c.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(TREE_H) $(CPPLIB_H) $(C_COMMON_H) c-pragma.h toplev.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/ia64/ia64-c.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/ia64/ia64-c.c
# genattrtab generates very long string literals.
insn-attrtab.o-warn = -Wno-error
diff --git a/gcc/config/m32c/t-m32c b/gcc/config/m32c/t-m32c
index 33454fe3c3e..30b8f6f0b45 100644
--- a/gcc/config/m32c/t-m32c
+++ b/gcc/config/m32c/t-m32c
@@ -1,5 +1,5 @@
# Target Makefile Fragment for R8C/M16C/M32C
-# Copyright (C) 2005, 2007
+# Copyright (C) 2005, 2006, 2007, 2008, 2009
# Free Software Foundation, Inc.
# Contributed by Red Hat.
#
@@ -57,7 +57,7 @@ md : $(MD_FILES:%=$(srcdir)/config/m32c/%.md) $(srcdir)/config/m32c/t-m32c
done > md
m32c-pragma.o: $(srcdir)/config/m32c/m32c-pragma.c $(RTL_H) $(TREE_H) $(CONFIG_H) $(TM_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
# We support four CPU series, but R8C and M16C share one multilib, and
# M32C and M32CM share another.
diff --git a/gcc/config/m32r/m32r.c b/gcc/config/m32r/m32r.c
index 0b5ff6bc6fd..b8721c27e53 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -488,7 +488,7 @@ m32r_init_expanders (void)
int
call_operand (rtx op, enum machine_mode mode)
{
- if (GET_CODE (op) != MEM)
+ if (!MEM_P (op))
return 0;
op = XEXP (op, 0);
return call_address_operand (op, mode);
@@ -563,7 +563,7 @@ addr32_operand (rtx op, enum machine_mode mode)
else if (GET_CODE (op) == CONST
&& GET_CODE (XEXP (op, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
- && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT
+ && CONST_INT_P (XEXP (XEXP (op, 0), 1))
&& ! flag_pic)
sym = XEXP (XEXP (op, 0), 0);
else
@@ -632,7 +632,7 @@ easy_df_const (rtx op)
int
memreg_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
{
- return GET_CODE (op) == MEM && GET_CODE (XEXP (op, 0)) == REG;
+ return MEM_P (op) && REG_P (XEXP (op, 0));
}
/* Return nonzero if TYPE must be passed by indirect reference. */
@@ -734,7 +734,7 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare)
code = EQ;
break;
case GT:
- if (GET_CODE (y) == CONST_INT)
+ if (CONST_INT_P (y))
tmp = gen_rtx_PLUS (SImode, y, const1_rtx);
else
emit_insn (gen_addsi3 (tmp, y, constm1_rtx));
@@ -774,7 +774,7 @@ gen_compare (enum rtx_code code, rtx x, rtx y, int need_compare)
code = EQ;
break;
case GTU:
- if (GET_CODE (y) == CONST_INT)
+ if (CONST_INT_P (y))
tmp = gen_rtx_PLUS (SImode, y, const1_rtx);
else
emit_insn (gen_addsi3 (tmp, y, constm1_rtx));
@@ -881,7 +881,7 @@ gen_cond_store (enum rtx_code code, rtx op0, rtx op1, rtx op2)
emit_insn (gen_seq_insn_m32rx (op0, op1, op2));
return true;
}
- if (GET_CODE (op2) == CONST_INT && INTVAL (op2) == 0)
+ if (CONST_INT_P (op2) && INTVAL (op2) == 0)
{
emit_insn (gen_seq_zero_insn (op0, op1));
return true;
@@ -894,7 +894,7 @@ gen_cond_store (enum rtx_code code, rtx op0, rtx op1, rtx op2)
return true;
case NE:
- if (GET_CODE (op2) != CONST_INT
+ if (!CONST_INT_P (op2)
|| (INTVAL (op2) != 0 && satisfies_constraint_K (op2)))
{
rtx reg;
@@ -971,7 +971,7 @@ gen_cond_store (enum rtx_code code, rtx op0, rtx op1, rtx op2)
if (!register_operand (op1, mode))
op1 = force_reg (mode, op1);
- if (GET_CODE (op2) == CONST_INT)
+ if (CONST_INT_P (op2))
{
HOST_WIDE_INT value = INTVAL (op2);
if (value >= 2147483647)
@@ -1025,12 +1025,12 @@ gen_split_move_double (rtx operands[])
alter_subreg (&src);
start_sequence ();
- if (GET_CODE (dest) == REG)
+ if (REG_P (dest))
{
int dregno = REGNO (dest);
/* Reg = reg. */
- if (GET_CODE (src) == REG)
+ if (REG_P (src))
{
int sregno = REGNO (src);
@@ -1049,7 +1049,7 @@ gen_split_move_double (rtx operands[])
}
/* Reg = constant. */
- else if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE)
+ else if (CONST_INT_P (src) || GET_CODE (src) == CONST_DOUBLE)
{
rtx words[2];
split_double (src, &words[0], &words[1]);
@@ -1063,7 +1063,7 @@ gen_split_move_double (rtx operands[])
}
/* Reg = mem. */
- else if (GET_CODE (src) == MEM)
+ else if (MEM_P (src))
{
/* If the high-address word is used in the address, we must load it
last. Otherwise, load it first. */
@@ -1107,7 +1107,7 @@ gen_split_move_double (rtx operands[])
st r1,r3; st r2,+r3; addi r3,-4
which saves 2 bytes and doesn't force longword alignment. */
- else if (GET_CODE (dest) == MEM && GET_CODE (src) == REG)
+ else if (MEM_P (dest) && REG_P (src))
{
emit_insn (gen_rtx_SET (VOIDmode,
adjust_address (dest, SImode, 0),
@@ -1654,9 +1654,9 @@ m32r_expand_epilogue (void)
/* If the last insn was a BARRIER, we don't have to write any code
because a jump (aka return) was put there. */
- if (insn && GET_CODE (insn) == NOTE)
+ if (insn && NOTE_P (insn))
insn = prev_nonnote_insn (insn);
- if (insn && GET_CODE (insn) == BARRIER)
+ if (insn && BARRIER_P (insn))
noepilogue = TRUE;
}
@@ -1778,7 +1778,7 @@ m32r_legitimate_pic_operand_p (rtx x)
&& GET_CODE (XEXP (x, 0)) == PLUS
&& (GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF
|| GET_CODE (XEXP (XEXP (x, 0), 0)) == LABEL_REF)
- && (GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT))
+ && (CONST_INT_P (XEXP (XEXP (x, 0), 1))))
return 0;
return 1;
@@ -1857,7 +1857,7 @@ m32r_legitimize_pic_address (rtx orig, rtx reg)
else
return orig;
- if (GET_CODE (offset) == CONST_INT)
+ if (CONST_INT_P (offset))
{
if (INT16_P (INTVAL (offset)))
return plus_constant (base, INTVAL (offset));
@@ -1925,14 +1925,14 @@ m32r_print_operand (FILE * file, rtx x, int code)
/* The 's' and 'p' codes are used by output_block_move() to
indicate post-increment 's'tores and 'p're-increment loads. */
case 's':
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
fprintf (file, "@+%s", reg_names [REGNO (x)]);
else
output_operand_lossage ("invalid operand to %%s code");
return;
case 'p':
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
fprintf (file, "@%s+", reg_names [REGNO (x)]);
else
output_operand_lossage ("invalid operand to %%p code");
@@ -1941,9 +1941,9 @@ m32r_print_operand (FILE * file, rtx x, int code)
case 'R' :
/* Write second word of DImode or DFmode reference,
register or memory. */
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
fputs (reg_names[REGNO (x)+1], file);
- else if (GET_CODE (x) == MEM)
+ else if (MEM_P (x))
{
fprintf (file, "@(");
/* Handle possible auto-increment. Since it is pre-increment and
@@ -1963,7 +1963,7 @@ m32r_print_operand (FILE * file, rtx x, int code)
case 'H' : /* High word. */
case 'L' : /* Low word. */
- if (GET_CODE (x) == REG)
+ if (REG_P (x))
{
/* L = least significant word, H = most significant word. */
if ((WORDS_BIG_ENDIAN != 0) ^ (code == 'L'))
@@ -1971,7 +1971,7 @@ m32r_print_operand (FILE * file, rtx x, int code)
else
fputs (reg_names[REGNO (x)+1], file);
}
- else if (GET_CODE (x) == CONST_INT
+ else if (CONST_INT_P (x)
|| GET_CODE (x) == CONST_DOUBLE)
{
rtx first, second;
@@ -2045,7 +2045,7 @@ m32r_print_operand (FILE * file, rtx x, int code)
case 'U' :
/* ??? wip */
/* Output a load/store with update indicator if appropriate. */
- if (GET_CODE (x) == MEM)
+ if (MEM_P (x))
{
if (GET_CODE (XEXP (x, 0)) == PRE_INC
|| GET_CODE (XEXP (x, 0)) == PRE_DEC)
@@ -2057,7 +2057,7 @@ m32r_print_operand (FILE * file, rtx x, int code)
case 'N' :
/* Print a constant value negated. */
- if (GET_CODE (x) == CONST_INT)
+ if (CONST_INT_P (x))
output_addr_const (file, GEN_INT (- INTVAL (x)));
else
output_operand_lossage ("invalid operand to %%N code");
@@ -2065,7 +2065,7 @@ m32r_print_operand (FILE * file, rtx x, int code)
case 'X' :
/* Print a const_int in hex. Used in comments. */
- if (GET_CODE (x) == CONST_INT)
+ if (CONST_INT_P (x))
fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (x));
return;
@@ -2092,21 +2092,21 @@ m32r_print_operand (FILE * file, rtx x, int code)
addr = XEXP (x, 0);
if (GET_CODE (addr) == PRE_INC)
{
- if (GET_CODE (XEXP (addr, 0)) != REG)
+ if (!REG_P (XEXP (addr, 0)))
fatal_insn ("pre-increment address is not a register", x);
fprintf (file, "@+%s", reg_names[REGNO (XEXP (addr, 0))]);
}
else if (GET_CODE (addr) == PRE_DEC)
{
- if (GET_CODE (XEXP (addr, 0)) != REG)
+ if (!REG_P (XEXP (addr, 0)))
fatal_insn ("pre-decrement address is not a register", x);
fprintf (file, "@-%s", reg_names[REGNO (XEXP (addr, 0))]);
}
else if (GET_CODE (addr) == POST_INC)
{
- if (GET_CODE (XEXP (addr, 0)) != REG)
+ if (!REG_P (XEXP (addr, 0)))
fatal_insn ("post-increment address is not a register", x);
fprintf (file, "@%s+", reg_names[REGNO (XEXP (addr, 0))]);
@@ -2156,13 +2156,13 @@ m32r_print_operand_address (FILE * file, rtx addr)
break;
case PLUS :
- if (GET_CODE (XEXP (addr, 0)) == CONST_INT)
+ if (CONST_INT_P (XEXP (addr, 0)))
offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1);
- else if (GET_CODE (XEXP (addr, 1)) == CONST_INT)
+ else if (CONST_INT_P (XEXP (addr, 1)))
offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0);
else
base = XEXP (addr, 0), index = XEXP (addr, 1);
- if (GET_CODE (base) == REG)
+ if (REG_P (base))
{
/* Print the offset first (if present) to conform to the manual. */
if (index == 0)
@@ -2172,7 +2172,7 @@ m32r_print_operand_address (FILE * file, rtx addr)
fputs (reg_names[REGNO (base)], file);
}
/* The chip doesn't support this, but left in for generality. */
- else if (GET_CODE (index) == REG)
+ else if (REG_P (index))
fprintf (file, "%s,%s",
reg_names[REGNO (base)], reg_names[REGNO (index)]);
/* Not sure this can happen, but leave in for now. */
@@ -2187,7 +2187,7 @@ m32r_print_operand_address (FILE * file, rtx addr)
}
else if (GET_CODE (base) == LO_SUM)
{
- gcc_assert (!index && GET_CODE (XEXP (base, 0)) == REG);
+ gcc_assert (!index && REG_P (XEXP (base, 0)));
if (small_data_operand (XEXP (base, 1), VOIDmode))
fputs ("sda(", file);
else
@@ -2201,7 +2201,7 @@ m32r_print_operand_address (FILE * file, rtx addr)
break;
case LO_SUM :
- if (GET_CODE (XEXP (addr, 0)) != REG)
+ if (!REG_P (XEXP (addr, 0)))
fatal_insn ("lo_sum not of register", addr);
if (small_data_operand (XEXP (addr, 1), VOIDmode))
fputs ("sda(", file);
@@ -2236,8 +2236,8 @@ int
zero_and_one (rtx operand1, rtx operand2)
{
return
- GET_CODE (operand1) == CONST_INT
- && GET_CODE (operand2) == CONST_INT
+ CONST_INT_P (operand1)
+ && CONST_INT_P (operand2)
&& ( ((INTVAL (operand1) == 0) && (INTVAL (operand2) == 1))
||((INTVAL (operand1) == 1) && (INTVAL (operand2) == 0)));
}
@@ -2257,7 +2257,7 @@ emit_cond_move (rtx * operands, rtx insn ATTRIBUTE_UNUSED)
buffer [0] = 0;
/* Destination must be a register. */
- gcc_assert (GET_CODE (operands [0]) == REG);
+ gcc_assert (REG_P (operands [0]));
gcc_assert (conditional_move_operand (operands [2], SImode));
gcc_assert (conditional_move_operand (operands [3], SImode));
@@ -2291,13 +2291,13 @@ m32r_not_same_reg (rtx a, rtx b)
while (GET_CODE (a) == SUBREG)
a = SUBREG_REG (a);
- if (GET_CODE (a) == REG)
+ if (REG_P (a))
reg_a = REGNO (a);
while (GET_CODE (b) == SUBREG)
b = SUBREG_REG (b);
- if (GET_CODE (b) == REG)
+ if (REG_P (b))
reg_b = REGNO (b);
return reg_a != reg_b;
@@ -2361,7 +2361,7 @@ m32r_expand_block_move (rtx operands[])
rtx orig_src = operands[1];
rtx bytes_rtx = operands[2];
rtx align_rtx = operands[3];
- int constp = GET_CODE (bytes_rtx) == CONST_INT;
+ int constp = CONST_INT_P (bytes_rtx);
HOST_WIDE_INT bytes = constp ? INTVAL (bytes_rtx) : 0;
int align = INTVAL (align_rtx);
int leftover;
diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h
index 41dc07abad6..61c322048d9 100644
--- a/gcc/config/m32r/m32r.h
+++ b/gcc/config/m32r/m32r.h
@@ -1059,7 +1059,7 @@ L2: .word STATIC
#define CONSTANT_ADDRESS_P(X) \
( GET_CODE (X) == LABEL_REF \
|| GET_CODE (X) == SYMBOL_REF \
- || GET_CODE (X) == CONST_INT \
+ || CONST_INT_P (X) \
|| (GET_CODE (X) == CONST \
&& ! (flag_pic && ! m32r_legitimate_pic_operand_p (X))))
@@ -1073,7 +1073,7 @@ L2: .word STATIC
(! (GET_CODE (X) == CONST \
&& GET_CODE (XEXP (X, 0)) == PLUS \
&& (GET_CODE (XEXP (XEXP (X, 0), 0)) == SYMBOL_REF || GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF) \
- && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
+ && CONST_INT_P (XEXP (XEXP (X, 0), 1)) \
&& (unsigned HOST_WIDE_INT) INTVAL (XEXP (XEXP (X, 0), 1)) > 32767))
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
@@ -1120,7 +1120,7 @@ L2: .word STATIC
/* Local to this file. */
#define RTX_OK_FOR_OFFSET_P(X) \
- (GET_CODE (X) == CONST_INT && INT16_P (INTVAL (X)))
+ (CONST_INT_P (X) && INT16_P (INTVAL (X)))
/* Local to this file. */
#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \
@@ -1142,7 +1142,7 @@ L2: .word STATIC
#define LOAD_POSTINC_P(MODE, X) \
(((MODE) == SImode || (MODE) == SFmode) \
&& GET_CODE (X) == POST_INC \
- && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_P (XEXP (X, 0)) \
&& RTX_OK_FOR_BASE_P (XEXP (X, 0)))
/* Local to this file. */
@@ -1150,7 +1150,7 @@ L2: .word STATIC
#define STORE_PREINC_PREDEC_P(MODE, X) \
(((MODE) == SImode || (MODE) == SFmode) \
&& (GET_CODE (X) == PRE_INC || GET_CODE (X) == PRE_DEC) \
- && GET_CODE (XEXP (X, 0)) == REG \
+ && REG_P (XEXP (X, 0)) \
&& RTX_OK_FOR_BASE_P (XEXP (X, 0)))
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
diff --git a/gcc/config/m32r/m32r.md b/gcc/config/m32r/m32r.md
index 0c76a044ccc..ec0d61f294c 100644
--- a/gcc/config/m32r/m32r.md
+++ b/gcc/config/m32r/m32r.md
@@ -250,7 +250,7 @@
/* Everything except mem = const or mem = mem can be done easily.
Objects in the small data area are handled too. */
- if (GET_CODE (operands[0]) == MEM)
+ if (MEM_P (operands[0]))
operands[1] = force_reg (QImode, operands[1]);
}")
@@ -289,7 +289,7 @@
/* Everything except mem = const or mem = mem can be done easily. */
- if (GET_CODE (operands[0]) == MEM)
+ if (MEM_P (operands[0]))
operands[1] = force_reg (HImode, operands[1]);
}")
@@ -341,7 +341,7 @@
/* Everything except mem = const or mem = mem can be done easily. */
- if (GET_CODE (operands[0]) == MEM)
+ if (MEM_P (operands[0]))
operands[1] = force_reg (SImode, operands[1]);
/* Small Data Area reference? */
@@ -367,7 +367,7 @@
"register_operand (operands[0], SImode) || register_operand (operands[1], SImode)"
"*
{
- if (GET_CODE (operands[0]) == REG || GET_CODE (operands[1]) == SUBREG)
+ if (REG_P (operands[0]) || GET_CODE (operands[1]) == SUBREG)
{
switch (GET_CODE (operands[1]))
{
@@ -409,8 +409,8 @@
}
}
- else if (GET_CODE (operands[0]) == MEM
- && (GET_CODE (operands[1]) == REG || GET_CODE (operands[1]) == SUBREG))
+ else if (MEM_P (operands[0])
+ && (REG_P (operands[1]) || GET_CODE (operands[1]) == SUBREG))
{
if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
&& XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)
@@ -585,7 +585,7 @@
/* Everything except mem = const or mem = mem can be done easily. */
- if (GET_CODE (operands[0]) == MEM)
+ if (MEM_P (operands[0]))
operands[1] = force_reg (DImode, operands[1]);
}")
@@ -626,7 +626,7 @@
/* Everything except mem = const or mem = mem can be done easily. */
- if (GET_CODE (operands[0]) == MEM)
+ if (MEM_P (operands[0]))
operands[1] = force_reg (SFmode, operands[1]);
}")
@@ -678,7 +678,7 @@
/* Everything except mem = const or mem = mem can be done easily. */
- if (GET_CODE (operands[0]) == MEM)
+ if (MEM_P (operands[0]))
operands[1] = force_reg (DFmode, operands[1]);
}")
@@ -1036,7 +1036,7 @@
&& satisfies_constraint_I (operands[2]))
return \"#\";
- else if (GET_CODE (operands[2]) == CONST_INT)
+ else if (CONST_INT_P (operands[2]))
return \"and3 %0,%1,%#%X2\";
return \"and %0,%2\";
@@ -1067,7 +1067,7 @@
&& satisfies_constraint_I (operands[2]))
return \"#\";
- else if (GET_CODE (operands[2]) == CONST_INT)
+ else if (CONST_INT_P (operands[2]))
return \"or3 %0,%1,%#%X2\";
return \"or %0,%2\";
@@ -1098,7 +1098,7 @@
&& satisfies_constraint_I (operands[2]))
return \"#\";
- else if (GET_CODE (operands[2]) == CONST_INT)
+ else if (CONST_INT_P (operands[2]))
return \"xor3 %0,%1,%#%X2\";
return \"xor %0,%2\";
@@ -1588,7 +1588,7 @@
rtx op3 = operands[3];
HOST_WIDE_INT value;
- if (GET_CODE (op2) == REG && GET_CODE (op3) == REG
+ if (REG_P (op2) && REG_P (op3)
&& REGNO (op2) == REGNO (op3))
{
op1 = operands[2];
@@ -1596,7 +1596,7 @@
}
start_sequence ();
- if (GET_CODE (op1) == REG && GET_CODE (op3) == REG
+ if (REG_P (op1) && REG_P (op3)
&& REGNO (op1) != REGNO (op3))
{
emit_move_insn (op3, op1);
diff --git a/gcc/config/m32r/predicates.md b/gcc/config/m32r/predicates.md
index 5873b6d2ff6..4b3c5fea1e1 100644
--- a/gcc/config/m32r/predicates.md
+++ b/gcc/config/m32r/predicates.md
@@ -22,10 +22,10 @@
(define_predicate "reg_or_zero_operand"
(match_code "reg,subreg,const_int")
{
- if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ if (REG_P (op) || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
return 0;
return INTVAL (op) == 0;
@@ -75,11 +75,11 @@
return FALSE;
x = XEXP (op, 0);
- if (GET_CODE (x) != REG || REGNO (x) != CARRY_REGNUM)
+ if (!REG_P (x) || REGNO (x) != CARRY_REGNUM)
return FALSE;
x = XEXP (op, 1);
- if (GET_CODE (x) != CONST_INT || INTVAL (x) != 0)
+ if (!CONST_INT_P (x) || INTVAL (x) != 0)
return FALSE;
return TRUE;
@@ -119,7 +119,7 @@
case SUBREG :
/* (subreg (mem ...) ...) can occur here if the inner part was once a
pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
+ if (MEM_P (SUBREG_REG (op)))
return address_operand (XEXP (SUBREG_REG (op), 0), mode);
else
return register_operand (op, mode);
@@ -175,7 +175,7 @@
case SUBREG :
/* (subreg (mem ...) ...) can occur here if the inner part was once a
pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
+ if (MEM_P (SUBREG_REG (op)))
return address_operand (XEXP (SUBREG_REG (op), 0), mode);
else
return register_operand (op, mode);
@@ -205,7 +205,7 @@
case SUBREG :
/* (subreg (mem ...) ...) can occur here if the inner part was once a
pseudo-reg and is now a stack slot. */
- if (GET_CODE (SUBREG_REG (op)) == MEM)
+ if (MEM_P (SUBREG_REG (op)))
return move_double_src_operand (SUBREG_REG (op), mode);
else
return register_operand (op, mode);
@@ -226,7 +226,7 @@
(define_predicate "two_insn_const_operand"
(match_code "const_int")
{
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
return 0;
if (satisfies_constraint_J (op)
|| satisfies_constraint_M (op)
@@ -257,7 +257,7 @@
(define_predicate "int8_operand"
(match_code "const_int")
{
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
return 0;
return satisfies_constraint_I (op);
})
@@ -267,7 +267,7 @@
(define_predicate "uint16_operand"
(match_code "const_int")
{
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
return 0;
return satisfies_constraint_K (op);
})
@@ -277,9 +277,9 @@
(define_predicate "reg_or_int16_operand"
(match_code "reg,subreg,const_int")
{
- if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ if (REG_P (op) || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
return 0;
return satisfies_constraint_J (op);
})
@@ -289,9 +289,9 @@
(define_predicate "reg_or_uint16_operand"
(match_code "reg,subreg,const_int")
{
- if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ if (REG_P (op) || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
return 0;
return satisfies_constraint_K (op);
})
@@ -302,9 +302,9 @@
(define_predicate "reg_or_cmp_int16_operand"
(match_code "reg,subreg,const_int")
{
- if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ if (REG_P (op) || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
return 0;
return satisfies_constraint_P (op);
})
@@ -319,10 +319,10 @@
{
HOST_WIDE_INT value;
- if (GET_CODE (op) == REG || GET_CODE (op) == SUBREG)
+ if (REG_P (op) || GET_CODE (op) == SUBREG)
return register_operand (op, mode);
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
return 0;
value = INTVAL (op);
@@ -335,7 +335,7 @@
(define_predicate "cmp_int16_operand"
(match_code "const_int")
{
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
return 0;
return satisfies_constraint_P (op);
})
@@ -384,7 +384,7 @@
(define_predicate "small_insn_p"
(match_code "insn,call_insn,jump_insn")
{
- if (GET_CODE (op) == CONST_INT && INTVAL (op) == 0)
+ if (CONST_INT_P (op) && INTVAL (op) == 0)
return 1;
if (! INSN_P (op))
@@ -399,7 +399,7 @@
(define_predicate "m32r_block_immediate_operand"
(match_code "const_int")
{
- if (GET_CODE (op) != CONST_INT
+ if (!CONST_INT_P (op)
|| INTVAL (op) > MAX_MOVE_BYTES
|| INTVAL (op) <= 0)
return 0;
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index ed10c391971..50a47e9bd5e 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -13928,6 +13928,8 @@ mips_set_mips16_mode (int mips16_p)
targetm.min_anchor_offset = 0;
targetm.max_anchor_offset = 127;
+ targetm.const_anchor = 0;
+
if (flag_pic && !TARGET_OLDABI)
sorry ("MIPS16 PIC for ABIs other than o32 and o64");
@@ -13955,6 +13957,8 @@ mips_set_mips16_mode (int mips16_p)
targetm.min_anchor_offset = -32768;
targetm.max_anchor_offset = 32767;
+
+ targetm.const_anchor = 0x8000;
}
/* (Re)initialize MIPS target internals for new ISA. */
diff --git a/gcc/config/mips/x-native b/gcc/config/mips/x-native
index 6820e73d94b..5e31121ede1 100644
--- a/gcc/config/mips/x-native
+++ b/gcc/config/mips/x-native
@@ -1,3 +1,3 @@
driver-native.o : $(srcdir)/config/mips/driver-native.c \
$(CONFIG_H) $(SYSTEM_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/pa/pa-hpux.h b/gcc/config/pa/pa-hpux.h
index bd12d4fc68e..b600b0e3d4c 100644
--- a/gcc/config/pa/pa-hpux.h
+++ b/gcc/config/pa/pa-hpux.h
@@ -95,12 +95,10 @@ along with GCC; see the file COPYING3. If not see
#undef LINK_SPEC
#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_PA_11)
#define LINK_SPEC \
- "%<fwhole-program\
- %{!mpa-risc-1-0:%{!march=1.0:%{static:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}}%{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}"
+ "%{!mpa-risc-1-0:%{!march=1.0:%{static:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}}%{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}"
#else
#define LINK_SPEC \
- "%<fwhole-program\
- %{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}"
+ "%{mlinker-opt:-O} %{!shared:-u main} %{static:-a archive} %{g*:-a archive} %{shared:-b}"
#endif
/* hpux8 and later have C++ compatible include files, so do not
diff --git a/gcc/config/pa/pa-hpux10.h b/gcc/config/pa/pa-hpux10.h
index c1294dfff0b..df36ea2e8a9 100644
--- a/gcc/config/pa/pa-hpux10.h
+++ b/gcc/config/pa/pa-hpux10.h
@@ -82,8 +82,7 @@ along with GCC; see the file COPYING3. If not see
#undef LINK_SPEC
#if ((TARGET_DEFAULT | TARGET_CPU_DEFAULT) & MASK_PA_11)
#define LINK_SPEC \
- "%<fwhole-program\
- %{!mpa-risc-1-0:%{!march=1.0:%{static:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}}\
+ "%{!mpa-risc-1-0:%{!march=1.0:%{static:-L/lib/pa1.1 -L/usr/lib/pa1.1 }}}\
%{!shared:%{p:-L/lib/libp %{!static:\
%nWarning: consider linking with `-static' as system libraries with\n\
%n profiling support are only provided in archive format}}}\
@@ -94,8 +93,7 @@ along with GCC; see the file COPYING3. If not see
%{static:-a archive} %{shared:-b}"
#else
#define LINK_SPEC \
- "%<fwhole-program\
- %{!shared:%{p:-L/lib/libp %{!static:\
+ "%{!shared:%{p:-L/lib/libp %{!static:\
%nWarning: consider linking with `-static' as system libraries with\n\
%n profiling support are only provided in archive format}}}\
%{!shared:%{pg:-L/lib/libp %{!static:\
diff --git a/gcc/config/pa/pa-hpux11.h b/gcc/config/pa/pa-hpux11.h
index 06b709c2350..09b414cb00a 100644
--- a/gcc/config/pa/pa-hpux11.h
+++ b/gcc/config/pa/pa-hpux11.h
@@ -104,8 +104,7 @@ along with GCC; see the file COPYING3. If not see
want dereferencing of a NULL pointer to cause a SEGV. */
#undef LINK_SPEC
#define LINK_SPEC \
- "%<fwhole-program\
- %{!shared:%{p:-L/lib/libp -L/usr/lib/libp %{!static:\
+ "%{!shared:%{p:-L/lib/libp -L/usr/lib/libp %{!static:\
%nWarning: consider linking with `-static' as system libraries with\n\
%n profiling support are only provided in archive format}}}\
%{!shared:%{pg:-L/lib/libp -L/usr/lib/libp %{!static:\
diff --git a/gcc/config/picochip/picochip.c b/gcc/config/picochip/picochip.c
index 56c58a83056..358ef71e36b 100644
--- a/gcc/config/picochip/picochip.c
+++ b/gcc/config/picochip/picochip.c
@@ -315,9 +315,6 @@ picochip_override_options (void)
PARAM_VALUE (PARAM_LARGE_STACK_FRAME) = 0;
PARAM_VALUE (PARAM_STACK_FRAME_GROWTH) = 0;
}
- /* The function call overhead on picochip is not very high. Let the
- inliner know so its heuristics become more reasonable. */
- PARAM_VALUE (PARAM_INLINE_CALL_COST) = 2;
/* Turn off the elimination of unused types. The elaborator
generates various interesting types to represent constants,
diff --git a/gcc/config/rs6000/aix.h b/gcc/config/rs6000/aix.h
index 4e736ce3fc2..b9f1bcadb1a 100644
--- a/gcc/config/rs6000/aix.h
+++ b/gcc/config/rs6000/aix.h
@@ -120,18 +120,10 @@
/* #define ASM_SPEC "-u %(asm_cpu)" */
/* Default location of syscalls.exp under AIX */
-#ifndef CROSS_DIRECTORY_STRUCTURE
-#define LINK_SYSCALLS_SPEC "-bI:/lib/syscalls.exp"
-#else
-#define LINK_SYSCALLS_SPEC ""
-#endif
+#define LINK_SYSCALLS_SPEC "-bI:%R/lib/syscalls.exp"
/* Default location of libg.exp under AIX */
-#ifndef CROSS_DIRECTORY_STRUCTURE
-#define LINK_LIBG_SPEC "-bexport:/usr/lib/libg.exp"
-#else
-#define LINK_LIBG_SPEC ""
-#endif
+#define LINK_LIBG_SPEC "-bexport:%R/usr/lib/libg.exp"
/* Define the options for the binder: Start text at 512, align all segments
to 512 bytes, and warn if there is text relocation.
@@ -152,8 +144,8 @@
%{!shared:%{g*: %(link_libg) }} %{shared:-bM:SRE}"
/* Profiled library versions are used by linking with special directories. */
-#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
-%{p:-L/lib/profiled -L/usr/lib/profiled} %{!shared:%{g*:-lg}} -lc"
+#define LIB_SPEC "%{pg:-L%R/lib/profiled -L%R/usr/lib/profiled}\
+%{p:-L%R/lib/profiled -L%R/usr/lib/profiled} %{!shared:%{g*:-lg}} -lc"
/* Static linking with shared libstdc++ requires libsupc++ as well. */
#define LIBSTDCXX_STATIC "-lstdc++ -lsupc++"
diff --git a/gcc/config/rs6000/aix43.h b/gcc/config/rs6000/aix43.h
index 56b24a363c6..bbe23373060 100644
--- a/gcc/config/rs6000/aix43.h
+++ b/gcc/config/rs6000/aix43.h
@@ -104,7 +104,7 @@ do { \
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE}\
%{ansi: -D_ANSI_C_SOURCE}\
%{maix64: -D__64BIT__}\
- %{mpe: -I/usr/lpp/ppe.poe/include}\
+ %{mpe: -I%R/usr/lpp/ppe.poe/include}\
%{pthread: -D_THREAD_SAFE}"
/* The GNU C++ standard library requires that these macros be
@@ -113,7 +113,7 @@ do { \
#define CPLUSPLUS_CPP_SPEC \
"-D_ALL_SOURCE \
%{maix64: -D__64BIT__} \
- %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{mpe: -I%R/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
#undef TARGET_DEFAULT
@@ -141,11 +141,11 @@ do { \
#define MULTILIB_DEFAULTS { "mcpu=common" }
#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
- %{p:-L/lib/profiled -L/usr/lib/profiled}\
+#define LIB_SPEC "%{pg:-L%R/lib/profiled -L%R/usr/lib/profiled}\
+ %{p:-L%R/lib/profiled -L%R/usr/lib/profiled}\
%{!maix64:%{!shared:%{g*:-lg}}}\
- %{mpe:-L/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
- %{pthread:-L/usr/lib/threads -lpthreads -lc_r /usr/lib/libc.a}\
+ %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
+ %{pthread:-L%R/usr/lib/threads -lpthreads -lc_r %R/usr/lib/libc.a}\
%{!pthread:-lc}"
#undef LINK_SPEC
@@ -187,3 +187,5 @@ do { \
/* This target uses the aix64.opt file. */
#define TARGET_USES_AIX64_OPT 1
+
+#define TARGET_AIX_VERSION 43
diff --git a/gcc/config/rs6000/aix51.h b/gcc/config/rs6000/aix51.h
index dbec0fb2a3c..32bdbb41f28 100644
--- a/gcc/config/rs6000/aix51.h
+++ b/gcc/config/rs6000/aix51.h
@@ -101,7 +101,7 @@ do { \
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \
%{ansi: -D_ANSI_C_SOURCE} \
%{maix64: -D__64BIT__} \
- %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{mpe: -I%R/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
/* The GNU C++ standard library requires that these macros be
@@ -110,7 +110,7 @@ do { \
#define CPLUSPLUS_CPP_SPEC \
"-D_ALL_SOURCE \
%{maix64: -D__64BIT__} \
- %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{mpe: -I%R/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
#undef TARGET_DEFAULT
@@ -138,10 +138,10 @@ do { \
#define MULTILIB_DEFAULTS { "mcpu=common" }
#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
- %{p:-L/lib/profiled -L/usr/lib/profiled}\
+#define LIB_SPEC "%{pg:-L%R/lib/profiled -L%R/usr/lib/profiled}\
+ %{p:-L%R/lib/profiled -L%R/usr/lib/profiled}\
%{!maix64:%{!shared:%{g*:-lg}}}\
- %{mpe:-L/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
+ %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
%{pthread:-lpthreads} -lc"
#undef LINK_SPEC
@@ -191,3 +191,5 @@ do { \
but does not have crtbegin/end. */
#define TARGET_USE_JCR_SECTION 0
+
+#define TARGET_AIX_VERSION 51
diff --git a/gcc/config/rs6000/aix52.h b/gcc/config/rs6000/aix52.h
index 8fab3f4a263..8d6c2411621 100644
--- a/gcc/config/rs6000/aix52.h
+++ b/gcc/config/rs6000/aix52.h
@@ -99,7 +99,7 @@ do { \
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \
%{ansi: -D_ANSI_C_SOURCE} \
%{maix64: -D__64BIT__} \
- %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{mpe: -I%R/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
/* The GNU C++ standard library requires that these macros be
@@ -108,7 +108,7 @@ do { \
#define CPLUSPLUS_CPP_SPEC \
"-D_ALL_SOURCE \
%{maix64: -D__64BIT__} \
- %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{mpe: -I%R/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
#undef TARGET_DEFAULT
@@ -140,10 +140,10 @@ do { \
#undef MULTILIB_DEFAULTS
#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
- %{p:-L/lib/profiled -L/usr/lib/profiled}\
+#define LIB_SPEC "%{pg:-L%R/lib/profiled -L%R/usr/lib/profiled}\
+ %{p:-L%R/lib/profiled -L%R/usr/lib/profiled}\
%{!maix64:%{!shared:%{g*:-lg}}}\
- %{mpe:-L/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
+ %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
%{pthread:-lpthreads} -lc"
#undef LINK_SPEC
@@ -201,3 +201,5 @@ extern long long int atoll(const char *);
but does not have crtbegin/end. */
#define TARGET_USE_JCR_SECTION 0
+
+#define TARGET_AIX_VERSION 52
diff --git a/gcc/config/rs6000/aix53.h b/gcc/config/rs6000/aix53.h
index 80f1038faa1..6172e76aad2 100644
--- a/gcc/config/rs6000/aix53.h
+++ b/gcc/config/rs6000/aix53.h
@@ -101,7 +101,7 @@ do { \
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \
%{ansi: -D_ANSI_C_SOURCE} \
%{maix64: -D__64BIT__} \
- %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{mpe: -I%R/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
/* The GNU C++ standard library requires that these macros be
@@ -110,7 +110,7 @@ do { \
#define CPLUSPLUS_CPP_SPEC \
"-D_ALL_SOURCE \
%{maix64: -D__64BIT__} \
- %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{mpe: -I%R/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
#undef TARGET_DEFAULT
@@ -136,10 +136,10 @@ do { \
#undef MULTILIB_DEFAULTS
#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
- %{p:-L/lib/profiled -L/usr/lib/profiled}\
+#define LIB_SPEC "%{pg:-L%R/lib/profiled -L%R/usr/lib/profiled}\
+ %{p:-L%R/lib/profiled -L%R/usr/lib/profiled}\
%{!maix64:%{!shared:%{g*:-lg}}}\
- %{mpe:-L/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
+ %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
%{pthread:-lpthreads} -lc"
#undef LINK_SPEC
@@ -197,3 +197,5 @@ extern long long int atoll(const char *);
but does not have crtbegin/end. */
#define TARGET_USE_JCR_SECTION 0
+
+#define TARGET_AIX_VERSION 53
diff --git a/gcc/config/rs6000/aix61.h b/gcc/config/rs6000/aix61.h
index e62a775c745..c0899d8c513 100644
--- a/gcc/config/rs6000/aix61.h
+++ b/gcc/config/rs6000/aix61.h
@@ -102,7 +102,7 @@ do { \
#define CPP_SPEC "%{posix: -D_POSIX_SOURCE} \
%{ansi: -D_ANSI_C_SOURCE} \
%{maix64: -D__64BIT__} \
- %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{mpe: -I%R/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
/* The GNU C++ standard library requires that these macros be
@@ -111,7 +111,7 @@ do { \
#define CPLUSPLUS_CPP_SPEC \
"-D_ALL_SOURCE -D__COMPATMATH__ \
%{maix64: -D__64BIT__} \
- %{mpe: -I/usr/lpp/ppe.poe/include} \
+ %{mpe: -I%R/usr/lpp/ppe.poe/include} \
%{pthread: -D_THREAD_SAFE}"
#undef TARGET_DEFAULT
@@ -137,10 +137,10 @@ do { \
#undef MULTILIB_DEFAULTS
#undef LIB_SPEC
-#define LIB_SPEC "%{pg:-L/lib/profiled -L/usr/lib/profiled}\
- %{p:-L/lib/profiled -L/usr/lib/profiled}\
+#define LIB_SPEC "%{pg:-L%R/lib/profiled -L%R/usr/lib/profiled}\
+ %{p:-L%R/lib/profiled -L%R/usr/lib/profiled}\
%{!maix64:%{!shared:%{g*:-lg}}}\
- %{mpe:-L/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
+ %{mpe:-L%R/usr/lpp/ppe.poe/lib -lmpi -lvtd}\
%{pthread:-lpthreads} -lc"
#undef LINK_SPEC
@@ -202,3 +202,5 @@ extern long long int atoll(const char *);
/* Default to 128 bit long double. */
#define RS6000_DEFAULT_LONG_DOUBLE_SIZE 128
+
+#define TARGET_AIX_VERSION 61
diff --git a/gcc/config/rs6000/rs6000-c.c b/gcc/config/rs6000/rs6000-c.c
index c7adcdb5e04..33bbd65bff7 100644
--- a/gcc/config/rs6000/rs6000-c.c
+++ b/gcc/config/rs6000/rs6000-c.c
@@ -91,6 +91,7 @@ static GTY(()) tree __pixel_keyword;
static GTY(()) tree pixel_keyword;
static GTY(()) tree __bool_keyword;
static GTY(()) tree bool_keyword;
+static GTY(()) tree _Bool_keyword;
/* Preserved across calls. */
static tree expand_bool_pixel;
@@ -111,6 +112,9 @@ altivec_categorize_keyword (const cpp_token *tok)
if (ident == C_CPP_HASHNODE (bool_keyword))
return C_CPP_HASHNODE (__bool_keyword);
+ if (ident == C_CPP_HASHNODE (_Bool_keyword))
+ return C_CPP_HASHNODE (__bool_keyword);
+
return ident;
}
@@ -141,6 +145,9 @@ init_vector_keywords (void)
bool_keyword = get_identifier ("bool");
C_CPP_HASHNODE (bool_keyword)->flags |= NODE_CONDITIONAL;
+
+ _Bool_keyword = get_identifier ("_Bool");
+ C_CPP_HASHNODE (_Bool_keyword)->flags |= NODE_CONDITIONAL;
}
/* Called to decide whether a conditional macro should be expanded.
@@ -295,6 +302,7 @@ rs6000_cpu_cpp_builtins (cpp_reader *pfile)
builtin_define ("vector=vector");
builtin_define ("pixel=pixel");
builtin_define ("bool=bool");
+ builtin_define ("_Bool=_Bool");
init_vector_keywords ();
/* Enable context-sensitive macros. */
diff --git a/gcc/config/rs6000/t-aix52 b/gcc/config/rs6000/t-aix52
index b22a190096e..0b4540278ce 100644
--- a/gcc/config/rs6000/t-aix52
+++ b/gcc/config/rs6000/t-aix52
@@ -47,7 +47,7 @@ SHLIB_LINK = $(GCC_FOR_TARGET) $(LIBGCC2_CFLAGS) -shared -nodefaultlibs \
-Wl,-bE:@shlib_map_file@ -o @multilib_dir@/shr.o \
@multilib_flags@ @shlib_objs@ -lc \
`case @multilib_dir@ in \
- *pthread*) echo -L/usr/lib/threads -lpthreads -lc_r /usr/lib/libc.a ;; \
+ *pthread*) echo -L$(TARGET_SYSTEM_ROOT)/usr/lib/threads -lpthreads -lc_r $(TARGET_SYSTEM_ROOT)/usr/lib/libc.a ;; \
*) echo -lc ;; esac` ; \
rm -f @multilib_dir@/tmp-@shlib_base_name@.a ; \
$(AR_CREATE_FOR_TARGET) @multilib_dir@/tmp-@shlib_base_name@.a \
diff --git a/gcc/config/rs6000/t-rs6000 b/gcc/config/rs6000/t-rs6000
index c435bf40324..1a838c54bc3 100644
--- a/gcc/config/rs6000/t-rs6000
+++ b/gcc/config/rs6000/t-rs6000
@@ -1,7 +1,7 @@
# General rules that all rs6000/ targets must have.
#
-# Copyright (C) 1995, 1997, 1998, 1999, 2001, 2002, 2003, 2004,
-# 2008 Free Software Foundation, Inc.
+# Copyright (C) 1995, 1997, 1998, 1999, 2001, 2002, 2003, 2004, 2008, 2009
+# Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -31,7 +31,8 @@ rs6000-c.o: $(srcdir)/config/rs6000/rs6000-c.c \
$(srcdir)/config/rs6000/rs6000-protos.h \
$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(CPPLIB_H) \
$(TM_P_H) c-pragma.h errors.h coretypes.h $(TM_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/rs6000/rs6000-c.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/rs6000/rs6000-c.c
# The rs6000 backend doesn't cause warnings in these files.
insn-conditions.o-warn =
diff --git a/gcc/config/rs6000/x-darwin b/gcc/config/rs6000/x-darwin
index 033ab6bf54c..5672c698b1e 100644
--- a/gcc/config/rs6000/x-darwin
+++ b/gcc/config/rs6000/x-darwin
@@ -1,4 +1,5 @@
host-ppc-darwin.o : $(srcdir)/config/rs6000/host-darwin.c \
$(CONFIG_H) $(SYSTEM_H) coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) toplev.h \
config/host-darwin.h $(DIAGNOSTIC_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< -o $@
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
+ $(INCLUDES) $< -o $@
diff --git a/gcc/config/rs6000/x-darwin64 b/gcc/config/rs6000/x-darwin64
index 3cb423db35e..921d555ba01 100644
--- a/gcc/config/rs6000/x-darwin64
+++ b/gcc/config/rs6000/x-darwin64
@@ -1,4 +1,5 @@
host-ppc64-darwin.o : $(srcdir)/config/rs6000/host-ppc64-darwin.c \
$(CONFIG_H) $(SYSTEM_H) coretypes.h hosthooks.h $(HOSTHOOKS_DEF_H) toplev.h \
config/host-darwin.h $(DIAGNOSTIC_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< -o $@
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
+ $(INCLUDES) $< -o $@
diff --git a/gcc/config/rs6000/x-rs6000 b/gcc/config/rs6000/x-rs6000
index 8246c377630..9e31f24cd64 100644
--- a/gcc/config/rs6000/x-rs6000
+++ b/gcc/config/rs6000/x-rs6000
@@ -1,3 +1,3 @@
driver-rs6000.o : $(srcdir)/config/rs6000/driver-rs6000.c \
$(CONFIG_H) $(SYSTEM_H) $(TM_H) coretypes.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/score/t-score-elf b/gcc/config/score/t-score-elf
index c2db527a25b..e30a5a1000f 100644
--- a/gcc/config/score/t-score-elf
+++ b/gcc/config/score/t-score-elf
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -20,13 +20,13 @@
score7.o: $(srcdir)/config/score/score7.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(RTL_H) output.h flags.h $(TREE_H) \
expr.h toplev.h $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/score/score7.c
score3.o: $(srcdir)/config/score/score3.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h $(TM_H) $(RTL_H) output.h flags.h $(TREE_H) \
expr.h toplev.h $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/score/score3.c
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index db49b8d32ef..545ac047121 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -6746,10 +6746,9 @@ sh_expand_epilogue (bool sibcall_p)
if (frame_pointer_needed)
{
- /* We must avoid scheduling the epilogue with previous basic blocks
- when exception handling is enabled. See PR/18032. */
- if (flag_exceptions)
- emit_insn (gen_blockage ());
+ /* We must avoid scheduling the epilogue with previous basic blocks.
+ See PR/18032 and PR/40313. */
+ emit_insn (gen_blockage ());
output_stack_adjust (frame_size, hard_frame_pointer_rtx, e,
&live_regs_mask);
@@ -11085,7 +11084,7 @@ sh_expand_t_scc (rtx operands[])
emit_insn (gen_movt (result));
else if (TARGET_SH2A && ((code == EQ && val == 0)
|| (code == NE && val == 1)))
- emit_insn (gen_movrt (result));
+ emit_insn (gen_xorsi3_movrt (result));
else if ((code == EQ && val == 0) || (code == NE && val == 1))
{
emit_clobber (result);
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 6f4d1b2f84b..30022d66bcb 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -3850,6 +3850,34 @@ label:
[(set_attr "length" "4")
(set_attr "type" "arith")])
+;; Expander for DImode shift left with SImode operations.
+
+(define_expand "ashldi3_std"
+ [(set (match_operand:DI 0 "arith_reg_dest" "=r")
+ (ashift:DI (match_operand:DI 1 "arith_reg_operand" "r")
+ (match_operand:DI 2 "const_int_operand" "n")))]
+ "TARGET_SH1 && INTVAL (operands[2]) < 32"
+ "
+{
+ int low_word = (TARGET_LITTLE_ENDIAN ? 0 : 1);
+ int high_word = (TARGET_LITTLE_ENDIAN ? 1 : 0);
+ rtx low_src = operand_subword (operands[1], low_word, 0, DImode);
+ rtx high_src = operand_subword (operands[1], high_word, 0, DImode);
+ rtx dst = gen_reg_rtx (DImode);
+ rtx low_dst = operand_subword (dst, low_word, 1, DImode);
+ rtx high_dst = operand_subword (dst, high_word, 1, DImode);
+ rtx tmp0, tmp1;
+
+ tmp0 = gen_reg_rtx (SImode);
+ tmp1 = gen_reg_rtx (SImode);
+ emit_insn (gen_lshrsi3 (tmp0, low_src, GEN_INT (32 - INTVAL (operands[2]))));
+ emit_insn (gen_ashlsi3 (low_dst, low_src, operands[2]));
+ emit_insn (gen_ashlsi3 (tmp1, high_src, operands[2]));
+ emit_insn (gen_iorsi3 (high_dst, tmp0, tmp1));
+ emit_move_insn (operands[0], dst);
+ DONE;
+}")
+
(define_insn "ashldi3_media"
[(set (match_operand:DI 0 "arith_reg_dest" "=r,r")
(ashift:DI (match_operand:DI 1 "arith_reg_operand" "r,r")
@@ -3882,8 +3910,19 @@ label:
emit_insn (gen_ashldi3_media (operands[0], operands[1], operands[2]));
DONE;
}
- if (GET_CODE (operands[2]) != CONST_INT
- || INTVAL (operands[2]) != 1)
+ if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) == 1)
+ {
+ emit_insn (gen_ashldi3_k (operands[0], operands[1]));
+ DONE;
+ }
+ else if (GET_CODE (operands[2]) == CONST_INT
+ && INTVAL (operands[2]) < 32)
+ {
+ emit_insn (gen_ashldi3_std (operands[0], operands[1], operands[2]));
+ DONE;
+ }
+ else
FAIL;
}")
@@ -9109,16 +9148,6 @@ mov.l\\t1f,r0\\n\\
"movt %0"
[(set_attr "type" "arith")])
-;; complements the T bit and stores the result in a register
-(define_insn "movrt"
- [(set (match_operand:SI 0 "arith_reg_dest" "=r")
- (if_then_else (eq:SI (reg:SI T_REG) (const_int 0))
- (const_int 1)
- (const_int 0)))]
- "TARGET_SH2A"
- "movrt\\t%0"
- [(set_attr "type" "arith")])
-
(define_expand "cstore4_media"
[(set (match_operand:SI 0 "register_operand" "=r")
(match_operator:SI 1 "sh_float_comparison_operator"
diff --git a/gcc/config/sh/t-sh b/gcc/config/sh/t-sh
index 07481bcc342..216a86b0090 100644
--- a/gcc/config/sh/t-sh
+++ b/gcc/config/sh/t-sh
@@ -19,7 +19,8 @@
sh-c.o: $(srcdir)/config/sh/sh-c.c \
$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) $(TM_P_H) coretypes.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/sh/sh-c.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/sh/sh-c.c
LIB1ASMSRC = sh/lib1funcs.asm
LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movmem \
diff --git a/gcc/config/sh/t-symbian b/gcc/config/sh/t-symbian
index 03f84edcf82..1698b722edc 100644
--- a/gcc/config/sh/t-symbian
+++ b/gcc/config/sh/t-symbian
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2006, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2006, 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -18,7 +18,8 @@
sh-c.o: $(srcdir)/config/sh/sh-c.c \
$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(TM_H) $(TM_P_H) coretypes.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/sh/sh-c.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/sh/sh-c.c
LIB1ASMSRC = sh/lib1funcs.asm
LIB1ASMFUNCS = _ashiftrt _ashiftrt_n _ashiftlt _lshiftrt _movstr \
@@ -49,7 +50,8 @@ gt-sh.h : s-gtype ; @true
symbian.o: $(srcdir)/config/sh/symbian.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(RTL_H) output.h flags.h $(TREE_H) expr.h toplev.h $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/sh/symbian.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/sh/symbian.c
# Local Variables:
diff --git a/gcc/config/spu/t-spu-elf b/gcc/config/spu/t-spu-elf
index 0a36e959c5b..0c9236fa89f 100644
--- a/gcc/config/spu/t-spu-elf
+++ b/gcc/config/spu/t-spu-elf
@@ -1,4 +1,4 @@
-# Copyright (C) 2006, 2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
#
# This file 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
@@ -91,5 +91,5 @@ spu-c.o: $(srcdir)/config/spu/spu-c.c \
$(srcdir)/config/spu/spu-protos.h \
$(CONFIG_H) $(SYSTEM_H) $(TREE_H) $(CPPLIB_H) \
$(TM_P_H) c-pragma.h coretypes.h $(TM_H) insn-codes.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/spu/spu-c.c
-
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/spu/spu-c.c
diff --git a/gcc/config/t-darwin b/gcc/config/t-darwin
index 09e63dded26..49dfa2ecce8 100644
--- a/gcc/config/t-darwin
+++ b/gcc/config/t-darwin
@@ -1,5 +1,5 @@
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007,
-# 2008 Free Software Foundation, Inc.
+# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+# Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -22,22 +22,24 @@ darwin.o: $(srcdir)/config/darwin.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
conditions.h insn-flags.h output.h insn-attr.h flags.h $(TREE_H) expr.h \
reload.h function.h $(GGC_H) langhooks.h $(TARGET_H) $(TM_P_H) gt-darwin.h \
config/darwin-sections.def
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/darwin.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/darwin.c
darwin-c.o: $(srcdir)/config/darwin-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(CPPLIB_H) $(TREE_H) c-pragma.h $(C_TREE_H) toplev.h $(TM_P_H) \
incpath.h flags.h $(C_COMMON_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/darwin-c.c $(PREPROCESSOR_DEFINES)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/darwin-c.c $(PREPROCESSOR_DEFINES)
darwin-f.o: $(srcdir)/config/darwin-f.c $(CONFIG_H) $(SYSTEM_H) coretypes.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/darwin-f.c $(PREPROCESSOR_DEFINES)
gt-darwin.h : s-gtype ; @true
darwin-driver.o: $(srcdir)/config/darwin-driver.c \
$(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/darwin-driver.c
# How to build crt3.o
diff --git a/gcc/config/t-sol2 b/gcc/config/t-sol2
index a8c44a68ed3..28aa8651f25 100644
--- a/gcc/config/t-sol2
+++ b/gcc/config/t-sol2
@@ -1,4 +1,4 @@
-# Copyright (C) 2004, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2004, 2008, 2009 Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -20,11 +20,11 @@
sol2-c.o: $(srcdir)/config/sol2-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
tree.h c-format.h intl.h $(CPPLIB_H) c-pragma.h $(TM_H) $(TM_P_H) \
toplev.h $(C_COMMON_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/sol2-c.c
# Solaris-specific attributes
sol2.o: $(srcdir)/config/sol2.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
tree.h $(TM_H) $(TM_P_H) toplev.h $(GGC_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/sol2.c
diff --git a/gcc/config/t-vxworks b/gcc/config/t-vxworks
index 62cfb5b31a7..42eab72771f 100644
--- a/gcc/config/t-vxworks
+++ b/gcc/config/t-vxworks
@@ -50,4 +50,4 @@ EXTRA_MULTILIB_PARTS =
vxworks.o: $(srcdir)/config/vxworks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TARGET_H) toplev.h output.h $(TM_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/v850/t-v850 b/gcc/config/v850/t-v850
index eca4c5cd59e..5c893d802e3 100644
--- a/gcc/config/v850/t-v850
+++ b/gcc/config/v850/t-v850
@@ -1,5 +1,5 @@
-# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003,
-# 2008 Free Software Foundation, Inc.
+# Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2008, 2009
+# Free Software Foundation, Inc.
#
# This file is part of GCC.
#
@@ -109,7 +109,8 @@ TCFLAGS = -mno-app-regs -msmall-sld -Wa,-mwarn-signed-overflow -Wa,-mwarn-unsign
v850-c.o: $(srcdir)/config/v850/v850-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(CPPLIB_H) $(TREE_H) c-pragma.h toplev.h $(GGC_H) $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/v850/v850-c.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/v850/v850-c.c
# Local Variables:
# mode: Makefile
diff --git a/gcc/config/v850/t-v850e b/gcc/config/v850/t-v850e
index 1cfef87807b..9fcd897bb17 100644
--- a/gcc/config/v850/t-v850e
+++ b/gcc/config/v850/t-v850e
@@ -107,7 +107,8 @@ TCFLAGS = -mno-app-regs -msmall-sld -Wa,-mwarn-signed-overflow -Wa,-mwarn-unsign
v850-c.o: $(srcdir)/config/v850/v850-c.c $(CONFIG_H) $(SYSTEM_H) coretypes.h \
$(TM_H) $(CPPLIB_H) $(TREE_H) c-pragma.h toplev.h $(GGC_H) $(TM_P_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(srcdir)/config/v850/v850-c.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(srcdir)/config/v850/v850-c.c
# Local Variables:
# mode: Makefile
diff --git a/gcc/config/vax/vax.c b/gcc/config/vax/vax.c
index f0f6a936407..a783b6f7131 100644
--- a/gcc/config/vax/vax.c
+++ b/gcc/config/vax/vax.c
@@ -133,7 +133,7 @@ vax_output_function_prologue (FILE * file, HOST_WIDE_INT size)
if (dwarf2out_do_frame ())
{
- const char *label = dwarf2out_cfi_label ();
+ const char *label = dwarf2out_cfi_label (false);
int offset = 0;
for (regno = FIRST_PSEUDO_REGISTER-1; regno >= 0; --regno)
diff --git a/gcc/config/x-darwin b/gcc/config/x-darwin
index c2ffd7d5c89..f671d911f0d 100644
--- a/gcc/config/x-darwin
+++ b/gcc/config/x-darwin
@@ -1,3 +1,3 @@
host-darwin.o : $(srcdir)/config/host-darwin.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h toplev.h config/host-darwin.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
diff --git a/gcc/config/x-hpux b/gcc/config/x-hpux
index fa0c5553c3d..e9f2f18f1b8 100644
--- a/gcc/config/x-hpux
+++ b/gcc/config/x-hpux
@@ -1,4 +1,4 @@
host-hpux.o : $(srcdir)/config/host-hpux.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h hosthooks.h hosthooks-def.h $(HOOKS_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/host-hpux.c
diff --git a/gcc/config/x-linux b/gcc/config/x-linux
index e4aa040bceb..f87a45b24d9 100644
--- a/gcc/config/x-linux
+++ b/gcc/config/x-linux
@@ -1,4 +1,4 @@
host-linux.o : $(srcdir)/config/host-linux.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h hosthooks.h hosthooks-def.h $(HOOKS_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/host-linux.c
diff --git a/gcc/config/x-solaris b/gcc/config/x-solaris
index 59c7bf61f5c..3e99df65748 100644
--- a/gcc/config/x-solaris
+++ b/gcc/config/x-solaris
@@ -1,4 +1,4 @@
host-solaris.o : $(srcdir)/config/host-solaris.c $(CONFIG_H) $(SYSTEM_H) \
coretypes.h hosthooks.h hosthooks-def.h $(HOOKS_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
$(srcdir)/config/host-solaris.c
diff --git a/gcc/configure b/gcc/configure
index bf6ae1b62b9..3b85619a2b5 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -23282,6 +23282,44 @@ fi
i[34567]86-*-* | x86_64-*-*)
case $target_os in
cygwin* | pe | mingw32*)
+ # Recent binutils allows the three-operand form of ".comm" on PE. This
+ # definition is used unconditionally to initialise the default state of
+ # the target option variable that governs usage of the feature.
+ echo "$as_me:$LINENO: checking assembler for .comm with alignment" >&5
+echo $ECHO_N "checking assembler for .comm with alignment... $ECHO_C" >&6
+if test "${gcc_cv_as_comm_has_align+set}" = set; then
+ echo $ECHO_N "(cached) $ECHO_C" >&6
+else
+ gcc_cv_as_comm_has_align=no
+ if test $in_tree_gas = yes; then
+ if test $gcc_cv_gas_vers -ge `expr \( \( 2 \* 1000 \) + 19 \) \* 1000 + 52`
+ then gcc_cv_as_comm_has_align=yes
+fi
+ elif test x$gcc_cv_as != x; then
+ echo '.comm foo,1,32' > conftest.s
+ if { ac_try='$gcc_cv_as -o conftest.o conftest.s >&5'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }
+ then
+ gcc_cv_as_comm_has_align=yes
+ else
+ echo "configure: failed program was" >&5
+ cat conftest.s >&5
+ fi
+ rm -f conftest.o conftest.s
+ fi
+fi
+echo "$as_me:$LINENO: result: $gcc_cv_as_comm_has_align" >&5
+echo "${ECHO_T}$gcc_cv_as_comm_has_align" >&6
+
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_GAS_ALIGNED_COMM `if test $gcc_cv_as_comm_has_align = yes; then echo 1; else echo 0; fi`
+_ACEOF
+
# Used for DWARF 2 in PE
echo "$as_me:$LINENO: checking assembler for .secrel32 relocs" >&5
echo $ECHO_N "checking assembler for .secrel32 relocs... $ECHO_C" >&6
@@ -25453,6 +25491,14 @@ fi
+case "${GMPLIBS}" in
+ *-lmpc*)
+cat >>confdefs.h <<\_ACEOF
+#define HAVE_mpc 1
+_ACEOF
+ ;;
+esac
+
diff --git a/gcc/configure.ac b/gcc/configure.ac
index ffd76392461..4c7d798814a 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -3265,6 +3265,15 @@ changequote(,)dnl
changequote([,])dnl
case $target_os in
cygwin* | pe | mingw32*)
+ # Recent binutils allows the three-operand form of ".comm" on PE. This
+ # definition is used unconditionally to initialise the default state of
+ # the target option variable that governs usage of the feature.
+ gcc_GAS_CHECK_FEATURE([.comm with alignment], gcc_cv_as_comm_has_align,
+ [2,19,52],,[.comm foo,1,32])
+ AC_DEFINE_UNQUOTED(HAVE_GAS_ALIGNED_COMM,
+ [`if test $gcc_cv_as_comm_has_align = yes; then echo 1; else echo 0; fi`],
+ [Define if your assembler supports specifying the alignment
+ of objects allocated using the GAS .comm command.])
# Used for DWARF 2 in PE
gcc_GAS_CHECK_FEATURE([.secrel32 relocs],
gcc_cv_as_ix86_pe_secrel32,
@@ -4342,6 +4351,10 @@ fi
AC_ARG_VAR(GMPLIBS,[How to link GMP])
AC_ARG_VAR(GMPINC,[How to find GMP include files])
+case "${GMPLIBS}" in
+ *-lmpc*) AC_DEFINE(HAVE_mpc, 1, [Define if mpc is in use.]) ;;
+esac
+
AC_ARG_VAR(PPLLIBS,[How to link PPL])
AC_ARG_VAR(PPLINC,[How to find PPL include files])
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7e22a4f2968..8472f0ce7b1 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,98 @@
+2009-06-02 Mark Mitchell <mark@codesourcery.com>
+
+ * decl.c (maybe_deduce_size_from_array_init): Use relayout_decl.
+
+2009-06-02 Jason Merrill <jason@redhat.com>
+
+ PR c++/40308
+ PR c++/40311
+ * typeck.c (cp_build_modify_expr): Always pass init-lists to the
+ conversion code.
+ * call.c (implicit_conversion): Allow init-list conversion to scalar
+ during direct-initialization, too. Mark the conversion bad if it
+ has too many levels of braces.
+ (convert_like_real): And give a helpful error.
+
+ PR c++/40306
+ PR c++/40307
+ * decl.c (cp_finish_decl): Handle auto deduction from ().
+ * typeck.c (build_x_indirect_ref): Handle dereferencing an operand
+ with dependent type that is known to be a pointer.
+
+2009-06-02 Simon Martin <simartin@users.sourceforge.net>
+
+ PR c++/38089
+ * pt.c (register_specialization): Properly setup DECL_CONTEXT for
+ specializations in an invalid namespace.
+
+2009-06-01 Aldy Hernandez <aldyh@redhat.com>
+
+ * error.c (print_instantiation_partial_context): Print column
+ numbers.
+
+2009-05-29 Ian Lance Taylor <iant@google.com>
+
+ * error.c (cp_printer): Don't use va_arg with enum type.
+
+2009-05-28 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/39754
+ * cp-tree.h (canonical_type_variant): Remove this function declaration.
+ (strip_typedefs): New function declaration.
+ * tree.c (strip_typedefs): New function definition.
+ (canonical_type_variant): Remove function definition.
+ * cvt.c (convert_from_reference): No need to use
+ canonical_type_variant.
+ * typeck.c (cp_build_indirect_ref): Likewise.
+ * error.c (dump_template_bindings): Use strip_typedefs instead of
+ canonical_type_variant.
+ * pt.c (convert_template_argument, unify): Likewise.
+ * mangle.c (canonicalize_for_substitution): Don't use
+ canonical_type_variant.
+
+2009-05-27 Jason Merrill <jason@redhat.com>
+
+ * call.c (implicit_conversion): Handle conversion from
+ initializer-list to scalar.
+ (convert_like_real): Likewise. Avoid crashing on list
+ initialization with bad conversions.
+ (can_convert): Use LOOKUP_EXPLICIT.
+ (can_convert_arg_bad): Add flags parm.
+ * cp-tree.h: Adjust.
+ * typeck.c (convert_for_assignment): Pass flags.
+
+2009-05-27 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in (g++$(exeext)): Change $(COMPILER) to $(LINKER).
+ (cc1plus-dummy$(exeext), cc1plus$(exeext)): Likewise.
+
+2009-05-26 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in (g++spec.o): Use $(COMPILER).
+ (g++$(exeext), cc1plus-dummy$(exeext)): Likewise.
+ (cc1plus$(exeext)): Likewise.
+
+2009-05-26 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/40007
+ * cp-tree.h (MEMBER_TYPES_NEEDING_ACCESS_CHECK): Remove this accessor.
+ (TI_TYPEDEFS_NEEDING_ACCESS_CHECKING): New accessor.
+ (get_types_needing_access_check): Declare new entry point.
+ * pt.c (append_type_to_template_for_access_check_1,
+ get_types_needing_access_check): New functions.
+ (perform_typedefs_access_check): Accept FUNCTION_DECLs and
+ RECORD_TYPEs rather than TEMPLATE_DECLs. Use the new
+ get_types_needing_access_check, no more
+ MEMBER_TYPES_NEEDING_ACCESS_CHECK.
+ (instantiate_class_template): Set input_location to the source
+ location of the most specialized template definition.
+ Perform access check using the RECORD_TYPE of the template, not its
+ associated most generic TEMPLATE_DECL.
+ (append_type_to_template_for_access_check): Augment function
+ comments. Use the new get_types_needing_access_check, not
+ MEMBER_TYPE_NEEDING_ACCESS_CHECK. Use the new
+ append_type_to_template_for_access_check_1 subroutine.
+
2009-05-22 Jason Merrill <jason@redhat.com>
PR c++/38064
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index aadaae6e044..1396eb9ced2 100644
--- a/gcc/cp/Make-lang.in
+++ b/gcc/cp/Make-lang.in
@@ -1,6 +1,6 @@
# Top level -*- makefile -*- fragment for GNU C++.
# Copyright (C) 1994, 1995, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2007, 2008
+# 2005, 2007, 2008, 2009
# Free Software Foundation, Inc.
#This file is part of GCC.
@@ -54,13 +54,13 @@ c++: cc1plus$(exeext)
g++spec.o: $(srcdir)/cp/g++spec.c $(SYSTEM_H) coretypes.h $(TM_H) $(GCC_H) $(CONFIG_H)
(SHLIB_LINK='$(SHLIB_LINK)'; \
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
$(INCLUDES) $(srcdir)/cp/g++spec.c)
# Create the compiler driver for g++.
GXX_OBJS = $(GCC_OBJS) g++spec.o intl.o prefix.o version.o
g++$(exeext): $(GXX_OBJS) $(EXTRA_GCC_OBJS) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(GXX_OBJS) $(EXTRA_GCC_OBJS) $(LIBS)
# Create a version of the g++ driver which calls the cross-compiler.
@@ -92,7 +92,7 @@ c++_OBJS = $(CXX_OBJS) dummy-checksum.o cc1plus-checksum.o cp/g++spec.o
cp-warn = $(STRICT_WARN)
cc1plus-dummy$(exeext): $(CXX_OBJS) dummy-checksum.o $(BACKEND) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(CXX_OBJS) dummy-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
cc1plus-checksum.c : cc1plus-dummy$(exeext) build/genchecksum$(build_exeext)
@@ -101,7 +101,7 @@ cc1plus-checksum.c : cc1plus-dummy$(exeext) build/genchecksum$(build_exeext)
cc1plus-checksum.o : cc1plus-checksum.c
cc1plus$(exeext): $(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(CXX_OBJS) cc1plus-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
# Special build rules.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index a9c036746db..1ab27c738e2 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -1400,9 +1400,37 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
if (conv)
return conv;
- if (is_std_init_list (to) && expr
- && BRACE_ENCLOSED_INITIALIZER_P (expr))
- return build_list_conv (to, expr, flags);
+ if (expr && BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ if (is_std_init_list (to))
+ return build_list_conv (to, expr, flags);
+
+ /* Allow conversion from an initializer-list with one element to a
+ scalar type. */
+ if (SCALAR_TYPE_P (to))
+ {
+ int nelts = CONSTRUCTOR_NELTS (expr);
+ tree elt;
+
+ if (nelts == 0)
+ elt = integer_zero_node;
+ else if (nelts == 1)
+ elt = CONSTRUCTOR_ELT (expr, 0)->value;
+ else
+ elt = error_mark_node;
+
+ conv = implicit_conversion (to, TREE_TYPE (elt), elt,
+ c_cast_p, flags);
+ if (conv)
+ {
+ conv->check_narrowing = true;
+ if (BRACE_ENCLOSED_INITIALIZER_P (elt))
+ /* Too many levels of braces, i.e. '{{1}}'. */
+ conv->bad_p = true;
+ return conv;
+ }
+ }
+ }
if (expr != NULL_TREE
&& (MAYBE_CLASS_TYPE_P (from)
@@ -4669,12 +4697,21 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (convs->bad_p
&& convs->kind != ck_user
+ && convs->kind != ck_list
&& convs->kind != ck_ambig
&& convs->kind != ck_ref_bind
&& convs->kind != ck_rvalue
&& convs->kind != ck_base)
{
conversion *t = convs;
+
+ /* Give a helpful error if this is bad because of excess braces. */
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr)
+ && SCALAR_TYPE_P (totype)
+ && CONSTRUCTOR_NELTS (expr) > 0
+ && BRACE_ENCLOSED_INITIALIZER_P (CONSTRUCTOR_ELT (expr, 0)->value))
+ permerror (input_location, "too many braces around initializer for %qT", totype);
+
for (; t; t = convs->u.next)
{
if (t->kind == ck_user || !t->bad_p)
@@ -4748,6 +4785,17 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
return expr;
}
case ck_identity:
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr))
+ {
+ int nelts = CONSTRUCTOR_NELTS (expr);
+ if (nelts == 0)
+ expr = integer_zero_node;
+ else if (nelts == 1)
+ expr = CONSTRUCTOR_ELT (expr, 0)->value;
+ else
+ gcc_unreachable ();
+ }
+
if (type_unknown_p (expr))
expr = instantiate_type (totype, expr, complain);
/* Convert a constant to its underlying value, unless we are
@@ -7185,7 +7233,7 @@ tourney (struct z_candidate *candidates)
bool
can_convert (tree to, tree from)
{
- return can_convert_arg (to, from, NULL_TREE, LOOKUP_NORMAL);
+ return can_convert_arg (to, from, NULL_TREE, LOOKUP_IMPLICIT);
}
/* Returns nonzero if ARG (of type FROM) can be converted to TO. */
@@ -7213,7 +7261,7 @@ can_convert_arg (tree to, tree from, tree arg, int flags)
/* Like can_convert_arg, but allows dubious conversions as well. */
bool
-can_convert_arg_bad (tree to, tree from, tree arg)
+can_convert_arg_bad (tree to, tree from, tree arg, int flags)
{
conversion *t;
void *p;
@@ -7222,7 +7270,7 @@ can_convert_arg_bad (tree to, tree from, tree arg)
p = conversion_obstack_alloc (0);
/* Try to perform the conversion. */
t = implicit_conversion (to, from, arg, /*c_cast_p=*/false,
- LOOKUP_NORMAL);
+ flags);
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 5a32a90b312..e31726cfdb1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -2232,6 +2232,9 @@ extern void decl_shadowed_for_var_insert (tree, tree);
#define TI_TEMPLATE(NODE) (TREE_PURPOSE (NODE))
#define TI_ARGS(NODE) (TREE_VALUE (NODE))
#define TI_PENDING_TEMPLATE_FLAG(NODE) TREE_LANG_FLAG_1 (NODE)
+/* The list of typedefs - used in the template - that need
+ access checking at template instantiation time. */
+#define TI_TYPEDEFS_NEEDING_ACCESS_CHECKING(NODE) (TREE_CHAIN (NODE))
/* We use TREE_VECs to hold template arguments. If there is only one
level of template arguments, then the TREE_VEC contains the
@@ -3160,11 +3163,6 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
&& TREE_CODE (DECL_TEMPLATE_RESULT (NODE)) == TYPE_DECL \
&& !DECL_TEMPLATE_TEMPLATE_PARM_P (NODE))
-/* The chained list of typedefs that are referenced in templates.
- These typedefs need to be access checked at template instantiation time.
- There are put here at parsing time. */
-#define MEMBER_TYPES_NEEDING_ACCESS_CHECK(NODE) DECL_ACCESS (NODE)
-
/* Nonzero if NODE which declares a type. */
#define DECL_DECLARES_TYPE_P(NODE) \
(TREE_CODE (NODE) == TYPE_DECL || DECL_CLASS_TEMPLATE_P (NODE))
@@ -4193,7 +4191,7 @@ extern tree build_op_call (tree, VEC(tree,gc) **,
extern tree build_op_delete_call (enum tree_code, tree, tree, bool, tree, tree);
extern bool can_convert (tree, tree);
extern bool can_convert_arg (tree, tree, tree, int);
-extern bool can_convert_arg_bad (tree, tree, tree);
+extern bool can_convert_arg_bad (tree, tree, tree, int);
extern bool enforce_access (tree, tree, tree);
extern tree convert_default_arg (tree, tree, tree, int);
extern tree convert_arg_to_ellipsis (tree);
@@ -4572,6 +4570,7 @@ extern bool template_parameter_pack_p (const_tree);
extern tree make_pack_expansion (tree);
extern bool check_for_bare_parameter_packs (tree);
extern tree get_template_info (tree);
+extern tree get_types_needing_access_check (tree);
extern int template_class_depth (tree);
extern int is_specialization_of (tree, tree);
extern bool is_specialization_of_friend (tree, tree);
@@ -4828,7 +4827,7 @@ extern void init_tree (void);
extern int pod_type_p (const_tree);
extern bool class_tmpl_impl_spec_p (const_tree);
extern int zero_init_p (const_tree);
-extern tree canonical_type_variant (tree);
+extern tree strip_typedefs (tree);
extern tree copy_binfo (tree, tree, tree,
tree *, int);
extern int member_p (const_tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 3220fe676bc..596e81c9cce 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -508,7 +508,7 @@ convert_from_reference (tree val)
{
if (TREE_CODE (TREE_TYPE (val)) == REFERENCE_TYPE)
{
- tree t = canonical_type_variant (TREE_TYPE (TREE_TYPE (val)));
+ tree t = TREE_TYPE (TREE_TYPE (val));
tree ref = build1 (INDIRECT_REF, t, val);
/* We *must* set TREE_READONLY when dereferencing a pointer to const,
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index a626a71fc34..bf99b3d193a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4502,7 +4502,7 @@ maybe_deduce_size_from_array_init (tree decl, tree init)
cp_apply_type_quals_to_decl (cp_type_quals (TREE_TYPE (decl)), decl);
- layout_decl (decl, 0);
+ relayout_decl (decl);
}
}
@@ -5531,7 +5531,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
TREE_TYPE (decl) = error_mark_node;
return;
}
- else if (describable_type (init))
+ if (TREE_CODE (init) == TREE_LIST)
+ init = build_x_compound_expr_from_list (init, "initializer");
+ if (describable_type (init))
{
type = TREE_TYPE (decl) = do_auto_deduction (type, init, auto_node);
if (type == error_mark_node)
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 3c7a8d5c58e..7be241dd02e 100644
--- a/gcc/cp/error.c
+++ b/gcc/cp/error.c
@@ -322,7 +322,7 @@ dump_template_bindings (tree parms, tree args, VEC(tree,gc)* typenames)
t = tsubst (t, args, tf_none, NULL_TREE);
/* Strip typedefs. We can't just use TFF_CHASE_TYPEDEF because
pp_simple_type_specifier doesn't know about it. */
- t = canonical_type_variant (t);
+ t = strip_typedefs (t);
dump_type (t, TFF_PLAIN_IDENTIFIER);
}
}
@@ -2705,19 +2705,30 @@ print_instantiation_partial_context (diagnostic_context *context,
struct tinst_level *t, location_t loc)
{
expanded_location xloc;
+ const char *str;
for (; ; t = t->next)
{
xloc = expand_location (loc);
if (t == NULL)
break;
- pp_verbatim (context->printer, _("%s:%d: instantiated from %qs\n"),
- xloc.file, xloc.line,
- decl_as_string_translate (t->decl,
- TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE));
+ str = decl_as_string_translate (t->decl,
+ TFF_DECL_SPECIFIERS | TFF_RETURN_TYPE);
+ if (flag_show_column)
+ pp_verbatim (context->printer,
+ _("%s:%d:%d: instantiated from %qs\n"),
+ xloc.file, xloc.line, xloc.column, str);
+ else
+ pp_verbatim (context->printer,
+ _("%s:%d: instantiated from %qs\n"),
+ xloc.file, xloc.line, str);
loc = t->locus;
}
- pp_verbatim (context->printer, _("%s:%d: instantiated from here"),
- xloc.file, xloc.line);
+ if (flag_show_column)
+ pp_verbatim (context->printer, _("%s:%d:%d: instantiated from here"),
+ xloc.file, xloc.line, xloc.column);
+ else
+ pp_verbatim (context->printer, _("%s:%d: instantiated from here"),
+ xloc.file, xloc.line);
pp_base_newline (context->printer);
}
@@ -2761,8 +2772,8 @@ cp_printer (pretty_printer *pp, text_info *text, const char *spec,
const char *result;
tree t = NULL;
#define next_tree (t = va_arg (*text->args_ptr, tree))
-#define next_tcode va_arg (*text->args_ptr, enum tree_code)
-#define next_lang va_arg (*text->args_ptr, enum languages)
+#define next_tcode ((enum tree_code) va_arg (*text->args_ptr, int))
+#define next_lang ((enum languages) va_arg (*text->args_ptr, int))
#define next_int va_arg (*text->args_ptr, int)
if (precision != 0 || wide)
diff --git a/gcc/cp/mangle.c b/gcc/cp/mangle.c
index ff77981c264..c905304eac6 100644
--- a/gcc/cp/mangle.c
+++ b/gcc/cp/mangle.c
@@ -338,9 +338,14 @@ canonicalize_for_substitution (tree node)
/* For a TYPE_DECL, use the type instead. */
if (TREE_CODE (node) == TYPE_DECL)
node = TREE_TYPE (node);
- if (TYPE_P (node))
- node = canonical_type_variant (node);
-
+ if (TYPE_P (node)
+ && TYPE_CANONICAL (node) != node
+ && TYPE_MAIN_VARIANT (node) != node)
+ /* Here we want to strip the topmost typedef only.
+ We need to do that so is_std_substitution can do proper
+ name matching. */
+ node = cp_build_qualified_type (TYPE_MAIN_VARIANT (node),
+ cp_type_quals (node));
return node;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index f8a6e7ece6e..38e930b3035 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -175,6 +175,7 @@ static tree tsubst_copy (tree, tree, tsubst_flags_t, tree);
static tree tsubst_pack_expansion (tree, tree, tsubst_flags_t, tree);
static tree tsubst_decl (tree, tree, tsubst_flags_t);
static void perform_typedefs_access_check (tree tmpl, tree targs);
+static void append_type_to_template_for_access_check_1 (tree, tree, tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
@@ -1315,7 +1316,7 @@ register_specialization (tree spec, tree tmpl, tree args, bool is_friend)
template it is specializing. */
if (DECL_TEMPLATE_SPECIALIZATION (spec)
&& !check_specialization_namespace (tmpl))
- DECL_CONTEXT (spec) = FROB_CONTEXT (decl_namespace_context (tmpl));
+ DECL_CONTEXT (spec) = DECL_CONTEXT (tmpl);
if (!optimize_specialization_lookup_p (tmpl))
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
@@ -5072,7 +5073,7 @@ convert_template_argument (tree parm,
the typedef, which is confusing if those future uses do not
themselves also use the typedef. */
if (TYPE_P (val))
- val = canonical_type_variant (val);
+ val = strip_typedefs (val);
}
else
{
@@ -6941,10 +6942,12 @@ perform_typedefs_access_check (tree tmpl, tree targs)
{
tree t;
- if (!tmpl || TREE_CODE (tmpl) != TEMPLATE_DECL)
+ if (!tmpl
+ || (TREE_CODE (tmpl) != RECORD_TYPE
+ && TREE_CODE (tmpl) != FUNCTION_DECL))
return;
- for (t = MEMBER_TYPES_NEEDING_ACCESS_CHECK (tmpl); t; t = TREE_CHAIN (t))
+ for (t = get_types_needing_access_check (tmpl); t; t = TREE_CHAIN (t))
{
tree type_decl = TREE_PURPOSE (t);
tree type_scope = TREE_VALUE (t);
@@ -6957,7 +6960,8 @@ perform_typedefs_access_check (tree tmpl, tree targs)
if (uses_template_parms (type_scope))
type_scope = tsubst (type_scope, targs, tf_error, NULL_TREE);
- perform_or_defer_access_check (TYPE_BINFO (type_scope), type_decl, type_decl);
+ perform_or_defer_access_check (TYPE_BINFO (type_scope),
+ type_decl, type_decl);
}
}
@@ -7031,9 +7035,9 @@ instantiate_class_template (tree type)
SET_CLASSTYPE_INTERFACE_UNKNOWN (type);
- /* Set the input location to the template definition. This is needed
- if tsubsting causes an error. */
- typedecl = TYPE_MAIN_DECL (type);
+ /* Set the input location to the most specialized template definition.
+ This is needed if tsubsting causes an error. */
+ typedecl = TYPE_MAIN_DECL (pattern);
input_location = DECL_SOURCE_LOCATION (typedecl);
TYPE_HAS_USER_CONSTRUCTOR (type) = TYPE_HAS_USER_CONSTRUCTOR (pattern);
@@ -7439,8 +7443,8 @@ instantiate_class_template (tree type)
/* Some typedefs referenced from within the template code need to be access
checked at template instantiation time, i.e now. These types were
added to the template at parsing time. Let's get those and perform
- the acces checks then. */
- perform_typedefs_access_check (templ, args);
+ the access checks then. */
+ perform_typedefs_access_check (pattern, args);
perform_deferred_access_checks ();
pop_nested_class ();
pop_from_top_level ();
@@ -12163,7 +12167,7 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
checked at template instantiation time, i.e now. These types were
added to the template at parsing time. Let's get those and perfom
the acces checks then. */
- perform_typedefs_access_check (tmpl, targ_ptr);
+ perform_typedefs_access_check (DECL_TEMPLATE_RESULT (tmpl), targ_ptr);
perform_deferred_access_checks ();
pop_access_scope (fndecl);
pop_deferring_access_checks ();
@@ -13671,7 +13675,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
return 1;
/* Strip typedefs as in convert_template_argument. */
- arg = canonical_type_variant (arg);
+ arg = strip_typedefs (arg);
}
/* If ARG is a parameter pack or an expansion, we cannot unify
@@ -17267,33 +17271,108 @@ type_uses_auto (tree type)
return NULL_TREE;
}
+/* For a given template T, return the list of typedefs referenced
+ in T for which access check is needed at T instantiation time.
+ T is either a FUNCTION_DECL or a RECORD_TYPE.
+ Those typedefs were added to T by the function
+ append_type_to_template_for_access_check. */
+
+tree
+get_types_needing_access_check (tree t)
+{
+ tree ti, result = NULL_TREE;
+
+ if (!t || t == error_mark_node)
+ return t;
+
+ if (!(ti = get_template_info (t)))
+ return NULL_TREE;
+
+ if (TREE_CODE (t) == RECORD_TYPE || TREE_CODE (t) == FUNCTION_DECL)
+ {
+ if (!TI_TEMPLATE (ti))
+ return NULL_TREE;
+
+ result = TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti);
+ }
+
+ return result;
+}
+
+/* Append the typedef TYPE_DECL used in template T to a list of typedefs
+ tied to T. That list of typedefs will be access checked at
+ T instantiation time.
+ T is either a FUNCTION_DECL or a RECORD_TYPE.
+ TYPE_DECL is a TYPE_DECL node representing a typedef.
+ SCOPE is the scope through which TYPE_DECL is accessed.
+
+ This function is a subroutine of
+ append_type_to_template_for_access_check. */
+
+static void
+append_type_to_template_for_access_check_1 (tree t,
+ tree type_decl,
+ tree scope)
+{
+ tree ti;
+
+ if (!t || t == error_mark_node)
+ return;
+
+ gcc_assert ((TREE_CODE (t) == FUNCTION_DECL
+ || TREE_CODE (t) == RECORD_TYPE)
+ && type_decl
+ && TREE_CODE (type_decl) == TYPE_DECL
+ && scope);
+
+ if (!(ti = get_template_info (t)))
+ return;
+
+ gcc_assert (TI_TEMPLATE (ti));
+
+ TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti) =
+ tree_cons (type_decl, scope, TI_TYPEDEFS_NEEDING_ACCESS_CHECKING (ti));
+}
+
/* Append TYPE_DECL to the template TEMPL.
- TEMPL is either a class type or a FUNCTION_DECL associated
- to a TEMPLATE_DECL.
+ TEMPL is either a class type, a FUNCTION_DECL or a a TEMPLATE_DECL.
At TEMPL instanciation time, TYPE_DECL will be checked to see
- if it can be accessed through SCOPE. */
+ if it can be accessed through SCOPE.
+
+ e.g. consider the following code snippet:
+
+ class C
+ {
+ typedef int myint;
+ };
+
+ template<class U> struct S
+ {
+ C::myint mi;
+ };
+
+ S<char> s;
+
+ At S<char> instantiation time, we need to check the access of C::myint
+ In other words, we need to check the access of the myint typedef through
+ the C scope. For that purpose, this function will add the myint typedef
+ and the scope C through which its being accessed to a list of typedefs
+ tied to the template S. That list will be walked at template instantiation
+ time and access check performed on each typedefs it contains.
+ Note that this particular code snippet should yield an error because
+ myint is private to C. */
void
append_type_to_template_for_access_check (tree templ,
tree type_decl,
tree scope)
{
- tree node, templ_decl;
-
- gcc_assert (templ
- && get_template_info (templ)
- && TI_TEMPLATE (get_template_info (templ))
- && type_decl
- && (TREE_CODE (type_decl) == TYPE_DECL));
+ tree node;
- templ_decl = TI_TEMPLATE (get_template_info (templ));
- gcc_assert (templ_decl);
+ gcc_assert (type_decl && (TREE_CODE (type_decl) == TYPE_DECL));
- /* Make sure we don't append the type to the template twice.
- If this appears to be too slow, the
- MEMBER_TYPE_NEEDING_ACCESS_CHECK property
- of templ should be a hash table instead. */
- for (node = MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl);
+ /* Make sure we don't append the type to the template twice. */
+ for (node = get_types_needing_access_check (templ);
node;
node = TREE_CHAIN (node))
{
@@ -17304,9 +17383,7 @@ append_type_to_template_for_access_check (tree templ,
return;
}
- MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl) =
- tree_cons (type_decl, scope,
- MEMBER_TYPES_NEEDING_ACCESS_CHECK (templ_decl));
+ append_type_to_template_for_access_check_1 (templ, type_decl, scope);
}
#include "gt-cp-pt.h"
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index dece159f4e8..b40ef10d0e9 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -911,19 +911,111 @@ cp_build_qualified_type_real (tree type,
return result;
}
-/* Returns the canonical version of TYPE. In other words, if TYPE is
- a typedef, returns the underlying type. The cv-qualification of
- the type returned matches the type input; they will always be
- compatible types. */
+/* Builds a qualified variant of T that is not a typedef variant.
+ E.g. consider the following declarations:
+ typedef const int ConstInt;
+ typedef ConstInt* PtrConstInt;
+ If T is PtrConstInt, this function returns a type representing
+ const int*.
+ In other words, if T is a typedef, the function returns the underlying type.
+ The cv-qualification and attributes of the type returned match the
+ input type.
+ They will always be compatible types.
+ The returned type is built so that all of its subtypes
+ recursively have their typedefs stripped as well.
+
+ This is different from just returning TYPE_CANONICAL (T)
+ Because of several reasons:
+ * If T is a type that needs structural equality
+ its TYPE_CANONICAL (T) will be NULL.
+ * TYPE_CANONICAL (T) desn't carry type attributes
+ and looses template parameter names. */
tree
-canonical_type_variant (tree t)
+strip_typedefs (tree t)
{
- if (t == error_mark_node)
- return error_mark_node;
+ tree result = NULL, type = NULL, t0 = NULL;
+
+ if (!t || t == error_mark_node || t == TYPE_CANONICAL (t))
+ return t;
+
+ gcc_assert (TYPE_P (t));
+
+ switch (TREE_CODE (t))
+ {
+ case POINTER_TYPE:
+ type = strip_typedefs (TREE_TYPE (t));
+ result = build_pointer_type (type);
+ break;
+ case REFERENCE_TYPE:
+ type = strip_typedefs (TREE_TYPE (t));
+ result = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
+ break;
+ case OFFSET_TYPE:
+ t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t));
+ type = strip_typedefs (TREE_TYPE (t));
+ result = build_offset_type (t0, type);
+ break;
+ case RECORD_TYPE:
+ if (TYPE_PTRMEMFUNC_P (t))
+ {
+ t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t));
+ result = build_ptrmemfunc_type (t0);
+ }
+ break;
+ case ARRAY_TYPE:
+ type = strip_typedefs (TREE_TYPE (t));
+ t0 = strip_typedefs (TYPE_DOMAIN (t));;
+ result = build_cplus_array_type (type, t0);
+ break;
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ {
+ tree arg_types = NULL, arg_node, arg_type;
+ for (arg_node = TYPE_ARG_TYPES (t);
+ arg_node;
+ arg_node = TREE_CHAIN (arg_node))
+ {
+ if (arg_node == void_list_node)
+ break;
+ arg_type = strip_typedefs (TREE_VALUE (arg_node));
+ gcc_assert (arg_type);
+
+ arg_types =
+ tree_cons (TREE_PURPOSE (arg_node), arg_type, arg_types);
+ }
+
+ if (arg_types)
+ arg_types = nreverse (arg_types);
+
+ /* A list of parameters not ending with an ellipsis
+ must end with void_list_node. */
+ if (arg_node)
+ arg_types = chainon (arg_types, void_list_node);
- return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
+ type = strip_typedefs (TREE_TYPE (t));
+ if (TREE_CODE (t) == METHOD_TYPE)
+ {
+ tree class_type = TREE_TYPE (TREE_VALUE (arg_types));
+ gcc_assert (class_type);
+ result =
+ build_method_type_directly (class_type, type,
+ TREE_CHAIN (arg_types));
+ }
+ else
+ result = build_function_type (type,
+ arg_types);
+ }
+ break;
+ default:
+ break;
+ }
+
+ if (!result)
+ result = TYPE_MAIN_VARIANT (t);
+ return cp_build_qualified_type (result, cp_type_quals (t));
}
+
/* Makes a copy of BINFO and TYPE, which is to be inherited into a
graph dominated by T. If BINFO is NULL, TYPE is a dependent base,
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d7fddb11211..b384feae1a4 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -2449,6 +2449,10 @@ build_x_indirect_ref (tree expr, const char *errorstring,
if (processing_template_decl)
{
+ /* Retain the type if we know the operand is a pointer so that
+ describable_type doesn't make auto deduction break. */
+ if (TREE_TYPE (expr) && POINTER_TYPE_P (TREE_TYPE (expr)))
+ return build_min (INDIRECT_REF, TREE_TYPE (TREE_TYPE (expr)), expr);
if (type_dependent_expression_p (expr))
return build_min_nt (INDIRECT_REF, expr);
expr = build_non_dependent_expr (expr);
@@ -2494,12 +2498,8 @@ cp_build_indirect_ref (tree ptr, const char *errorstring,
/* [expr.unary.op]
If the type of the expression is "pointer to T," the type
- of the result is "T."
-
- We must use the canonical variant because certain parts of
- the back end, like fold, do pointer comparisons between
- types. */
- tree t = canonical_type_variant (TREE_TYPE (type));
+ of the result is "T." */
+ tree t = TREE_TYPE (type);
if (CONVERT_EXPR_P (ptr)
|| TREE_CODE (ptr) == VIEW_CONVERT_EXPR)
@@ -6081,8 +6081,11 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
if (modifycode == INIT_EXPR)
{
- if (TREE_CODE (rhs) == CONSTRUCTOR)
+ if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
+ /* Do the default thing. */;
+ else if (TREE_CODE (rhs) == CONSTRUCTOR)
{
+ /* Compound literal. */
if (! same_type_p (TREE_TYPE (rhs), lhstype))
/* Call convert to generate an error; see PR 11063. */
rhs = convert (lhstype, rhs);
@@ -6702,7 +6705,7 @@ convert_for_assignment (tree type, tree rhs,
We allow bad conversions here because by the time we get to this point
we are committed to doing the conversion. If we end up doing a bad
conversion, convert_like will complain. */
- if (!can_convert_arg_bad (type, rhstype, rhs))
+ if (!can_convert_arg_bad (type, rhstype, rhs, flags))
{
/* When -Wno-pmf-conversions is use, we just silently allow
conversions from pointers-to-members to plain pointers. If
diff --git a/gcc/cse.c b/gcc/cse.c
index a697ed428e0..8e37b64ecbb 100644
--- a/gcc/cse.c
+++ b/gcc/cse.c
@@ -502,6 +502,11 @@ struct table_elt
#define REGNO_QTY_VALID_P(N) (REG_QTY (N) >= 0)
+/* Compare table_elt X and Y and return true iff X is cheaper than Y. */
+
+#define CHEAPER(X, Y) \
+ (preferable ((X)->cost, (X)->regcost, (Y)->cost, (Y)->regcost) < 0)
+
static struct table_elt *table[HASH_SIZE];
/* Chain of `struct table_elt's made so far for this function
@@ -563,6 +568,8 @@ static void remove_pseudo_from_table (rtx, unsigned);
static struct table_elt *lookup (rtx, unsigned, enum machine_mode);
static struct table_elt *lookup_for_remove (rtx, unsigned, enum machine_mode);
static rtx lookup_as_function (rtx, enum rtx_code);
+static struct table_elt *insert_with_costs (rtx, struct table_elt *, unsigned,
+ enum machine_mode, int, int);
static struct table_elt *insert (rtx, struct table_elt *, unsigned,
enum machine_mode);
static void merge_equiv_classes (struct table_elt *, struct table_elt *);
@@ -1213,6 +1220,174 @@ insert_regs (rtx x, struct table_elt *classp, int modified)
return mention_regs (x);
}
+
+/* Compute upper and lower anchors for CST. Also compute the offset of CST
+ from these anchors/bases such that *_BASE + *_OFFS = CST. Return false iff
+ CST is equal to an anchor. */
+
+static bool
+compute_const_anchors (rtx cst,
+ HOST_WIDE_INT *lower_base, HOST_WIDE_INT *lower_offs,
+ HOST_WIDE_INT *upper_base, HOST_WIDE_INT *upper_offs)
+{
+ HOST_WIDE_INT n = INTVAL (cst);
+
+ *lower_base = n & ~(targetm.const_anchor - 1);
+ if (*lower_base == n)
+ return false;
+
+ *upper_base =
+ (n + (targetm.const_anchor - 1)) & ~(targetm.const_anchor - 1);
+ *upper_offs = n - *upper_base;
+ *lower_offs = n - *lower_base;
+ return true;
+}
+
+/* Insert the equivalence between ANCHOR and (REG + OFF) in mode MODE. */
+
+static void
+insert_const_anchor (HOST_WIDE_INT anchor, rtx reg, HOST_WIDE_INT offs,
+ enum machine_mode mode)
+{
+ struct table_elt *elt;
+ unsigned hash;
+ rtx anchor_exp;
+ rtx exp;
+
+ anchor_exp = GEN_INT (anchor);
+ hash = HASH (anchor_exp, mode);
+ elt = lookup (anchor_exp, hash, mode);
+ if (!elt)
+ elt = insert (anchor_exp, NULL, hash, mode);
+
+ exp = plus_constant (reg, offs);
+ /* REG has just been inserted and the hash codes recomputed. */
+ mention_regs (exp);
+ hash = HASH (exp, mode);
+
+ /* Use the cost of the register rather than the whole expression. When
+ looking up constant anchors we will further offset the corresponding
+ expression therefore it does not make sense to prefer REGs over
+ reg-immediate additions. Prefer instead the oldest expression. Also
+ don't prefer pseudos over hard regs so that we derive constants in
+ argument registers from other argument registers rather than from the
+ original pseudo that was used to synthesize the constant. */
+ insert_with_costs (exp, elt, hash, mode, COST (reg), 1);
+}
+
+/* The constant CST is equivalent to the register REG. Create
+ equivalences between the two anchors of CST and the corresponding
+ register-offset expressions using REG. */
+
+static void
+insert_const_anchors (rtx reg, rtx cst, enum machine_mode mode)
+{
+ HOST_WIDE_INT lower_base, lower_offs, upper_base, upper_offs;
+
+ if (!compute_const_anchors (cst, &lower_base, &lower_offs,
+ &upper_base, &upper_offs))
+ return;
+
+ /* Ignore anchors of value 0. Constants accessible from zero are
+ simple. */
+ if (lower_base != 0)
+ insert_const_anchor (lower_base, reg, -lower_offs, mode);
+
+ if (upper_base != 0)
+ insert_const_anchor (upper_base, reg, -upper_offs, mode);
+}
+
+/* We need to express ANCHOR_ELT->exp + OFFS. Walk the equivalence list of
+ ANCHOR_ELT and see if offsetting any of the entries by OFFS would create a
+ valid expression. Return the cheapest and oldest of such expressions. In
+ *OLD, return how old the resulting expression is compared to the other
+ equivalent expressions. */
+
+static rtx
+find_reg_offset_for_const (struct table_elt *anchor_elt, HOST_WIDE_INT offs,
+ unsigned *old)
+{
+ struct table_elt *elt;
+ unsigned idx;
+ struct table_elt *match_elt;
+ rtx match;
+
+ /* Find the cheapest and *oldest* expression to maximize the chance of
+ reusing the same pseudo. */
+
+ match_elt = NULL;
+ match = NULL_RTX;
+ for (elt = anchor_elt->first_same_value, idx = 0;
+ elt;
+ elt = elt->next_same_value, idx++)
+ {
+ if (match_elt && CHEAPER (match_elt, elt))
+ return match;
+
+ if (REG_P (elt->exp)
+ || (GET_CODE (elt->exp) == PLUS
+ && REG_P (XEXP (elt->exp, 0))
+ && GET_CODE (XEXP (elt->exp, 1)) == CONST_INT))
+ {
+ rtx x;
+
+ /* Ignore expressions that are no longer valid. */
+ if (!REG_P (elt->exp) && !exp_equiv_p (elt->exp, elt->exp, 1, false))
+ continue;
+
+ x = plus_constant (elt->exp, offs);
+ if (REG_P (x)
+ || (GET_CODE (x) == PLUS
+ && IN_RANGE (INTVAL (XEXP (x, 1)),
+ -targetm.const_anchor,
+ targetm.const_anchor - 1)))
+ {
+ match = x;
+ match_elt = elt;
+ *old = idx;
+ }
+ }
+ }
+
+ return match;
+}
+
+/* Try to express the constant SRC_CONST using a register+offset expression
+ derived from a constant anchor. Return it if successful or NULL_RTX,
+ otherwise. */
+
+static rtx
+try_const_anchors (rtx src_const, enum machine_mode mode)
+{
+ struct table_elt *lower_elt, *upper_elt;
+ HOST_WIDE_INT lower_base, lower_offs, upper_base, upper_offs;
+ rtx lower_anchor_rtx, upper_anchor_rtx;
+ rtx lower_exp = NULL_RTX, upper_exp = NULL_RTX;
+ unsigned lower_old, upper_old;
+
+ if (!compute_const_anchors (src_const, &lower_base, &lower_offs,
+ &upper_base, &upper_offs))
+ return NULL_RTX;
+
+ lower_anchor_rtx = GEN_INT (lower_base);
+ upper_anchor_rtx = GEN_INT (upper_base);
+ lower_elt = lookup (lower_anchor_rtx, HASH (lower_anchor_rtx, mode), mode);
+ upper_elt = lookup (upper_anchor_rtx, HASH (upper_anchor_rtx, mode), mode);
+
+ if (lower_elt)
+ lower_exp = find_reg_offset_for_const (lower_elt, lower_offs, &lower_old);
+ if (upper_elt)
+ upper_exp = find_reg_offset_for_const (upper_elt, upper_offs, &upper_old);
+
+ if (!lower_exp)
+ return upper_exp;
+ if (!upper_exp)
+ return lower_exp;
+
+ /* Return the older expression. */
+ return (upper_old > lower_old ? upper_exp : lower_exp);
+}
+
/* Look in or update the hash table. */
/* Remove table element ELT from use in the table.
@@ -1380,11 +1555,11 @@ lookup_as_function (rtx x, enum rtx_code code)
return 0;
}
-/* Insert X in the hash table, assuming HASH is its hash code
- and CLASSP is an element of the class it should go in
- (or 0 if a new class should be made).
- It is inserted at the proper position to keep the class in
- the order cheapest first.
+/* Insert X in the hash table, assuming HASH is its hash code and
+ CLASSP is an element of the class it should go in (or 0 if a new
+ class should be made). COST is the code of X and reg_cost is the
+ cost of registers in X. It is inserted at the proper position to
+ keep the class in the order cheapest first.
MODE is the machine-mode of X, or if X is an integer constant
with VOIDmode then MODE is the mode with which X will be used.
@@ -1404,11 +1579,9 @@ lookup_as_function (rtx x, enum rtx_code code)
If necessary, update table showing constant values of quantities. */
-#define CHEAPER(X, Y) \
- (preferable ((X)->cost, (X)->regcost, (Y)->cost, (Y)->regcost) < 0)
-
static struct table_elt *
-insert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mode)
+insert_with_costs (rtx x, struct table_elt *classp, unsigned int hash,
+ enum machine_mode mode, int cost, int reg_cost)
{
struct table_elt *elt;
@@ -1430,8 +1603,8 @@ insert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mo
elt->exp = x;
elt->canon_exp = NULL_RTX;
- elt->cost = COST (x);
- elt->regcost = approx_reg_cost (x);
+ elt->cost = cost;
+ elt->regcost = reg_cost;
elt->next_same_value = 0;
elt->prev_same_value = 0;
elt->next_same_hash = table[hash];
@@ -1566,6 +1739,17 @@ insert (rtx x, struct table_elt *classp, unsigned int hash, enum machine_mode mo
return elt;
}
+
+/* Wrap insert_with_costs by passing the default costs. */
+
+static struct table_elt *
+insert (rtx x, struct table_elt *classp, unsigned int hash,
+ enum machine_mode mode)
+{
+ return
+ insert_with_costs (x, classp, hash, mode, COST (x), approx_reg_cost (x));
+}
+
/* Given two equivalence classes, CLASS1 and CLASS2, put all the entries from
CLASS2 into CLASS1. This is done when we have reached an insn which makes
@@ -4253,6 +4437,7 @@ cse_insn (rtx insn)
rtx src_eqv_here;
rtx src_const = 0;
rtx src_related = 0;
+ bool src_related_is_const_anchor = false;
struct table_elt *src_const_elt = 0;
int src_cost = MAX_COST;
int src_eqv_cost = MAX_COST;
@@ -4602,6 +4787,19 @@ cse_insn (rtx insn)
}
#endif /* LOAD_EXTEND_OP */
+ /* Try to express the constant using a register+offset expression
+ derived from a constant anchor. */
+
+ if (targetm.const_anchor
+ && !src_related
+ && src_const
+ && GET_CODE (src_const) == CONST_INT)
+ {
+ src_related = try_const_anchors (src_const, mode);
+ src_related_is_const_anchor = src_related != NULL_RTX;
+ }
+
+
if (src == src_folded)
src_folded = 0;
@@ -4706,6 +4904,18 @@ cse_insn (rtx insn)
{
src_related_cost = COST (src_related);
src_related_regcost = approx_reg_cost (src_related);
+
+ /* If a const-anchor is used to synthesize a constant that
+ normally requires multiple instructions then slightly prefer
+ it over the original sequence. These instructions are likely
+ to become redundant now. We can't compare against the cost
+ of src_eqv_here because, on MIPS for example, multi-insn
+ constants have zero cost; they are assumed to be hoisted from
+ loops. */
+ if (src_related_is_const_anchor
+ && src_related_cost == src_cost
+ && src_eqv_here)
+ src_related_cost--;
}
}
@@ -5440,6 +5650,14 @@ cse_insn (rtx insn)
elt = insert (dest, sets[i].src_elt,
sets[i].dest_hash, GET_MODE (dest));
+ /* If this is a constant, insert the constant anchors with the
+ equivalent register-offset expressions using register DEST. */
+ if (targetm.const_anchor
+ && REG_P (dest)
+ && SCALAR_INT_MODE_P (GET_MODE (dest))
+ && GET_CODE (sets[i].src_elt->exp) == CONST_INT)
+ insert_const_anchors (dest, sets[i].src_elt->exp, GET_MODE (dest));
+
elt->in_memory = (MEM_P (sets[i].inner_dest)
&& !MEM_READONLY_P (sets[i].inner_dest));
diff --git a/gcc/dce.c b/gcc/dce.c
index abdd433cb0e..2d1bd7ada29 100644
--- a/gcc/dce.c
+++ b/gcc/dce.c
@@ -354,8 +354,8 @@ find_call_stack_args (rtx call_insn, bool do_mark, bool fast,
}
for (byte = off; byte < off + INTVAL (MEM_SIZE (mem)); byte++)
{
- gcc_assert (!bitmap_bit_p (sp_bytes, byte - min_sp_off));
- bitmap_set_bit (sp_bytes, byte - min_sp_off);
+ if (!bitmap_set_bit (sp_bytes, byte - min_sp_off))
+ gcc_unreachable ();
}
}
@@ -442,9 +442,8 @@ find_call_stack_args (rtx call_insn, bool do_mark, bool fast,
{
if (byte < min_sp_off
|| byte >= max_sp_off
- || !bitmap_bit_p (sp_bytes, byte - min_sp_off))
+ || !bitmap_clear_bit (sp_bytes, byte - min_sp_off))
break;
- bitmap_clear_bit (sp_bytes, byte - min_sp_off);
}
if (!deletable_insn_p (insn, fast, NULL))
diff --git a/gcc/df-core.c b/gcc/df-core.c
index c42b20f2ce7..8057b54df10 100644
--- a/gcc/df-core.c
+++ b/gcc/df-core.c
@@ -2120,7 +2120,13 @@ df_ref_debug (df_ref ref, FILE *file)
DF_REF_FLAGS (ref),
DF_REF_TYPE (ref));
if (DF_REF_LOC (ref))
- fprintf (file, "loc %p(%p) chain ", (void *)DF_REF_LOC (ref), (void *)*DF_REF_LOC (ref));
+ {
+ if (flag_dump_noaddr)
+ fprintf (file, "loc #(#) chain ");
+ else
+ fprintf (file, "loc %p(%p) chain ", (void *)DF_REF_LOC (ref),
+ (void *)*DF_REF_LOC (ref));
+ }
else
fprintf (file, "chain ");
df_chain_dump (DF_REF_CHAIN (ref), file);
diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c
index 704f00eb965..8c6726b2832 100644
--- a/gcc/diagnostic.c
+++ b/gcc/diagnostic.c
@@ -165,7 +165,7 @@ diagnostic_build_prefix (diagnostic_info *diagnostic)
return
(s.file == NULL
? build_message_string ("%s: %s", progname, text)
- : flag_show_column && s.column != 0
+ : flag_show_column
? build_message_string ("%s:%d:%d: %s", s.file, s.line, s.column, text)
: build_message_string ("%s:%d: %s", s.file, s.line, text));
}
@@ -247,9 +247,15 @@ diagnostic_report_current_module (diagnostic_context *context)
if (! MAIN_FILE_P (map))
{
map = INCLUDED_FROM (line_table, map);
- pp_verbatim (context->printer,
- "In file included from %s:%d",
- map->to_file, LAST_SOURCE_LINE (map));
+ if (flag_show_column)
+ pp_verbatim (context->printer,
+ "In file included from %s:%d:%d",
+ map->to_file,
+ LAST_SOURCE_LINE (map), LAST_SOURCE_COLUMN (map));
+ else
+ pp_verbatim (context->printer,
+ "In file included from %s:%d",
+ map->to_file, LAST_SOURCE_LINE (map));
while (! MAIN_FILE_P (map))
{
map = INCLUDED_FROM (line_table, map);
diff --git a/gcc/diagnostic.h b/gcc/diagnostic.h
index 63837c6d7f8..004fabd33d2 100644
--- a/gcc/diagnostic.h
+++ b/gcc/diagnostic.h
@@ -226,6 +226,7 @@ extern void print_generic_expr (FILE *, tree, int);
extern void print_generic_decl (FILE *, tree, int);
extern void debug_c_tree (tree);
extern void dump_omp_clauses (pretty_printer *, tree, int, int);
+extern void print_call_name (pretty_printer *, tree);
/* In gimple-pretty-print.c */
extern void debug_generic_expr (tree);
diff --git a/gcc/doc/contrib.texi b/gcc/doc/contrib.texi
index 2b9d735ab72..f8f09be0afb 100644
--- a/gcc/doc/contrib.texi
+++ b/gcc/doc/contrib.texi
@@ -156,6 +156,10 @@ Glenn Chambers for help with the GCJ FAQ@.
John-Marc Chandonia for various libgcj patches.
@item
+Denis Chertykov for contributed and maintain the AVR port, the first GCC port
+for an 8-bit architecture.
+
+@item
Scott Christley for his Objective-C contributions.
@item
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c6f60dad5de..69745080d48 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -275,7 +275,7 @@ Objective-C and Objective-C++ Dialects}.
@xref{Debugging Options,,Options for Debugging Your Program or GCC}.
@gccoptlist{-d@var{letters} -dumpspecs -dumpmachine -dumpversion @gol
-fdbg-cnt-list -fdbg-cnt=@var{counter-value-list} @gol
--fdump-noaddr -fdump-unnumbered @gol
+-fdump-noaddr -fdump-unnumbered -fdump-unnumbered-links @gol
-fdump-translation-unit@r{[}-@var{n}@r{]} @gol
-fdump-class-hierarchy@r{[}-@var{n}@r{]} @gol
-fdump-ipa-all -fdump-ipa-cgraph -fdump-ipa-inline @gol
@@ -594,21 +594,26 @@ Objective-C and Objective-C++ Dialects}.
@emph{IA-64 Options}
@gccoptlist{-mbig-endian -mlittle-endian -mgnu-as -mgnu-ld -mno-pic @gol
--mvolatile-asm-stop -mregister-names -mno-sdata @gol
--mconstant-gp -mauto-pic -minline-float-divide-min-latency @gol
+-mvolatile-asm-stop -mregister-names -msdata -mno-sdata @gol
+-mconstant-gp -mauto-pic -mfused-madd @gol
+-minline-float-divide-min-latency @gol
-minline-float-divide-max-throughput @gol
+-mno-inline-float-divide @gol
-minline-int-divide-min-latency @gol
-minline-int-divide-max-throughput @gol
+-mno-inline-int-divide @gol
-minline-sqrt-min-latency -minline-sqrt-max-throughput @gol
--mno-dwarf2-asm -mearly-stop-bits @gol
+-mno-inline-sqrt @gol
+-mdwarf2-asm -mearly-stop-bits @gol
-mfixed-range=@var{register-range} -mtls-size=@var{tls-size} @gol
--mtune=@var{cpu-type} -mt -pthread -milp32 -mlp64 @gol
--mno-sched-br-data-spec -msched-ar-data-spec -mno-sched-control-spec @gol
+-mtune=@var{cpu-type} -milp32 -mlp64 @gol
+-msched-br-data-spec -msched-ar-data-spec -msched-control-spec @gol
-msched-br-in-data-spec -msched-ar-in-data-spec -msched-in-control-spec @gol
--msched-ldc -mno-sched-control-ldc -mno-sched-spec-verbose @gol
--mno-sched-prefer-non-data-spec-insns @gol
--mno-sched-prefer-non-control-spec-insns @gol
--mno-sched-count-spec-in-critical-path}
+-msched-spec-ldc -msched-spec-control-ldc @gol
+-msched-prefer-non-data-spec-insns -msched-prefer-non-control-spec-insns @gol
+-msched-stop-bits-after-every-cycle -msched-count-spec-in-critical-path @gol
+-msel-sched-dont-check-control-spec -msched-fp-mem-deps-zero-cost @gol
+-msched-max-memory-insns-hard-limit -msched-max-memory-insns=@var{max-insns}}
@emph{M32R/D Options}
@gccoptlist{-m32r2 -m32rx -m32r @gol
@@ -3694,6 +3699,19 @@ Warn whenever a pointer is cast so as to remove a type qualifier from
the target type. For example, warn if a @code{const char *} is cast
to an ordinary @code{char *}.
+Also warn when making a cast which introduces a type qualifier in an
+unsafe way. For example, casting @code{char **} to @code{const char **}
+is unsafe, as in this example:
+
+@smallexample
+ /* p is char ** value. */
+ const char **q = (const char **) p;
+ /* Assignment of readonly string to const char * is OK. */
+ *q = "string";
+ /* Now char** pointer points to read-only memory. */
+ **p = 'b';
+@end smallexample
+
@item -Wcast-align
@opindex Wcast-align
@opindex Wno-cast-align
@@ -4929,6 +4947,12 @@ This makes it more feasible to use diff on debugging dumps for compiler
invocations with different options, in particular with and without
@option{-g}.
+@item -fdump-unnumbered-links
+@opindex fdump-unnumbered-links
+When doing debugging dumps (see @option{-d} option above), suppress
+instruction numbers for the links to the previous and next instructions
+in a sequence.
+
@item -fdump-translation-unit @r{(C++ only)}
@itemx -fdump-translation-unit-@var{options} @r{(C++ only)}
@opindex fdump-translation-unit
@@ -7312,19 +7336,6 @@ In each case, the @var{value} is an integer. The allowable choices for
@var{name} are given in the following table:
@table @gcctabopt
-@item sra-max-structure-size
-The maximum structure size, in bytes, at which the scalar replacement
-of aggregates (SRA) optimization will perform block copies. The
-default value, 0, implies that GCC will select the most appropriate
-size itself.
-
-@item sra-field-structure-ratio
-The threshold ratio (as a percentage) between instantiated fields and
-the complete structure size. We say that if the ratio of the number
-of bytes in instantiated fields to the number of bytes in the complete
-structure exceeds this parameter, then block copies are not used. The
-default is 75.
-
@item struct-reorg-cold-struct-ratio
The threshold ratio (as a percentage) between a structure frequency
and the frequency of the hottest structure in the program. This parameter
@@ -11728,6 +11739,10 @@ using the minimum latency algorithm.
Generate code for inline divides of floating point values
using the maximum throughput algorithm.
+@item -mno-inline-float-divide
+@opindex mno-inline-float-divide
+Do not generate inline code for divides of floating point values.
+
@item -minline-int-divide-min-latency
@opindex minline-int-divide-min-latency
Generate code for inline divides of integer values
@@ -11738,6 +11753,10 @@ using the minimum latency algorithm.
Generate code for inline divides of integer values
using the maximum throughput algorithm.
+@item -mno-inline-int-divide
+@opindex mno-inline-int-divide
+Do not generate inline code for divides of integer values.
+
@item -minline-sqrt-min-latency
@opindex minline-sqrt-min-latency
Generate code for inline square roots
@@ -11748,6 +11767,17 @@ using the minimum latency algorithm.
Generate code for inline square roots
using the maximum throughput algorithm.
+@item -mno-inline-sqrt
+@opindex mno-inline-sqrt
+Do not generate inline code for sqrt.
+
+@item -mfused-madd
+@itemx -mno-fused-madd
+@opindex mfused-madd
+@opindex mno-fused-madd
+Do (don't) generate code that uses the fused multiply/add or multiply/subtract
+instructions. The default is to use these instructions.
+
@item -mno-dwarf2-asm
@itemx -mdwarf2-asm
@opindex mno-dwarf2-asm
@@ -11781,15 +11811,6 @@ Specify bit size of immediate TLS offsets. Valid values are 14, 22, and
Tune the instruction scheduling for a particular CPU, Valid values are
itanium, itanium1, merced, itanium2, and mckinley.
-@item -mt
-@itemx -pthread
-@opindex mt
-@opindex pthread
-Add support for multithreading using the POSIX threads library. This
-option sets flags for both the preprocessor and linker. It does
-not affect the thread safety of object code produced by the compiler or
-that of libraries supplied with it. These are HP-UX specific flags.
-
@item -milp32
@itemx -mlp64
@opindex milp32
@@ -11854,31 +11875,6 @@ are dependent on the control speculative loads.
This is effective only with @option{-msched-control-spec} enabled.
The default is 'enable'.
-@item -msched-ldc
-@itemx -mno-sched-ldc
-@opindex msched-ldc
-@opindex mno-sched-ldc
-(En/Dis)able use of simple data speculation checks ld.c .
-If disabled, only chk.a instructions will be emitted to check
-data speculative loads.
-The default is 'enable'.
-
-@item -mno-sched-control-ldc
-@itemx -msched-control-ldc
-@opindex mno-sched-control-ldc
-@opindex msched-control-ldc
-(Dis/En)able use of ld.c instructions to check control speculative loads.
-If enabled, in case of control speculative load with no speculatively
-scheduled dependent instructions this load will be emitted as ld.sa and
-ld.c will be used to check it.
-The default is 'disable'.
-
-@item -mno-sched-spec-verbose
-@itemx -msched-spec-verbose
-@opindex mno-sched-spec-verbose
-@opindex msched-spec-verbose
-(Dis/En)able printing of the information about speculative motions.
-
@item -mno-sched-prefer-non-data-spec-insns
@itemx -msched-prefer-non-data-spec-insns
@opindex mno-sched-prefer-non-data-spec-insns
@@ -11906,6 +11902,43 @@ computation of the instructions priorities. This will make the use of the
speculation a bit more conservative.
The default is 'disable'.
+@item -msched-spec-ldc
+@opindex msched-spec-ldc
+Use a simple data speculation check. This option is on by default.
+
+@item -msched-control-spec-ldc
+@opindex msched-spec-ldc
+Use a simple check for control speculation. This option is on by default.
+
+@item -msched-stop-bits-after-every-cycle
+@opindex msched-stop-bits-after-every-cycle
+Place a stop bit after every cycle when scheduling. This option is on
+by default.
+
+@item -msched-fp-mem-deps-zero-cost
+@opindex msched-fp-mem-deps-zero-cost
+Assume that floating-point stores and loads are not likely to cause a conflict
+when placed into the same instruction group. This option is disabled by
+default.
+
+@item -msel-sched-dont-check-control-spec
+@opindex msel-sched-dont-check-control-spec
+Generate checks for control speculation in selective scheduling.
+This flag is disabled by default.
+
+@item -msched-max-memory-insns=@var{max-insns}
+@opindex msched-max-memory-insns
+Limit on the number of memory insns per instruction group, giving lower
+priority to subsequent memory insns attempting to schedule in the same
+instruction group. Frequently useful to prevent cache bank conflicts.
+The default value is 1.
+
+@item -msched-max-memory-insns-hard-limit
+@opindex msched-max-memory-insns-hard-limit
+Disallow more than `msched-max-memory-insns' in instruction group.
+Otherwise, limit is `soft' meaning that we would prefer non-memory operations
+when limit is reached but may still schedule memory operations.
+
@end table
@node M32C Options
@@ -15683,6 +15716,15 @@ This option is available for Cygwin and MinGW targets. It
specifies that a GUI application is to be generated by
instructing the linker to set the PE header subsystem type
appropriately.
+
+@item -mpe-aligned-commons
+@opindex mpe-aligned-commons
+This option is available for Cygwin and MinGW targets. It
+specifies that the GNU extension to the PE file format that
+permits the correct alignment of COMMON variables should be
+used when generating code. It will be enabled by default if
+GCC detects that the target assembler found during configuration
+supports the feature.
@end table
See also under @ref{i386 and x86-64 Options} for standard options.
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index cf5d2af1221..287619c404d 100644
--- a/gcc/doc/plugins.texi
+++ b/gcc/doc/plugins.texi
@@ -9,7 +9,7 @@
@section Loading Plugins
-Plugins are supported on platforms that support @option{-ld
+Plugins are supported on platforms that support @option{-ldl
-rdynamic}. They are loaded by the compiler using @code{dlopen}
and invoked at pre-determined locations in the compilation
process.
@@ -30,6 +30,8 @@ Plugins are activated by the compiler at specific events as defined in
call @code{register_callback} specifying the name of the event and
address of the callback function that will handle that event.
+The header @file{gcc-plugin.h} must be the first gcc header to be included.
+
@subsection Plugin initialization
Every plugin should export a function called @code{plugin_init} that
@@ -65,6 +67,25 @@ struct plugin_name_args
If initialization fails, @code{plugin_init} must return a non-zero
value. Otherwise, it should return 0.
+The version of the GCC compiler loading the plugin is described by the
+following structure:
+
+@smallexample
+struct plugin_gcc_version
+@{
+ const char *basever;
+ const char *datestamp;
+ const char *devphase;
+ const char *revision;
+ const char *configuration_arguments;
+@};
+@end smallexample
+
+The function @code{plugin_default_version_check} takes two pointers to
+such structure and compare them field by field. It can be used by the
+plugin's @code{plugin_init} function.
+
+
@subsection Plugin callbacks
Callback functions have the following prototype:
@@ -87,13 +108,20 @@ enum plugin_event
PLUGIN_FINISH_UNIT, /* Useful for summary processing. */
PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */
PLUGIN_FINISH, /* Called before GCC exits. */
+ PLUGIN_INFO, /* Information about the plugin. */
+ PLUGIN_GGC_START, /* Called at start of GCC Garbage Collection. */
+ PLUGIN_GGC_MARKING, /* Extend the GGC marking. */
+ PLUGIN_GGC_END, /* Called at end of GGC. */
+ PLUGIN_REGISTER_GGC_ROOTS, /* Register an extra GGC root table. */
PLUGIN_ATTRIBUTES, /* Called during attribute registration */
PLUGIN_EVENT_LAST /* Dummy event used for indexing callback
array. */
@};
@end smallexample
-To register a callback, the plugin calls @code{register_callback} with the arguments:
+
+To register a callback, the plugin calls @code{register_callback} with
+the arguments:
@itemize
@item @code{char *name}: Plugin name.
@@ -102,6 +130,9 @@ To register a callback, the plugin calls @code{register_callback} with the argum
@item @code{void *user_data}: Pointer to plugin-specific data.
@end itemize
+For the PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, and
+PLUGIN_REGISTER_GGC_ROOTS pseudo-events the @code{callback} should be
+null, and the @code{user_data} is specific.
@section Interacting with the pass manager
@@ -153,6 +184,50 @@ plugin_init (struct plugin_name_args *plugin_info,
...
@}
@end smallexample
+
+
+@section Interacting with the GCC Garbage Collector
+
+Some plugins may want to be informed when GGC (the GCC Garbage
+Collector) is running. They can register callbacks for the
+@code{PLUGIN_GGC_START} and @code{PLUGIN_GGC_END} events (for which
+the callback is called with a null @code{gcc_data}) to be notified of
+the start or end of the GCC garbage collection.
+
+Some plugins may need to have GGC mark additional data. This can be
+done by registering a callback (called with a null @code{gcc_data})
+for the @code{PLUGIN_GGC_MARKING} event. Such callbacks can call the
+@code{ggc_set_mark} routine, preferably thru the @code{ggc_mark} macro
+(and conversly, these routines should usually not be used in plugins
+outside of the @code{PLUGIN_GGC_MARKING} event).
+
+Some plugins may need to add extra GGC root tables, e.g. to handle
+their own @code{GTY}-ed data. This can be done with the
+@code{PLUGIN_REGISTER_GGC_ROOTS} pseudo-event with a null callback and the
+extra root table as @code{user_data}.
+
+You should understand the details of memory management inside GCC
+before using @code{PLUGIN_GGC_MARKING} or
+@code{PLUGIN_REGISTER_GGC_ROOTS}.
+
+
+@section Giving information about a plugin
+
+A plugin should give some information to the user about itself. This
+uses the following structure:
+
+@smallexample
+struct plugin_info
+@{
+ const char *version;
+ const char *help;
+@};
+@end smallexample
+
+Such a structure is passed as the @code{user_data} by the plugin's
+init routine using @code{register_callback} with the
+@code{PLUGIN_INFO} pseudo-event and a null callback.
+
@section Registering custom attributes
For analysis purposes it is useful to be able to add custom attributes.
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 67e1ca6d857..bc15583bfb0 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -7384,7 +7384,14 @@ outputting a single uninitialized variable.
A C statement (sans semicolon) to output to the stdio stream
@var{stream} the assembler definition of a common-label named
@var{name} whose size is @var{size} bytes. The variable @var{rounded}
-is the size rounded up to whatever alignment the caller wants.
+is the size rounded up to whatever alignment the caller wants. It is
+possible that @var{size} may be zero, for instance if a struct with no
+other member than a zero-length array is defined. In this case, the
+backend must output a symbol definition that allocates at least one
+byte, both so that the address of the resulting object does not compare
+equal to any other, and because some object formats cannot even express
+the concept of a zero-sized common symbol, as that is how they represent
+an ordinary undefined external.
Use the expression @code{assemble_name (@var{stream}, @var{name})} to
output the name itself; before and after that, output the additional
@@ -10852,3 +10859,21 @@ cannot safely move arguments from the registers in which they are passed
to the stack. Therefore, this hook should return true in general, but
false for naked functions. The default implementation always returns true.
@end deftypefn
+
+
+@deftypevr {Target Hook} {unsigned HOST_WIDE_INT} TARGET_CONST_ANCHOR
+On some architectures it can take multiple instructions to synthesize
+a constant. If there is another constant already in a register that
+is close enough in value then it is preferable that the new constant
+is computed from this register using immediate addition or
+substraction. We accomplish this through CSE. Besides the value of
+the constant we also add a lower and an upper constant anchor to the
+available expressions. These are then queried when encountering new
+constants. The anchors are computed by rounding the constant up and
+down to a multiple of the value of @code{TARGET_CONST_ANCHOR}.
+@code{TARGET_CONST_ANCHOR} should be the maximum positive value
+accepted by immediate-add plus one. We currently assume that the
+value of @code{TARGET_CONST_ANCHOR} is a power of 2. For example, on
+MIPS, where add-immediate takes a 16-bit signed value,
+@code{TARGET_CONST_ANCHOR} is set to @samp{0x8000}. The default value
+is zero, which disables this optimization. @end deftypevr
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index cb1b988906a..c23344430c9 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -247,7 +247,8 @@ typedef struct GTY(()) cfa_loc {
HOST_WIDE_INT offset;
HOST_WIDE_INT base_offset;
unsigned int reg;
- int indirect; /* 1 if CFA is accessed via a dereference. */
+ BOOL_BITFIELD indirect : 1; /* 1 if CFA is accessed via a dereference. */
+ BOOL_BITFIELD in_use : 1; /* 1 if a saved cfa is stored here. */
} dw_cfa_location;
/* All call frame descriptions (FDE's) in the GCC generated DWARF
@@ -404,7 +405,7 @@ static const char *dwarf_cfi_name (unsigned);
static dw_cfi_ref new_cfi (void);
static void add_cfi (dw_cfi_ref *, dw_cfi_ref);
static void add_fde_cfi (const char *, dw_cfi_ref);
-static void lookup_cfa_1 (dw_cfi_ref, dw_cfa_location *);
+static void lookup_cfa_1 (dw_cfi_ref, dw_cfa_location *, dw_cfa_location *);
static void lookup_cfa (dw_cfa_location *);
static void reg_save (const char *, unsigned, unsigned, HOST_WIDE_INT);
#ifdef DWARF2_UNWIND_INFO
@@ -668,7 +669,10 @@ add_cfi (dw_cfi_ref *list_head, dw_cfi_ref cfi)
/* When DRAP is used, CFA is defined with an expression. Redefine
CFA may lead to a different CFA value. */
- if (fde && fde->drap_reg != INVALID_REGNUM)
+ /* ??? Of course, this heuristic fails when we're annotating epilogues,
+ because of course we'll always want to redefine the CFA back to the
+ stack pointer on the way out. Where should we move this check? */
+ if (0 && fde && fde->drap_reg != INVALID_REGNUM)
switch (cfi->dw_cfi_opc)
{
case DW_CFA_def_cfa_register:
@@ -689,14 +693,15 @@ add_cfi (dw_cfi_ref *list_head, dw_cfi_ref cfi)
*p = cfi;
}
-/* Generate a new label for the CFI info to refer to. */
+/* Generate a new label for the CFI info to refer to. FORCE is true
+ if a label needs to be output even when using .cfi_* directives. */
char *
-dwarf2out_cfi_label (void)
+dwarf2out_cfi_label (bool force)
{
static char label[20];
- if (dwarf2out_do_cfi_asm ())
+ if (!force && dwarf2out_do_cfi_asm ())
{
/* In this case, we will be emitting the asm directive instead of
the label, so just return a placeholder to keep the rest of the
@@ -724,11 +729,59 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi)
{
if (label)
{
- output_cfi_directive (cfi);
+ dw_fde_ref fde = current_fde ();
+
+ gcc_assert (fde != NULL);
/* We still have to add the cfi to the list so that
- lookup_cfa works later on. */
- list_head = &current_fde ()->dw_fde_cfi;
+ lookup_cfa works later on. When -g2 and above we
+ even need to force emitting of CFI labels and
+ add to list a DW_CFA_set_loc for convert_cfa_to_fb_loc_list
+ purposes. */
+ switch (cfi->dw_cfi_opc)
+ {
+ case DW_CFA_def_cfa_offset:
+ case DW_CFA_def_cfa_offset_sf:
+ case DW_CFA_def_cfa_register:
+ case DW_CFA_def_cfa:
+ case DW_CFA_def_cfa_sf:
+ case DW_CFA_def_cfa_expression:
+ case DW_CFA_restore_state:
+ if (write_symbols != DWARF2_DEBUG
+ && write_symbols != VMS_AND_DWARF2_DEBUG)
+ break;
+ if (debug_info_level <= DINFO_LEVEL_TERSE)
+ break;
+
+ if (*label == 0 || strcmp (label, "<do not output>") == 0)
+ label = dwarf2out_cfi_label (true);
+
+ if (fde->dw_fde_current_label == NULL
+ || strcmp (label, fde->dw_fde_current_label) != 0)
+ {
+ dw_cfi_ref xcfi;
+
+ label = xstrdup (label);
+
+ /* Set the location counter to the new label. */
+ xcfi = new_cfi ();
+ /* It doesn't metter whether DW_CFA_set_loc
+ or DW_CFA_advance_loc4 is added here, those aren't
+ emitted into assembly, only looked up by
+ convert_cfa_to_fb_loc_list. */
+ xcfi->dw_cfi_opc = DW_CFA_set_loc;
+ xcfi->dw_cfi_oprnd1.dw_cfi_addr = label;
+ add_cfi (&fde->dw_fde_cfi, xcfi);
+ fde->dw_fde_current_label = label;
+ }
+ break;
+ default:
+ break;
+ }
+
+ output_cfi_directive (cfi);
+
+ list_head = &fde->dw_fde_cfi;
}
/* ??? If this is a CFI for the CIE, we don't emit. This
assumes that the standard CIE contents that the assembler
@@ -743,7 +796,7 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi)
gcc_assert (fde != NULL);
if (*label == 0)
- label = dwarf2out_cfi_label ();
+ label = dwarf2out_cfi_label (false);
if (fde->dw_fde_current_label == NULL
|| strcmp (label, fde->dw_fde_current_label) != 0)
@@ -774,7 +827,7 @@ add_fde_cfi (const char *label, dw_cfi_ref cfi)
/* Subroutine of lookup_cfa. */
static void
-lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc)
+lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc, dw_cfa_location *remember)
{
switch (cfi->dw_cfi_opc)
{
@@ -793,6 +846,18 @@ lookup_cfa_1 (dw_cfi_ref cfi, dw_cfa_location *loc)
case DW_CFA_def_cfa_expression:
get_cfa_from_loc_descr (loc, cfi->dw_cfi_oprnd1.dw_cfi_loc);
break;
+
+ case DW_CFA_remember_state:
+ gcc_assert (!remember->in_use);
+ *remember = *loc;
+ remember->in_use = 1;
+ break;
+ case DW_CFA_restore_state:
+ gcc_assert (remember->in_use);
+ *loc = *remember;
+ remember->in_use = 0;
+ break;
+
default:
break;
}
@@ -805,19 +870,19 @@ lookup_cfa (dw_cfa_location *loc)
{
dw_cfi_ref cfi;
dw_fde_ref fde;
+ dw_cfa_location remember;
+ memset (loc, 0, sizeof (*loc));
loc->reg = INVALID_REGNUM;
- loc->offset = 0;
- loc->indirect = 0;
- loc->base_offset = 0;
+ remember = *loc;
for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
- lookup_cfa_1 (cfi, loc);
+ lookup_cfa_1 (cfi, loc, &remember);
fde = current_fde ();
if (fde)
for (cfi = fde->dw_fde_cfi; cfi; cfi = cfi->dw_cfi_next)
- lookup_cfa_1 (cfi, loc);
+ lookup_cfa_1 (cfi, loc, &remember);
}
/* The current rule for calculating the DWARF2 canonical frame address. */
@@ -827,6 +892,9 @@ static dw_cfa_location cfa;
from the CFA. */
static dw_cfa_location cfa_store;
+/* The current save location around an epilogue. */
+static dw_cfa_location cfa_remember;
+
/* The running total of the size of arguments pushed onto the stack. */
static HOST_WIDE_INT args_size;
@@ -1212,8 +1280,7 @@ compute_barrier_args_size_1 (rtx insn, HOST_WIDE_INT cur_args_size,
if (! RTX_FRAME_RELATED_P (insn))
{
- if (prologue_epilogue_contains (insn)
- || sibcall_epilogue_contains (insn))
+ if (prologue_epilogue_contains (insn))
/* Nothing */;
else if (GET_CODE (PATTERN (insn)) == SET)
offset = stack_adjust_offset (PATTERN (insn), cur_args_size, 0);
@@ -1386,7 +1453,7 @@ dwarf2out_stack_adjust (rtx insn, bool after_p)
with this function. Proper support would require all frame-related
insns to be marked, and to be able to handle saving state around
epilogues textually in the middle of the function. */
- if (prologue_epilogue_contains (insn) || sibcall_epilogue_contains (insn))
+ if (prologue_epilogue_contains (insn))
return;
/* If INSN is an instruction from target of an annulled branch, the
@@ -1459,7 +1526,7 @@ dwarf2out_stack_adjust (rtx insn, bool after_p)
if (offset == 0)
return;
- label = dwarf2out_cfi_label ();
+ label = dwarf2out_cfi_label (false);
dwarf2out_args_size_adjust (offset, label);
}
@@ -1660,6 +1727,156 @@ reg_saved_in (rtx reg)
value, not an offset. */
static dw_cfa_location cfa_temp;
+/* A subroutine of dwarf2out_frame_debug, process a REG_DEF_CFA note. */
+
+static void
+dwarf2out_frame_debug_def_cfa (rtx pat, const char *label)
+{
+ memset (&cfa, 0, sizeof (cfa));
+
+ switch (GET_CODE (pat))
+ {
+ case PLUS:
+ cfa.reg = REGNO (XEXP (pat, 0));
+ cfa.offset = INTVAL (XEXP (pat, 1));
+ break;
+
+ case REG:
+ cfa.reg = REGNO (pat);
+ break;
+
+ default:
+ /* Recurse and define an expression. */
+ gcc_unreachable ();
+ }
+
+ def_cfa_1 (label, &cfa);
+}
+
+/* A subroutine of dwarf2out_frame_debug, process a REG_ADJUST_CFA note. */
+
+static void
+dwarf2out_frame_debug_adjust_cfa (rtx pat, const char *label)
+{
+ rtx src, dest;
+
+ gcc_assert (GET_CODE (pat) == SET);
+ dest = XEXP (pat, 0);
+ src = XEXP (pat, 1);
+
+ switch (GET_CODE (src))
+ {
+ case PLUS:
+ gcc_assert (REGNO (XEXP (src, 0)) == cfa.reg);
+ cfa.offset -= INTVAL (XEXP (src, 1));
+ break;
+
+ case REG:
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+
+ cfa.reg = REGNO (dest);
+ gcc_assert (cfa.indirect == 0);
+
+ def_cfa_1 (label, &cfa);
+}
+
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_OFFSET note. */
+
+static void
+dwarf2out_frame_debug_cfa_offset (rtx set, const char *label)
+{
+ HOST_WIDE_INT offset;
+ rtx src, addr, span;
+
+ src = XEXP (set, 1);
+ addr = XEXP (set, 0);
+ gcc_assert (MEM_P (addr));
+ addr = XEXP (addr, 0);
+
+ /* As documented, only consider extremely simple addresses. */
+ switch (GET_CODE (addr))
+ {
+ case REG:
+ gcc_assert (REGNO (addr) == cfa.reg);
+ offset = -cfa.offset;
+ break;
+ case PLUS:
+ gcc_assert (REGNO (XEXP (addr, 0)) == cfa.reg);
+ offset = INTVAL (XEXP (addr, 1)) - cfa.offset;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ span = targetm.dwarf_register_span (src);
+
+ /* ??? We'd like to use queue_reg_save, but we need to come up with
+ a different flushing heuristic for epilogues. */
+ if (!span)
+ reg_save (label, DWARF_FRAME_REGNUM (REGNO (src)), INVALID_REGNUM, offset);
+ else
+ {
+ /* We have a PARALLEL describing where the contents of SRC live.
+ Queue register saves for each piece of the PARALLEL. */
+ int par_index;
+ int limit;
+ HOST_WIDE_INT span_offset = offset;
+
+ gcc_assert (GET_CODE (span) == PARALLEL);
+
+ limit = XVECLEN (span, 0);
+ for (par_index = 0; par_index < limit; par_index++)
+ {
+ rtx elem = XVECEXP (span, 0, par_index);
+
+ reg_save (label, DWARF_FRAME_REGNUM (REGNO (elem)),
+ INVALID_REGNUM, span_offset);
+ span_offset += GET_MODE_SIZE (GET_MODE (elem));
+ }
+ }
+}
+
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_REGISTER note. */
+
+static void
+dwarf2out_frame_debug_cfa_register (rtx set, const char *label)
+{
+ rtx src, dest;
+ unsigned sregno, dregno;
+
+ src = XEXP (set, 1);
+ dest = XEXP (set, 0);
+
+ if (src == pc_rtx)
+ sregno = DWARF_FRAME_RETURN_COLUMN;
+ else
+ sregno = DWARF_FRAME_REGNUM (REGNO (src));
+
+ dregno = DWARF_FRAME_REGNUM (REGNO (dest));
+
+ /* ??? We'd like to use queue_reg_save, but we need to come up with
+ a different flushing heuristic for epilogues. */
+ reg_save (label, sregno, dregno, 0);
+}
+
+/* A subroutine of dwarf2out_frame_debug, process a REG_CFA_RESTORE note. */
+
+static void
+dwarf2out_frame_debug_cfa_restore (rtx reg, const char *label)
+{
+ dw_cfi_ref cfi = new_cfi ();
+ unsigned int regno = DWARF_FRAME_REGNUM (REGNO (reg));
+
+ cfi->dw_cfi_opc = (regno & ~0x3f ? DW_CFA_restore_extended : DW_CFA_restore);
+ cfi->dw_cfi_oprnd1.dw_cfi_reg_num = regno;
+
+ add_fde_cfi (label, cfi);
+}
+
/* Record call frame debugging information for an expression EXPR,
which either sets SP or FP (adjusting how we calculate the frame
address) or saves a register to the stack or another register.
@@ -2367,7 +2584,8 @@ void
dwarf2out_frame_debug (rtx insn, bool after_p)
{
const char *label;
- rtx src;
+ rtx note, n;
+ bool handled_one = false;
if (insn == NULL_RTX)
{
@@ -2411,16 +2629,159 @@ dwarf2out_frame_debug (rtx insn, bool after_p)
return;
}
- label = dwarf2out_cfi_label ();
- src = find_reg_note (insn, REG_FRAME_RELATED_EXPR, NULL_RTX);
- if (src)
- insn = XEXP (src, 0);
- else
- insn = PATTERN (insn);
+ label = dwarf2out_cfi_label (false);
+
+ for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
+ switch (REG_NOTE_KIND (note))
+ {
+ case REG_FRAME_RELATED_EXPR:
+ insn = XEXP (note, 0);
+ goto found;
+
+ case REG_CFA_DEF_CFA:
+ dwarf2out_frame_debug_def_cfa (XEXP (note, 0), label);
+ handled_one = true;
+ break;
+
+ case REG_CFA_ADJUST_CFA:
+ n = XEXP (note, 0);
+ if (n == NULL)
+ {
+ n = PATTERN (insn);
+ if (GET_CODE (n) == PARALLEL)
+ n = XVECEXP (n, 0, 0);
+ }
+ dwarf2out_frame_debug_adjust_cfa (n, label);
+ handled_one = true;
+ break;
+
+ case REG_CFA_OFFSET:
+ n = XEXP (note, 0);
+ if (n == NULL)
+ n = single_set (insn);
+ dwarf2out_frame_debug_cfa_offset (n, label);
+ handled_one = true;
+ break;
+
+ case REG_CFA_REGISTER:
+ n = XEXP (note, 0);
+ if (n == NULL)
+ {
+ n = PATTERN (insn);
+ if (GET_CODE (n) == PARALLEL)
+ n = XVECEXP (n, 0, 0);
+ }
+ dwarf2out_frame_debug_cfa_register (n, label);
+ handled_one = true;
+ break;
+
+ case REG_CFA_RESTORE:
+ n = XEXP (note, 0);
+ if (n == NULL)
+ {
+ n = PATTERN (insn);
+ if (GET_CODE (n) == PARALLEL)
+ n = XVECEXP (n, 0, 0);
+ n = XEXP (n, 0);
+ }
+ dwarf2out_frame_debug_cfa_restore (n, label);
+ handled_one = true;
+ break;
+
+ default:
+ break;
+ }
+ if (handled_one)
+ return;
+ insn = PATTERN (insn);
+ found:
dwarf2out_frame_debug_expr (insn, label);
}
+/* Determine if we need to save and restore CFI information around this
+ epilogue. If SIBCALL is true, then this is a sibcall epilogue. If
+ we do need to save/restore, then emit the save now, and insert a
+ NOTE_INSN_CFA_RESTORE_STATE at the appropriate place in the stream. */
+
+void
+dwarf2out_begin_epilogue (rtx insn)
+{
+ bool saw_frp = false;
+ rtx i;
+ dw_cfi_ref cfi;
+
+ /* Scan forward to the return insn, noticing if there are possible
+ frame related insns. */
+ for (i = NEXT_INSN (insn); i ; i = NEXT_INSN (i))
+ {
+ if (!INSN_P (i))
+ continue;
+
+ /* Look for both regular and sibcalls to end the block. */
+ if (returnjump_p (i))
+ break;
+ if (CALL_P (i) && SIBLING_CALL_P (i))
+ break;
+
+ if (RTX_FRAME_RELATED_P (i))
+ saw_frp = true;
+ }
+
+ /* If the port doesn't emit epilogue unwind info, we don't need a
+ save/restore pair. */
+ if (!saw_frp)
+ return;
+
+ /* Otherwise, search forward to see if the return insn was the last
+ basic block of the function. If so, we don't need save/restore. */
+ gcc_assert (i != NULL);
+ i = next_real_insn (i);
+ if (i == NULL)
+ return;
+
+ /* Insert the restore before that next real insn in the stream, and before
+ a potential NOTE_INSN_EPILOGUE_BEG -- we do need these notes to be
+ properly nested. This should be after any label or alignment. This
+ will be pushed into the CFI stream by the function below. */
+ while (1)
+ {
+ rtx p = PREV_INSN (i);
+ if (!NOTE_P (p))
+ break;
+ if (NOTE_KIND (p) == NOTE_INSN_BASIC_BLOCK)
+ break;
+ i = p;
+ }
+ emit_note_before (NOTE_INSN_CFA_RESTORE_STATE, i);
+
+ /* Emit the state save. */
+ cfi = new_cfi ();
+ cfi->dw_cfi_opc = DW_CFA_remember_state;
+ add_fde_cfi (dwarf2out_cfi_label (false), cfi);
+
+ /* And emulate the state save. */
+ gcc_assert (!cfa_remember.in_use);
+ cfa_remember = cfa;
+ cfa_remember.in_use = 1;
+}
+
+/* A "subroutine" of dwarf2out_begin_epilogue. Emit the restore required. */
+
+void
+dwarf2out_frame_debug_restore_state (void)
+{
+ dw_cfi_ref cfi = new_cfi ();
+ const char *label = dwarf2out_cfi_label (false);
+
+ cfi->dw_cfi_opc = DW_CFA_restore_state;
+ add_fde_cfi (label, cfi);
+
+ gcc_assert (cfa_remember.in_use);
+ cfa = cfa_remember;
+ cfa_remember.in_use = 0;
+}
+
#endif
/* Describe for the GTY machinery what parts of dw_cfi_oprnd1 are used. */
@@ -2434,6 +2795,8 @@ dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi)
{
case DW_CFA_nop:
case DW_CFA_GNU_window_save:
+ case DW_CFA_remember_state:
+ case DW_CFA_restore_state:
return dw_cfi_oprnd_unused;
case DW_CFA_set_loc:
@@ -2448,6 +2811,7 @@ dw_cfi_oprnd1_desc (enum dwarf_call_frame_info cfi)
case DW_CFA_def_cfa:
case DW_CFA_offset_extended_sf:
case DW_CFA_def_cfa_sf:
+ case DW_CFA_restore:
case DW_CFA_restore_extended:
case DW_CFA_undefined:
case DW_CFA_same_value:
@@ -2771,6 +3135,13 @@ output_cfi_directive (dw_cfi_ref cfi)
cfi->dw_cfi_oprnd1.dw_cfi_offset);
break;
+ case DW_CFA_remember_state:
+ fprintf (asm_out_file, "\t.cfi_remember_state\n");
+ break;
+ case DW_CFA_restore_state:
+ fprintf (asm_out_file, "\t.cfi_restore_state\n");
+ break;
+
case DW_CFA_GNU_args_size:
fprintf (asm_out_file, "\t.cfi_escape 0x%x,", DW_CFA_GNU_args_size);
dw2_asm_output_data_uleb128_raw (cfi->dw_cfi_oprnd1.dw_cfi_offset);
@@ -12056,6 +12427,7 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
dw_cfi_ref cfi;
dw_cfa_location last_cfa, next_cfa;
const char *start_label, *last_label, *section;
+ dw_cfa_location remember;
fde = current_fde ();
gcc_assert (fde != NULL);
@@ -12064,17 +12436,16 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
list_tail = &list;
list = NULL;
+ memset (&next_cfa, 0, sizeof (next_cfa));
next_cfa.reg = INVALID_REGNUM;
- next_cfa.offset = 0;
- next_cfa.indirect = 0;
- next_cfa.base_offset = 0;
+ remember = next_cfa;
start_label = fde->dw_fde_begin;
/* ??? Bald assumption that the CIE opcode list does not contain
advance opcodes. */
for (cfi = cie_cfi_head; cfi; cfi = cfi->dw_cfi_next)
- lookup_cfa_1 (cfi, &next_cfa);
+ lookup_cfa_1 (cfi, &next_cfa, &remember);
last_cfa = next_cfa;
last_label = start_label;
@@ -12101,14 +12472,10 @@ convert_cfa_to_fb_loc_list (HOST_WIDE_INT offset)
case DW_CFA_advance_loc:
/* The encoding is complex enough that we should never emit this. */
- case DW_CFA_remember_state:
- case DW_CFA_restore_state:
- /* We don't handle these two in this function. It would be possible
- if it were to be required. */
gcc_unreachable ();
default:
- lookup_cfa_1 (cfi, &next_cfa);
+ lookup_cfa_1 (cfi, &next_cfa, &remember);
break;
}
diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h
index 154bb143dbb..85c320dfbd5 100644
--- a/gcc/dwarf2out.h
+++ b/gcc/dwarf2out.h
@@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see
extern void dwarf2out_decl (tree);
extern void dwarf2out_frame_debug (rtx, bool);
+extern void dwarf2out_begin_epilogue (rtx);
+extern void dwarf2out_frame_debug_restore_state (void);
extern void debug_dwarf (void);
struct die_struct;
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 916774c659d..98fb243b612 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -3335,6 +3335,10 @@ try_split (rtx pat, rtx trial, int last)
rtx insn_last, insn;
int njumps = 0;
+ /* We're not good at redistributing frame information. */
+ if (RTX_FRAME_RELATED_P (trial))
+ return trial;
+
if (any_condjump_p (trial)
&& (note = find_reg_note (trial, REG_BR_PROB, 0)))
split_branch_probability = INTVAL (XEXP (note, 0));
@@ -5050,6 +5054,9 @@ copy_insn_1 (rtx orig)
RTX_CODE code;
const char *format_ptr;
+ if (orig == NULL)
+ return NULL;
+
code = GET_CODE (orig);
switch (code)
diff --git a/gcc/emutls.c b/gcc/emutls.c
index a9c7cf6954c..b7ee3bdfa7c 100644
--- a/gcc/emutls.c
+++ b/gcc/emutls.c
@@ -155,23 +155,23 @@ __emutls_get_address (struct __emutls_object *obj)
if (__builtin_expect (arr == NULL, 0))
{
pointer size = offset + 32;
- arr = calloc (size, sizeof (void *));
+ arr = calloc (size + 1, sizeof (void *));
if (arr == NULL)
abort ();
arr->size = size;
__gthread_setspecific (emutls_key, (void *) arr);
}
- else if (__builtin_expect (offset >= arr->size, 0))
+ else if (__builtin_expect (offset > arr->size, 0))
{
pointer orig_size = arr->size;
pointer size = orig_size * 2;
- if (offset >= size)
+ if (offset > size)
size = offset + 32;
- arr = realloc (arr, size * sizeof (void *));
+ arr = realloc (arr, (size + 1) * sizeof (void *));
if (arr == NULL)
abort ();
arr->size = size;
- memset (arr->data + orig_size - 1, 0,
+ memset (arr->data + orig_size, 0,
(size - orig_size) * sizeof (void *));
__gthread_setspecific (emutls_key, (void *) arr);
}
diff --git a/gcc/expr.c b/gcc/expr.c
index c2524f2ead5..1ecdb0277d2 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -6224,6 +6224,45 @@ component_ref_field_offset (tree exp)
else
return SUBSTITUTE_PLACEHOLDER_IN_EXPR (DECL_FIELD_OFFSET (field), exp);
}
+
+/* Alignment in bits the TARGET of an assignment may be assumed to have. */
+
+static unsigned HOST_WIDE_INT
+target_align (const_tree target)
+{
+ /* We might have a chain of nested references with intermediate misaligning
+ bitfields components, so need to recurse to find out. */
+
+ unsigned HOST_WIDE_INT this_align, outer_align;
+
+ switch (TREE_CODE (target))
+ {
+ case BIT_FIELD_REF:
+ return 1;
+
+ case COMPONENT_REF:
+ this_align = DECL_ALIGN (TREE_OPERAND (target, 1));
+ outer_align = target_align (TREE_OPERAND (target, 0));
+ return MIN (this_align, outer_align);
+
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ this_align = TYPE_ALIGN (TREE_TYPE (target));
+ outer_align = target_align (TREE_OPERAND (target, 0));
+ return MIN (this_align, outer_align);
+
+ CASE_CONVERT:
+ case NON_LVALUE_EXPR:
+ case VIEW_CONVERT_EXPR:
+ this_align = TYPE_ALIGN (TREE_TYPE (target));
+ outer_align = target_align (TREE_OPERAND (target, 0));
+ return MAX (this_align, outer_align);
+
+ default:
+ return TYPE_ALIGN (TREE_TYPE (target));
+ }
+}
+
/* Given an rtx VALUE that may contain additions and multiplications, return
an equivalent value that just refers to a register, memory, or constant.
@@ -6670,14 +6709,10 @@ highest_pow2_factor (const_tree exp)
static unsigned HOST_WIDE_INT
highest_pow2_factor_for_target (const_tree target, const_tree exp)
{
- unsigned HOST_WIDE_INT target_align, factor;
-
- factor = highest_pow2_factor (exp);
- if (TREE_CODE (target) == COMPONENT_REF)
- target_align = DECL_ALIGN_UNIT (TREE_OPERAND (target, 1));
- else
- target_align = TYPE_ALIGN_UNIT (TREE_TYPE (target));
- return MAX (factor, target_align);
+ unsigned HOST_WIDE_INT talign = target_align (target) / BITS_PER_UNIT;
+ unsigned HOST_WIDE_INT factor = highest_pow2_factor (exp);
+
+ return MAX (factor, talign);
}
/* Return &VAR expression for emulated thread local VAR. */
@@ -8248,7 +8283,8 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
}
if (!op0)
- op0 = expand_expr (TREE_OPERAND (exp, 0), NULL_RTX, mode, modifier);
+ op0 = expand_expr (TREE_OPERAND (exp, 0),
+ NULL_RTX, VOIDmode, modifier);
/* If the input and output modes are both the same, we are done. */
if (mode == GET_MODE (op0))
@@ -9042,12 +9078,7 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
case LTGT_EXPR:
temp = do_store_flag (exp,
modifier != EXPAND_STACK_PARM ? target : NULL_RTX,
- (tmode != VOIDmode
- /* do_store_flag does not handle target modes
- of a different class than the comparison mode.
- Avoid ICEing in convert_move. */
- && GET_MODE_CLASS (tmode) == GET_MODE_CLASS (mode))
- ? tmode : mode);
+ tmode != VOIDmode ? tmode : mode);
if (temp != 0)
return temp;
diff --git a/gcc/final.c b/gcc/final.c
index 2f68ee8431e..785b090685a 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -1879,9 +1879,19 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
break;
case NOTE_INSN_EPILOGUE_BEG:
+#if defined (DWARF2_UNWIND_INFO) && defined (HAVE_epilogue)
+ if (dwarf2out_do_frame ())
+ dwarf2out_begin_epilogue (insn);
+#endif
targetm.asm_out.function_begin_epilogue (file);
break;
+ case NOTE_INSN_CFA_RESTORE_STATE:
+#if defined (DWARF2_UNWIND_INFO)
+ dwarf2out_frame_debug_restore_state ();
+#endif
+ break;
+
case NOTE_INSN_FUNCTION_BEG:
app_disable ();
(*debug_hooks->end_prologue) (last_linenum, last_filename);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index e322ecb2cf8..03f68054f3a 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -10175,8 +10175,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
&& TREE_INT_CST_HIGH (tree11) == 0
&& ((TREE_INT_CST_LOW (tree01) + TREE_INT_CST_LOW (tree11))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (arg0, 0)))))
- return build2 (LROTATE_EXPR, type, TREE_OPERAND (arg0, 0),
- code0 == LSHIFT_EXPR ? tree01 : tree11);
+ return fold_convert (type,
+ build2 (LROTATE_EXPR,
+ TREE_TYPE (TREE_OPERAND (arg0, 0)),
+ TREE_OPERAND (arg0, 0),
+ code0 == LSHIFT_EXPR
+ ? tree01 : tree11));
else if (code11 == MINUS_EXPR)
{
tree tree110, tree111;
@@ -10190,10 +10194,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
(TREE_TYPE (TREE_OPERAND
(arg0, 0))))
&& operand_equal_p (tree01, tree111, 0))
- return build2 ((code0 == LSHIFT_EXPR
- ? LROTATE_EXPR
- : RROTATE_EXPR),
- type, TREE_OPERAND (arg0, 0), tree01);
+ return fold_convert (type,
+ build2 ((code0 == LSHIFT_EXPR
+ ? LROTATE_EXPR
+ : RROTATE_EXPR),
+ TREE_TYPE (TREE_OPERAND (arg0, 0)),
+ TREE_OPERAND (arg0, 0), tree01));
}
else if (code01 == MINUS_EXPR)
{
@@ -10208,10 +10214,12 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
(TREE_TYPE (TREE_OPERAND
(arg0, 0))))
&& operand_equal_p (tree11, tree011, 0))
- return build2 ((code0 != LSHIFT_EXPR
- ? LROTATE_EXPR
- : RROTATE_EXPR),
- type, TREE_OPERAND (arg0, 0), tree11);
+ return fold_convert (type,
+ build2 ((code0 != LSHIFT_EXPR
+ ? LROTATE_EXPR
+ : RROTATE_EXPR),
+ TREE_TYPE (TREE_OPERAND (arg0, 0)),
+ TREE_OPERAND (arg0, 0), tree11));
}
}
}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index 32c3192d297..533ac20a337 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,64 @@
+2009-06-01 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/40309
+ * trans-decl.c (gfc_sym_identifier): Use "MAIN__" for PROGRAM "main".
+ (create_main_function): Set main_identifier_node.
+
+2009-05-29 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/40019
+ * trans-types.c (gfc_build_uint_type): Make nonstatic.
+ * trans.h (gfor_fndecl_clz128, gfor_fndecl_ctz128): New prototypes.
+ * trans-types.h (gfc_build_uint_type): Add prototype.
+ * trans-decl.c (gfc_build_intrinsic_function_decls): Build
+ gfor_fndecl_clz128 and gfor_fndecl_ctz128.
+ * trans-intrinsic.c (gfc_conv_intrinsic_leadz,
+ gfc_conv_intrinsic_trailz): Call the right builtins or library
+ functions, and cast arguments to unsigned types first.
+ * simplify.c (gfc_simplify_leadz): Deal with negative arguments.
+
+2009-05-27 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in (gfortran$(exeext)): Change $(COMPILER) to
+ $(LINKER).
+ (f951$(exeext)): Likewise.
+
+2009-05-27 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/40270
+ * trans-decl.c (create_main_function): Mark MAIN__ and
+ argc/argv as TREE_USED and push/pop function_decl context
+ if needed.
+
+2009-05-26 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/39178
+ * gfortranspec.c (lang_specific_driver): Stop linking
+ libgfortranbegin.
+ * trans-decl.c (gfc_build_builtin_function_decls): Stop
+ making MAIN__ publicly visible.
+ (gfc_build_builtin_function_decls): Add
+ gfor_fndecl_set_args.
+ (create_main_function) New function.
+ (gfc_generate_function_code): Use it.
+
+2009-05-26 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/40246
+ * match.c (gfc_match_nullify): NULLify freed pointer.
+
+2009-05-26 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in (gfortranspec.o): Use $(COMPILER).
+ (gfortran$(exeext), f951$(exeext), fortran/cpp.o): Likewise.
+
+2009-05-26 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * gfortran.h (GFC_MPC_RND_MODE): New.
+ * simplify.c (call_mpc_func): New helper function.
+ (gfc_simplify_cos, gfc_simplify_exp, gfc_simplify_log,
+ gfc_simplify_sin, gfc_simplify_sqrt): Add MPC support.
+
2009-05-25 Janus Weil <janus@gcc.gnu.org>
PR fortran/40176
diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in
index 5885a621933..0ac9bb2262b 100644
--- a/gcc/fortran/Make-lang.in
+++ b/gcc/fortran/Make-lang.in
@@ -1,6 +1,6 @@
# -*- makefile -*-
# Top level makefile fragment for GNU gfortran, the GNU Fortran 95 compiler.
-# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software
+# Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software
# Foundation, Inc.
# Contributed by Paul Brook <paul@nowt.org
# and Steven Bosscher <s.bosscher@student.tudelft.nl>
@@ -80,13 +80,13 @@ fortran: f951$(exeext)
gfortranspec.o: $(srcdir)/fortran/gfortranspec.c $(SYSTEM_H) $(TM_H) $(GCC_H) \
$(CONFIG_H) coretypes.h intl.h
(SHLIB_LINK='$(SHLIB_LINK)'; \
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
$(INCLUDES) $(srcdir)/fortran/gfortranspec.c)
# Create the compiler driver gfortran.
GFORTRAN_D_OBJS = $(GCC_OBJS) gfortranspec.o version.o prefix.o intl.o
gfortran$(exeext): $(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(GFORTRAN_D_OBJS) $(EXTRA_GCC_OBJS) $(LIBS)
# Create a version of the gfortran driver which calls the cross-compiler.
@@ -97,7 +97,7 @@ gfortran-cross$(exeext): gfortran$(exeext)
# The compiler itself is called f951.
f951$(exeext): $(F95_OBJS) \
$(BACKEND) $(LIBDEPS) attribs.o
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(F95_OBJS) $(BACKEND) $(LIBS) attribs.o $(BACKENDLIBS)
gt-fortran-trans.h : s-gtype; @true
@@ -338,5 +338,5 @@ fortran/resolve.o: fortran/dependency.h fortran/data.h fortran/target-memory.h
fortran/data.o: fortran/data.h
fortran/options.o: $(PARAMS_H) $(TARGET_H) fortran/cpp.h
fortran/cpp.o: fortran/cpp.c $(BASEVER) incpath.h incpath.o
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) -DBASEVER=$(BASEVER_s) \
- $< $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
+ -DBASEVER=$(BASEVER_s) $< $(OUTPUT_OPTION)
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index 8ed05f2d6dd..82f07ef0052 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1556,6 +1556,7 @@ gfc_intrinsic_sym;
#include <gmp.h>
#include <mpfr.h>
#define GFC_RND_MODE GMP_RNDN
+#define GFC_MPC_RND_MODE MPC_RNDNN
typedef struct gfc_expr
{
diff --git a/gcc/fortran/gfortranspec.c b/gcc/fortran/gfortranspec.c
index 0e5e7913e97..a6f9b42b474 100644
--- a/gcc/fortran/gfortranspec.c
+++ b/gcc/fortran/gfortranspec.c
@@ -58,10 +58,6 @@ along with GCC; see the file COPYING3. If not see
#define MATH_LIBRARY "-lm"
#endif
-#ifndef FORTRAN_INIT
-#define FORTRAN_INIT "-lgfortranbegin"
-#endif
-
#ifndef FORTRAN_LIBRARY
#define FORTRAN_LIBRARY "-lgfortran"
#endif
@@ -278,10 +274,6 @@ lang_specific_driver (int *in_argc, const char *const **in_argv,
2 => last two args were -l<library> -lm. */
int saw_library = 0;
- /* 0 => initial/reset state
- 1 => FORTRAN_INIT linked in */
- int use_init = 0;
-
/* By default, we throw on the math library if we have one. */
int need_math = (MATH_LIBRARY[0] != '\0');
@@ -505,12 +497,6 @@ For more information about these matters, see the file named COPYING\n\n"));
saw_library = 2; /* -l<library> -lm. */
else
{
- if (0 == use_init)
- {
- append_arg (FORTRAN_INIT);
- use_init = 1;
- }
-
ADD_ARG_LIBGFORTRAN (FORTRAN_LIBRARY);
}
}
@@ -540,11 +526,6 @@ For more information about these matters, see the file named COPYING\n\n"));
switch (saw_library)
{
case 0:
- if (0 == use_init)
- {
- append_arg (FORTRAN_INIT);
- use_init = 1;
- }
ADD_ARG_LIBGFORTRAN (library);
/* Fall through. */
diff --git a/gcc/fortran/match.c b/gcc/fortran/match.c
index ed7bf58bb86..cf558b54e1b 100644
--- a/gcc/fortran/match.c
+++ b/gcc/fortran/match.c
@@ -2418,6 +2418,11 @@ syntax:
cleanup:
gfc_free_statements (new_st.next);
+ new_st.next = NULL;
+ gfc_free_expr (new_st.expr1);
+ new_st.expr1 = NULL;
+ gfc_free_expr (new_st.expr2);
+ new_st.expr2 = NULL;
return MATCH_ERROR;
}
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 01b252cf2ad..51a3c5198e5 100644
--- a/gcc/fortran/simplify.c
+++ b/gcc/fortran/simplify.c
@@ -210,6 +210,24 @@ convert_mpz_to_signed (mpz_t x, int bitsize)
}
}
+/* Helper function to convert to/from mpfr_t & mpc_t and call the
+ supplied mpc function on the respective values. */
+
+#ifdef HAVE_mpc
+static void
+call_mpc_func (mpfr_ptr result_re, mpfr_ptr result_im,
+ mpfr_srcptr input_re, mpfr_srcptr input_im,
+ int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
+{
+ mpc_t c;
+ mpc_init2 (c, mpfr_get_default_prec());
+ mpc_set_fr_fr (c, input_re, input_im, GFC_MPC_RND_MODE);
+ func (c, c, GFC_MPC_RND_MODE);
+ mpfr_set (result_re, MPC_RE (c), GFC_RND_MODE);
+ mpfr_set (result_im, MPC_IM (c), GFC_RND_MODE);
+ mpc_clear (c);
+}
+#endif
/********************** Simplification functions *****************************/
@@ -985,7 +1003,6 @@ gfc_expr *
gfc_simplify_cos (gfc_expr *x)
{
gfc_expr *result;
- mpfr_t xp, xq;
if (x->expr_type != EXPR_CONSTANT)
return NULL;
@@ -999,6 +1016,12 @@ gfc_simplify_cos (gfc_expr *x)
break;
case BT_COMPLEX:
gfc_set_model_kind (x->ts.kind);
+#ifdef HAVE_mpc
+ call_mpc_func (result->value.complex.r, result->value.complex.i,
+ x->value.complex.r, x->value.complex.i, mpc_cos);
+#else
+ {
+ mpfr_t xp, xq;
mpfr_init (xp);
mpfr_init (xq);
@@ -1012,6 +1035,8 @@ gfc_simplify_cos (gfc_expr *x)
mpfr_neg (result->value.complex.i, xp, GFC_RND_MODE );
mpfr_clears (xp, xq, NULL);
+ }
+#endif
break;
default:
gfc_internal_error ("in gfc_simplify_cos(): Bad type");
@@ -1370,7 +1395,6 @@ gfc_expr *
gfc_simplify_exp (gfc_expr *x)
{
gfc_expr *result;
- mpfr_t xp, xq;
if (x->expr_type != EXPR_CONSTANT)
return NULL;
@@ -1385,6 +1409,12 @@ gfc_simplify_exp (gfc_expr *x)
case BT_COMPLEX:
gfc_set_model_kind (x->ts.kind);
+#ifdef HAVE_mpc
+ call_mpc_func (result->value.complex.r, result->value.complex.i,
+ x->value.complex.r, x->value.complex.i, mpc_exp);
+#else
+ {
+ mpfr_t xp, xq;
mpfr_init (xp);
mpfr_init (xq);
mpfr_exp (xq, x->value.complex.r, GFC_RND_MODE);
@@ -1393,6 +1423,8 @@ gfc_simplify_exp (gfc_expr *x)
mpfr_sin (xp, x->value.complex.i, GFC_RND_MODE);
mpfr_mul (result->value.complex.i, xq, xp, GFC_RND_MODE);
mpfr_clears (xp, xq, NULL);
+ }
+#endif
break;
default:
@@ -2547,10 +2579,13 @@ gfc_simplify_leadz (gfc_expr *e)
bs = gfc_integer_kinds[i].bit_size;
if (mpz_cmp_si (e->value.integer, 0) == 0)
lz = bs;
+ else if (mpz_cmp_si (e->value.integer, 0) < 0)
+ lz = 0;
else
lz = bs - mpz_sizeinbase (e->value.integer, 2);
- result = gfc_constant_result (BT_INTEGER, gfc_default_integer_kind, &e->where);
+ result = gfc_constant_result (BT_INTEGER, gfc_default_integer_kind,
+ &e->where);
mpz_set_ui (result->value.integer, lz);
return result;
@@ -2688,7 +2723,6 @@ gfc_expr *
gfc_simplify_log (gfc_expr *x)
{
gfc_expr *result;
- mpfr_t xr, xi;
if (x->expr_type != EXPR_CONSTANT)
return NULL;
@@ -2721,6 +2755,12 @@ gfc_simplify_log (gfc_expr *x)
}
gfc_set_model_kind (x->ts.kind);
+#ifdef HAVE_mpc
+ call_mpc_func (result->value.complex.r, result->value.complex.i,
+ x->value.complex.r, x->value.complex.i, mpc_log);
+#else
+ {
+ mpfr_t xr, xi;
mpfr_init (xr);
mpfr_init (xi);
@@ -2734,7 +2774,8 @@ gfc_simplify_log (gfc_expr *x)
mpfr_log (result->value.complex.r, xr, GFC_RND_MODE);
mpfr_clears (xr, xi, NULL);
-
+ }
+#endif
break;
default:
@@ -4314,7 +4355,6 @@ gfc_expr *
gfc_simplify_sin (gfc_expr *x)
{
gfc_expr *result;
- mpfr_t xp, xq;
if (x->expr_type != EXPR_CONSTANT)
return NULL;
@@ -4329,6 +4369,12 @@ gfc_simplify_sin (gfc_expr *x)
case BT_COMPLEX:
gfc_set_model (x->value.real);
+#ifdef HAVE_mpc
+ call_mpc_func (result->value.complex.r, result->value.complex.i,
+ x->value.complex.r, x->value.complex.i, mpc_sin);
+#else
+ {
+ mpfr_t xp, xq;
mpfr_init (xp);
mpfr_init (xq);
@@ -4341,6 +4387,8 @@ gfc_simplify_sin (gfc_expr *x)
mpfr_mul (result->value.complex.i, xp, xq, GFC_RND_MODE);
mpfr_clears (xp, xq, NULL);
+ }
+#endif
break;
default:
@@ -4425,7 +4473,6 @@ gfc_expr *
gfc_simplify_sqrt (gfc_expr *e)
{
gfc_expr *result;
- mpfr_t ac, ad, s, t, w;
if (e->expr_type != EXPR_CONSTANT)
return NULL;
@@ -4442,10 +4489,16 @@ gfc_simplify_sqrt (gfc_expr *e)
break;
case BT_COMPLEX:
+ gfc_set_model (e->value.real);
+#ifdef HAVE_mpc
+ call_mpc_func (result->value.complex.r, result->value.complex.i,
+ e->value.complex.r, e->value.complex.i, mpc_sqrt);
+#else
+ {
/* Formula taken from Numerical Recipes to avoid over- and
underflow. */
- gfc_set_model (e->value.real);
+ mpfr_t ac, ad, s, t, w;
mpfr_init (ac);
mpfr_init (ad);
mpfr_init (s);
@@ -4517,7 +4570,8 @@ gfc_simplify_sqrt (gfc_expr *e)
&e->where);
mpfr_clears (s, t, ac, ad, w, NULL);
-
+ }
+#endif
break;
default:
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 8f355f6a373..ef6172c85c3 100644
--- a/gcc/fortran/trans-decl.c
+++ b/gcc/fortran/trans-decl.c
@@ -86,6 +86,7 @@ tree gfor_fndecl_runtime_error_at;
tree gfor_fndecl_runtime_warning_at;
tree gfor_fndecl_os_error;
tree gfor_fndecl_generate_error;
+tree gfor_fndecl_set_args;
tree gfor_fndecl_set_fpe;
tree gfor_fndecl_set_options;
tree gfor_fndecl_set_convert;
@@ -144,6 +145,8 @@ tree gfor_fndecl_convert_char4_to_char1;
tree gfor_fndecl_size0;
tree gfor_fndecl_size1;
tree gfor_fndecl_iargc;
+tree gfor_fndecl_clz128;
+tree gfor_fndecl_ctz128;
/* Intrinsic functions implemented in Fortran. */
tree gfor_fndecl_sc_kind;
@@ -286,7 +289,10 @@ gfc_get_label_decl (gfc_st_label * lp)
static tree
gfc_sym_identifier (gfc_symbol * sym)
{
- return (get_identifier (sym->name));
+ if (sym->attr.is_main_program && strcmp (sym->name, "main") == 0)
+ return (get_identifier ("MAIN__"));
+ else
+ return (get_identifier (sym->name));
}
@@ -1525,7 +1531,7 @@ build_function_decl (gfc_symbol * sym)
/* This specifies if a function is globally visible, i.e. it is
the opposite of declaring static in C. */
if (DECL_CONTEXT (fndecl) == NULL_TREE
- && !sym->attr.entry_master)
+ && !sym->attr.entry_master && !sym->attr.is_main_program)
TREE_PUBLIC (fndecl) = 1;
/* TREE_STATIC means the function body is defined here. */
@@ -1544,12 +1550,6 @@ build_function_decl (gfc_symbol * sym)
TREE_SIDE_EFFECTS (fndecl) = 0;
}
- /* For -fwhole-program to work well, the main program needs to have the
- "externally_visible" attribute. */
- if (attr.is_main_program)
- DECL_ATTRIBUTES (fndecl)
- = tree_cons (get_identifier("externally_visible"), NULL_TREE, NULL_TREE);
-
/* Layout the function declaration and put it in the binding level
of the current function. */
pushdecl (fndecl);
@@ -2575,6 +2575,19 @@ gfc_build_intrinsic_function_decls (void)
gfc_build_library_function_decl (get_identifier (PREFIX ("iargc")),
gfc_int4_type_node,
0);
+
+ if (gfc_type_for_size (128, true))
+ {
+ tree uint128 = gfc_type_for_size (128, true);
+
+ gfor_fndecl_clz128 =
+ gfc_build_library_function_decl (get_identifier (PREFIX ("clz128")),
+ integer_type_node, 1, uint128);
+
+ gfor_fndecl_ctz128 =
+ gfc_build_library_function_decl (get_identifier (PREFIX ("ctz128")),
+ integer_type_node, 1, uint128);
+ }
}
@@ -2635,6 +2648,11 @@ gfc_build_builtin_function_decls (void)
/* The runtime_error function does not return. */
TREE_THIS_VOLATILE (gfor_fndecl_os_error) = 1;
+ gfor_fndecl_set_args =
+ gfc_build_library_function_decl (get_identifier (PREFIX("set_args")),
+ void_type_node, 2, integer_type_node,
+ build_pointer_type (pchar_type_node));
+
gfor_fndecl_set_fpe =
gfc_build_library_function_decl (get_identifier (PREFIX("set_fpe")),
void_type_node, 1, integer_type_node);
@@ -2643,7 +2661,7 @@ gfc_build_builtin_function_decls (void)
gfor_fndecl_set_options =
gfc_build_library_function_decl (get_identifier (PREFIX("set_options")),
void_type_node, 2, integer_type_node,
- pvoid_type_node);
+ build_pointer_type (integer_type_node));
gfor_fndecl_set_convert =
gfc_build_library_function_decl (get_identifier (PREFIX("set_convert")),
@@ -3835,6 +3853,220 @@ add_argument_checking (stmtblock_t *block, gfc_symbol *sym)
}
+static void
+create_main_function (tree fndecl)
+{
+ tree old_context;
+ tree ftn_main;
+ tree tmp, decl, result_decl, argc, argv, typelist, arglist;
+ stmtblock_t body;
+
+ old_context = current_function_decl;
+
+ if (old_context)
+ {
+ push_function_context ();
+ saved_parent_function_decls = saved_function_decls;
+ saved_function_decls = NULL_TREE;
+ }
+
+ /* main() function must be declared with global scope. */
+ gcc_assert (current_function_decl == NULL_TREE);
+
+ /* Declare the function. */
+ tmp = build_function_type_list (integer_type_node, integer_type_node,
+ build_pointer_type (pchar_type_node),
+ NULL_TREE);
+ main_identifier_node = get_identifier ("main");
+ ftn_main = build_decl (FUNCTION_DECL, main_identifier_node, tmp);
+ ftn_main = build_decl (FUNCTION_DECL, get_identifier ("main"), tmp);
+ DECL_EXTERNAL (ftn_main) = 0;
+ TREE_PUBLIC (ftn_main) = 1;
+ TREE_STATIC (ftn_main) = 1;
+ DECL_ATTRIBUTES (ftn_main)
+ = tree_cons (get_identifier("externally_visible"), NULL_TREE, NULL_TREE);
+
+ /* Setup the result declaration (for "return 0"). */
+ result_decl = build_decl (RESULT_DECL, NULL_TREE, integer_type_node);
+ DECL_ARTIFICIAL (result_decl) = 1;
+ DECL_IGNORED_P (result_decl) = 1;
+ DECL_CONTEXT (result_decl) = ftn_main;
+ DECL_RESULT (ftn_main) = result_decl;
+
+ pushdecl (ftn_main);
+
+ /* Get the arguments. */
+
+ arglist = NULL_TREE;
+ typelist = TYPE_ARG_TYPES (TREE_TYPE (ftn_main));
+
+ tmp = TREE_VALUE (typelist);
+ argc = build_decl (PARM_DECL, get_identifier ("argc"), tmp);
+ DECL_CONTEXT (argc) = ftn_main;
+ DECL_ARG_TYPE (argc) = TREE_VALUE (typelist);
+ TREE_READONLY (argc) = 1;
+ gfc_finish_decl (argc);
+ arglist = chainon (arglist, argc);
+
+ typelist = TREE_CHAIN (typelist);
+ tmp = TREE_VALUE (typelist);
+ argv = build_decl (PARM_DECL, get_identifier ("argv"), tmp);
+ DECL_CONTEXT (argv) = ftn_main;
+ DECL_ARG_TYPE (argv) = TREE_VALUE (typelist);
+ TREE_READONLY (argv) = 1;
+ DECL_BY_REFERENCE (argv) = 1;
+ gfc_finish_decl (argv);
+ arglist = chainon (arglist, argv);
+
+ DECL_ARGUMENTS (ftn_main) = arglist;
+ current_function_decl = ftn_main;
+ announce_function (ftn_main);
+
+ rest_of_decl_compilation (ftn_main, 1, 0);
+ make_decl_rtl (ftn_main);
+ init_function_start (ftn_main);
+ pushlevel (0);
+
+ gfc_init_block (&body);
+
+ /* Call some libgfortran initialization routines, call then MAIN__(). */
+
+ /* Call _gfortran_set_args (argc, argv). */
+ TREE_USED (argc) = 1;
+ TREE_USED (argv) = 1;
+ tmp = build_call_expr (gfor_fndecl_set_args, 2, argc, argv);
+ gfc_add_expr_to_block (&body, tmp);
+
+ /* Add a call to set_options to set up the runtime library Fortran
+ language standard parameters. */
+ {
+ tree array_type, array, var;
+
+ /* Passing a new option to the library requires four modifications:
+ + add it to the tree_cons list below
+ + change the array size in the call to build_array_type
+ + change the first argument to the library call
+ gfor_fndecl_set_options
+ + modify the library (runtime/compile_options.c)! */
+
+ array = tree_cons (NULL_TREE, build_int_cst (integer_type_node,
+ gfc_option.warn_std), NULL_TREE);
+ array = tree_cons (NULL_TREE, build_int_cst (integer_type_node,
+ gfc_option.allow_std), array);
+ array = tree_cons (NULL_TREE, build_int_cst (integer_type_node, pedantic),
+ array);
+ array = tree_cons (NULL_TREE, build_int_cst (integer_type_node,
+ gfc_option.flag_dump_core), array);
+ array = tree_cons (NULL_TREE, build_int_cst (integer_type_node,
+ gfc_option.flag_backtrace), array);
+ array = tree_cons (NULL_TREE, build_int_cst (integer_type_node,
+ gfc_option.flag_sign_zero), array);
+
+ array = tree_cons (NULL_TREE, build_int_cst (integer_type_node,
+ (gfc_option.rtcheck & GFC_RTCHECK_BOUNDS)), array);
+
+ array = tree_cons (NULL_TREE, build_int_cst (integer_type_node,
+ gfc_option.flag_range_check), array);
+
+ array_type = build_array_type (integer_type_node,
+ build_index_type (build_int_cst (NULL_TREE, 7)));
+ array = build_constructor_from_list (array_type, nreverse (array));
+ TREE_CONSTANT (array) = 1;
+ TREE_STATIC (array) = 1;
+
+ /* Create a static variable to hold the jump table. */
+ var = gfc_create_var (array_type, "options");
+ TREE_CONSTANT (var) = 1;
+ TREE_STATIC (var) = 1;
+ TREE_READONLY (var) = 1;
+ DECL_INITIAL (var) = array;
+ var = gfc_build_addr_expr (build_pointer_type (integer_type_node), var);
+
+ tmp = build_call_expr (gfor_fndecl_set_options, 2,
+ build_int_cst (integer_type_node, 8), var);
+ gfc_add_expr_to_block (&body, tmp);
+ }
+
+ /* If -ffpe-trap option was provided, add a call to set_fpe so that
+ the library will raise a FPE when needed. */
+ if (gfc_option.fpe != 0)
+ {
+ tmp = build_call_expr (gfor_fndecl_set_fpe, 1,
+ build_int_cst (integer_type_node,
+ gfc_option.fpe));
+ gfc_add_expr_to_block (&body, tmp);
+ }
+
+ /* If this is the main program and an -fconvert option was provided,
+ add a call to set_convert. */
+
+ if (gfc_option.convert != GFC_CONVERT_NATIVE)
+ {
+ tmp = build_call_expr (gfor_fndecl_set_convert, 1,
+ build_int_cst (integer_type_node,
+ gfc_option.convert));
+ gfc_add_expr_to_block (&body, tmp);
+ }
+
+ /* If this is the main program and an -frecord-marker option was provided,
+ add a call to set_record_marker. */
+
+ if (gfc_option.record_marker != 0)
+ {
+ tmp = build_call_expr (gfor_fndecl_set_record_marker, 1,
+ build_int_cst (integer_type_node,
+ gfc_option.record_marker));
+ gfc_add_expr_to_block (&body, tmp);
+ }
+
+ if (gfc_option.max_subrecord_length != 0)
+ {
+ tmp = build_call_expr (gfor_fndecl_set_max_subrecord_length, 1,
+ build_int_cst (integer_type_node,
+ gfc_option.max_subrecord_length));
+ gfc_add_expr_to_block (&body, tmp);
+ }
+
+ /* Call MAIN__(). */
+ tmp = build_call_expr (fndecl, 0);
+ gfc_add_expr_to_block (&body, tmp);
+
+ /* Mark MAIN__ as used. */
+ TREE_USED (fndecl) = 1;
+
+ /* "return 0". */
+ tmp = fold_build2 (MODIFY_EXPR, integer_type_node, DECL_RESULT (ftn_main),
+ build_int_cst (integer_type_node, 0));
+ tmp = build1_v (RETURN_EXPR, tmp);
+ gfc_add_expr_to_block (&body, tmp);
+
+
+ DECL_SAVED_TREE (ftn_main) = gfc_finish_block (&body);
+ decl = getdecls ();
+
+ /* Finish off this function and send it for code generation. */
+ poplevel (1, 0, 1);
+ BLOCK_SUPERCONTEXT (DECL_INITIAL (ftn_main)) = ftn_main;
+
+ DECL_SAVED_TREE (ftn_main)
+ = build3_v (BIND_EXPR, decl, DECL_SAVED_TREE (ftn_main),
+ DECL_INITIAL (ftn_main));
+
+ /* Output the GENERIC tree. */
+ dump_function (TDI_original, ftn_main);
+
+ gfc_gimplify_function (ftn_main);
+ cgraph_finalize_function (ftn_main, false);
+
+ if (old_context)
+ {
+ pop_function_context ();
+ saved_function_decls = saved_parent_function_decls;
+ }
+ current_function_decl = old_context;
+}
+
+
/* Generate code for a function. */
void
@@ -3919,107 +4151,6 @@ gfc_generate_function_code (gfc_namespace * ns)
/* Now generate the code for the body of this function. */
gfc_init_block (&body);
- /* If this is the main program, add a call to set_options to set up the
- runtime library Fortran language standard parameters. */
- if (sym->attr.is_main_program)
- {
- tree array_type, array, var;
-
- /* Passing a new option to the library requires four modifications:
- + add it to the tree_cons list below
- + change the array size in the call to build_array_type
- + change the first argument to the library call
- gfor_fndecl_set_options
- + modify the library (runtime/compile_options.c)! */
- array = tree_cons (NULL_TREE,
- build_int_cst (integer_type_node,
- gfc_option.warn_std), NULL_TREE);
- array = tree_cons (NULL_TREE,
- build_int_cst (integer_type_node,
- gfc_option.allow_std), array);
- array = tree_cons (NULL_TREE,
- build_int_cst (integer_type_node, pedantic), array);
- array = tree_cons (NULL_TREE,
- build_int_cst (integer_type_node,
- gfc_option.flag_dump_core), array);
- array = tree_cons (NULL_TREE,
- build_int_cst (integer_type_node,
- gfc_option.flag_backtrace), array);
- array = tree_cons (NULL_TREE,
- build_int_cst (integer_type_node,
- gfc_option.flag_sign_zero), array);
-
- array = tree_cons (NULL_TREE,
- build_int_cst (integer_type_node,
- (gfc_option.rtcheck
- & GFC_RTCHECK_BOUNDS)), array);
-
- array = tree_cons (NULL_TREE,
- build_int_cst (integer_type_node,
- gfc_option.flag_range_check), array);
-
- array_type = build_array_type (integer_type_node,
- build_index_type (build_int_cst (NULL_TREE,
- 7)));
- array = build_constructor_from_list (array_type, nreverse (array));
- TREE_CONSTANT (array) = 1;
- TREE_STATIC (array) = 1;
-
- /* Create a static variable to hold the jump table. */
- var = gfc_create_var (array_type, "options");
- TREE_CONSTANT (var) = 1;
- TREE_STATIC (var) = 1;
- TREE_READONLY (var) = 1;
- DECL_INITIAL (var) = array;
- var = gfc_build_addr_expr (pvoid_type_node, var);
-
- tmp = build_call_expr (gfor_fndecl_set_options, 2,
- build_int_cst (integer_type_node, 8), var);
- gfc_add_expr_to_block (&body, tmp);
- }
-
- /* If this is the main program and a -ffpe-trap option was provided,
- add a call to set_fpe so that the library will raise a FPE when
- needed. */
- if (sym->attr.is_main_program && gfc_option.fpe != 0)
- {
- tmp = build_call_expr (gfor_fndecl_set_fpe, 1,
- build_int_cst (integer_type_node,
- gfc_option.fpe));
- gfc_add_expr_to_block (&body, tmp);
- }
-
- /* If this is the main program and an -fconvert option was provided,
- add a call to set_convert. */
-
- if (sym->attr.is_main_program && gfc_option.convert != GFC_CONVERT_NATIVE)
- {
- tmp = build_call_expr (gfor_fndecl_set_convert, 1,
- build_int_cst (integer_type_node,
- gfc_option.convert));
- gfc_add_expr_to_block (&body, tmp);
- }
-
- /* If this is the main program and an -frecord-marker option was provided,
- add a call to set_record_marker. */
-
- if (sym->attr.is_main_program && gfc_option.record_marker != 0)
- {
- tmp = build_call_expr (gfor_fndecl_set_record_marker, 1,
- build_int_cst (integer_type_node,
- gfc_option.record_marker));
- gfc_add_expr_to_block (&body, tmp);
- }
-
- if (sym->attr.is_main_program && gfc_option.max_subrecord_length != 0)
- {
- tmp = build_call_expr (gfor_fndecl_set_max_subrecord_length,
- 1,
- build_int_cst (integer_type_node,
- gfc_option.max_subrecord_length));
- gfc_add_expr_to_block (&body, tmp);
- }
-
is_recursive = sym->attr.recursive
|| (sym->attr.entry_master
&& sym->ns->entries->sym->attr.recursive);
@@ -4203,8 +4334,12 @@ gfc_generate_function_code (gfc_namespace * ns)
gfc_trans_use_stmts (ns);
gfc_traverse_ns (ns, gfc_emit_parameter_debug_info);
+
+ if (sym->attr.is_main_program)
+ create_main_function (fndecl);
}
+
void
gfc_generate_constructors (void)
{
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 33cc7f569a3..c1409578610 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -2710,53 +2710,51 @@ gfc_conv_intrinsic_leadz (gfc_se * se, gfc_expr * expr)
tree leadz;
tree bit_size;
tree tmp;
- int arg_kind;
- int i, n, s;
+ tree func;
+ int s, argsize;
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
+ argsize = TYPE_PRECISION (TREE_TYPE (arg));
/* Which variant of __builtin_clz* should we call? */
- arg_kind = expr->value.function.actual->expr->ts.kind;
- i = gfc_validate_kind (BT_INTEGER, arg_kind, false);
- switch (arg_kind)
+ if (argsize <= INT_TYPE_SIZE)
{
- case 1:
- case 2:
- case 4:
- arg_type = unsigned_type_node;
- n = BUILT_IN_CLZ;
- break;
-
- case 8:
- arg_type = long_unsigned_type_node;
- n = BUILT_IN_CLZL;
- break;
-
- case 16:
- arg_type = long_long_unsigned_type_node;
- n = BUILT_IN_CLZLL;
- break;
-
- default:
- gcc_unreachable ();
+ arg_type = unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CLZ];
+ }
+ else if (argsize <= LONG_TYPE_SIZE)
+ {
+ arg_type = long_unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CLZL];
+ }
+ else if (argsize <= LONG_LONG_TYPE_SIZE)
+ {
+ arg_type = long_long_unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CLZLL];
+ }
+ else
+ {
+ gcc_assert (argsize == 128);
+ arg_type = gfc_build_uint_type (argsize);
+ func = gfor_fndecl_clz128;
}
- /* Convert the actual argument to the proper argument type for the built-in
+ /* Convert the actual argument twice: first, to the unsigned type of the
+ same size; then, to the proper argument type for the built-in
function. But the return type is of the default INTEGER kind. */
+ arg = fold_convert (gfc_build_uint_type (argsize), arg);
arg = fold_convert (arg_type, arg);
result_type = gfc_get_int_type (gfc_default_integer_kind);
/* Compute LEADZ for the case i .ne. 0. */
- s = TYPE_PRECISION (arg_type) - gfc_integer_kinds[i].bit_size;
- tmp = fold_convert (result_type, build_call_expr (built_in_decls[n], 1, arg));
+ s = TYPE_PRECISION (arg_type) - argsize;
+ tmp = fold_convert (result_type, build_call_expr (func, 1, arg));
leadz = fold_build2 (MINUS_EXPR, result_type,
tmp, build_int_cst (result_type, s));
/* Build BIT_SIZE. */
- bit_size = build_int_cst (result_type, gfc_integer_kinds[i].bit_size);
+ bit_size = build_int_cst (result_type, argsize);
- /* ??? For some combinations of targets and integer kinds, the condition
- can be avoided if CLZ_DEFINED_VALUE_AT_ZERO is used. Later. */
cond = fold_build2 (EQ_EXPR, boolean_type_node,
arg, build_int_cst (arg_type, 0));
se->expr = fold_build3 (COND_EXPR, result_type, cond, bit_size, leadz);
@@ -2777,50 +2775,48 @@ gfc_conv_intrinsic_trailz (gfc_se * se, gfc_expr *expr)
tree result_type;
tree trailz;
tree bit_size;
- int arg_kind;
- int i, n;
+ tree func;
+ int argsize;
gfc_conv_intrinsic_function_args (se, expr, &arg, 1);
+ argsize = TYPE_PRECISION (TREE_TYPE (arg));
- /* Which variant of __builtin_clz* should we call? */
- arg_kind = expr->value.function.actual->expr->ts.kind;
- i = gfc_validate_kind (BT_INTEGER, arg_kind, false);
- switch (expr->ts.kind)
+ /* Which variant of __builtin_ctz* should we call? */
+ if (argsize <= INT_TYPE_SIZE)
{
- case 1:
- case 2:
- case 4:
- arg_type = unsigned_type_node;
- n = BUILT_IN_CTZ;
- break;
-
- case 8:
- arg_type = long_unsigned_type_node;
- n = BUILT_IN_CTZL;
- break;
-
- case 16:
- arg_type = long_long_unsigned_type_node;
- n = BUILT_IN_CTZLL;
- break;
-
- default:
- gcc_unreachable ();
+ arg_type = unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CTZ];
+ }
+ else if (argsize <= LONG_TYPE_SIZE)
+ {
+ arg_type = long_unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CTZL];
+ }
+ else if (argsize <= LONG_LONG_TYPE_SIZE)
+ {
+ arg_type = long_long_unsigned_type_node;
+ func = built_in_decls[BUILT_IN_CTZLL];
+ }
+ else
+ {
+ gcc_assert (argsize == 128);
+ arg_type = gfc_build_uint_type (argsize);
+ func = gfor_fndecl_ctz128;
}
- /* Convert the actual argument to the proper argument type for the built-in
+ /* Convert the actual argument twice: first, to the unsigned type of the
+ same size; then, to the proper argument type for the built-in
function. But the return type is of the default INTEGER kind. */
+ arg = fold_convert (gfc_build_uint_type (argsize), arg);
arg = fold_convert (arg_type, arg);
result_type = gfc_get_int_type (gfc_default_integer_kind);
/* Compute TRAILZ for the case i .ne. 0. */
- trailz = fold_convert (result_type, build_call_expr (built_in_decls[n], 1, arg));
+ trailz = fold_convert (result_type, build_call_expr (func, 1, arg));
/* Build BIT_SIZE. */
- bit_size = build_int_cst (result_type, gfc_integer_kinds[i].bit_size);
+ bit_size = build_int_cst (result_type, argsize);
- /* ??? For some combinations of targets and integer kinds, the condition
- can be avoided if CTZ_DEFINED_VALUE_AT_ZERO is used. Later. */
cond = fold_build2 (EQ_EXPR, boolean_type_node,
arg, build_int_cst (arg_type, 0));
se->expr = fold_build3 (COND_EXPR, result_type, cond, bit_size, trailz);
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index e945fcbf7b5..0c439937125 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -686,7 +686,7 @@ gfc_build_int_type (gfc_integer_info *info)
return make_signed_type (mode_precision);
}
-static tree
+tree
gfc_build_uint_type (int size)
{
if (size == CHAR_TYPE_SIZE)
diff --git a/gcc/fortran/trans-types.h b/gcc/fortran/trans-types.h
index c3e51a11c8e..283d57772a0 100644
--- a/gcc/fortran/trans-types.h
+++ b/gcc/fortran/trans-types.h
@@ -68,6 +68,7 @@ tree gfc_get_function_type (gfc_symbol *);
tree gfc_type_for_size (unsigned, int);
tree gfc_type_for_mode (enum machine_mode, int);
+tree gfc_build_uint_type (int);
tree gfc_get_element_type (tree);
tree gfc_get_array_type_bounds (tree, int, tree *, tree *, int,
diff --git a/gcc/fortran/trans.h b/gcc/fortran/trans.h
index 4846af245fd..906896985d1 100644
--- a/gcc/fortran/trans.h
+++ b/gcc/fortran/trans.h
@@ -590,6 +590,8 @@ extern GTY(()) tree gfor_fndecl_convert_char4_to_char1;
extern GTY(()) tree gfor_fndecl_size0;
extern GTY(()) tree gfor_fndecl_size1;
extern GTY(()) tree gfor_fndecl_iargc;
+extern GTY(()) tree gfor_fndecl_clz128;
+extern GTY(()) tree gfor_fndecl_ctz128;
/* Implemented in Fortran. */
extern GTY(()) tree gfor_fndecl_sc_kind;
diff --git a/gcc/function.c b/gcc/function.c
index 9d9d3ad5066..ddf08b04602 100644
--- a/gcc/function.c
+++ b/gcc/function.c
@@ -124,13 +124,11 @@ struct machine_function * (*init_machine_status) (void);
/* The currently compiled function. */
struct function *cfun = 0;
-/* These arrays record the INSN_UIDs of the prologue and epilogue insns. */
-static VEC(int,heap) *prologue;
-static VEC(int,heap) *epilogue;
-
-/* Array of INSN_UIDs to hold the INSN_UIDs for each sibcall epilogue
- in this function. */
-static VEC(int,heap) *sibcall_epilogue;
+/* These hashes record the prologue and epilogue insns. */
+static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
+ htab_t prologue_insn_hash;
+static GTY((if_marked ("ggc_marked_p"), param_is (struct rtx_def)))
+ htab_t epilogue_insn_hash;
/* Forward declarations. */
@@ -143,8 +141,8 @@ static tree *get_block_vector (tree, int *);
extern tree debug_find_var_in_block_tree (tree, tree);
/* We always define `record_insns' even if it's not used so that we
can always export `prologue_epilogue_contains'. */
-static void record_insns (rtx, VEC(int,heap) **) ATTRIBUTE_UNUSED;
-static int contains (const_rtx, VEC(int,heap) **);
+static void record_insns (rtx, rtx, htab_t *) ATTRIBUTE_UNUSED;
+static bool contains (const_rtx, htab_t);
#ifdef HAVE_return
static void emit_return_into_block (basic_block);
#endif
@@ -207,9 +205,9 @@ free_after_parsing (struct function *f)
void
free_after_compilation (struct function *f)
{
- VEC_free (int, heap, prologue);
- VEC_free (int, heap, epilogue);
- VEC_free (int, heap, sibcall_epilogue);
+ prologue_insn_hash = NULL;
+ epilogue_insn_hash = NULL;
+
if (crtl->emit.regno_pointer_align)
free (crtl->emit.regno_pointer_align);
@@ -4196,18 +4194,11 @@ init_function_start (tree subr)
warning (OPT_Waggregate_return, "function returns an aggregate");
}
-/* Make sure all values used by the optimization passes have sane
- defaults. */
+/* Make sure all values used by the optimization passes have sane defaults. */
unsigned int
init_function_for_compilation (void)
{
reg_renumber = 0;
-
- /* No prologue/epilogue insns yet. Make sure that these vectors are
- empty. */
- gcc_assert (VEC_length (int, prologue) == 0);
- gcc_assert (VEC_length (int, epilogue) == 0);
- gcc_assert (VEC_length (int, sibcall_epilogue) == 0);
return 0;
}
@@ -4873,16 +4864,42 @@ get_arg_pointer_save_area (void)
return ret;
}
-/* Extend a vector that records the INSN_UIDs of INSNS
- (a list of one or more insns). */
+/* Add a list of INSNS to the hash HASHP, possibly allocating HASHP
+ for the first time. */
static void
-record_insns (rtx insns, VEC(int,heap) **vecp)
+record_insns (rtx insns, rtx end, htab_t *hashp)
{
rtx tmp;
+ htab_t hash = *hashp;
+
+ if (hash == NULL)
+ *hashp = hash
+ = htab_create_ggc (17, htab_hash_pointer, htab_eq_pointer, NULL);
+
+ for (tmp = insns; tmp != end; tmp = NEXT_INSN (tmp))
+ {
+ void **slot = htab_find_slot (hash, tmp, INSERT);
+ gcc_assert (*slot == NULL);
+ *slot = tmp;
+ }
+}
+
+/* INSN has been duplicated as COPY, as part of duping a basic block.
+ If INSN is an epilogue insn, then record COPY as epilogue as well. */
- for (tmp = insns; tmp != NULL_RTX; tmp = NEXT_INSN (tmp))
- VEC_safe_push (int, heap, *vecp, INSN_UID (tmp));
+void
+maybe_copy_epilogue_insn (rtx insn, rtx copy)
+{
+ void **slot;
+
+ if (epilogue_insn_hash == NULL
+ || htab_find (epilogue_insn_hash, insn) == NULL)
+ return;
+
+ slot = htab_find_slot (epilogue_insn_hash, copy, INSERT);
+ gcc_assert (*slot == NULL);
+ *slot = copy;
}
/* Set the locator of the insn chain starting at INSN to LOC. */
@@ -4897,52 +4914,37 @@ set_insn_locators (rtx insn, int loc)
}
}
-/* Determine how many INSN_UIDs in VEC are part of INSN. Because we can
- be running after reorg, SEQUENCE rtl is possible. */
+/* Determine if any INSNs in HASH are, or are part of, INSN. Because
+ we can be running after reorg, SEQUENCE rtl is possible. */
-static int
-contains (const_rtx insn, VEC(int,heap) **vec)
+static bool
+contains (const_rtx insn, htab_t hash)
{
- int i, j;
+ if (hash == NULL)
+ return false;
- if (NONJUMP_INSN_P (insn)
- && GET_CODE (PATTERN (insn)) == SEQUENCE)
+ if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
{
- int count = 0;
+ int i;
for (i = XVECLEN (PATTERN (insn), 0) - 1; i >= 0; i--)
- for (j = VEC_length (int, *vec) - 1; j >= 0; --j)
- if (INSN_UID (XVECEXP (PATTERN (insn), 0, i))
- == VEC_index (int, *vec, j))
- count++;
- return count;
+ if (htab_find (hash, XVECEXP (PATTERN (insn), 0, i)))
+ return true;
+ return false;
}
- else
- {
- for (j = VEC_length (int, *vec) - 1; j >= 0; --j)
- if (INSN_UID (insn) == VEC_index (int, *vec, j))
- return 1;
- }
- return 0;
+
+ return htab_find (hash, insn) != NULL;
}
int
prologue_epilogue_contains (const_rtx insn)
{
- if (contains (insn, &prologue))
+ if (contains (insn, prologue_insn_hash))
return 1;
- if (contains (insn, &epilogue))
+ if (contains (insn, epilogue_insn_hash))
return 1;
return 0;
}
-int
-sibcall_epilogue_contains (const_rtx insn)
-{
- if (sibcall_epilogue)
- return contains (insn, &sibcall_epilogue);
- return 0;
-}
-
#ifdef HAVE_return
/* Insert gen_return at the end of block BB. This also means updating
block_for_insn appropriately. */
@@ -4985,7 +4987,7 @@ thread_prologue_and_epilogue_insns (void)
emit_use (hard_frame_pointer_rtx);
/* Retain a map of the prologue insns. */
- record_insns (seq, &prologue);
+ record_insns (seq, NULL, &prologue_insn_hash);
emit_note (NOTE_INSN_PROLOGUE_END);
#ifndef PROFILE_BEFORE_PROLOGUE
@@ -5117,6 +5119,38 @@ thread_prologue_and_epilogue_insns (void)
}
}
#endif
+
+ /* A small fib -- epilogue is not yet completed, but we wish to re-use
+ this marker for the splits of EH_RETURN patterns, and nothing else
+ uses the flag in the meantime. */
+ epilogue_completed = 1;
+
+#ifdef HAVE_eh_return
+ /* Find non-fallthru edges that end with EH_RETURN instructions. On
+ some targets, these get split to a special version of the epilogue
+ code. In order to be able to properly annotate these with unwind
+ info, try to split them now. If we get a valid split, drop an
+ EPILOGUE_BEG note and mark the insns as epilogue insns. */
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+ {
+ rtx prev, last, trial;
+
+ if (e->flags & EDGE_FALLTHRU)
+ continue;
+ last = BB_END (e->src);
+ if (!eh_returnjump_p (last))
+ continue;
+
+ prev = PREV_INSN (last);
+ trial = try_split (PATTERN (last), last, 1);
+ if (trial == last)
+ continue;
+
+ record_insns (NEXT_INSN (prev), NEXT_INSN (trial), &epilogue_insn_hash);
+ emit_note_after (NOTE_INSN_EPILOGUE_BEG, prev);
+ }
+#endif
+
/* Find the edge that falls through to EXIT. Other edges may exist
due to RETURN instructions, but those don't need epilogues.
There really shouldn't be a mixture -- either all should have
@@ -5137,7 +5171,7 @@ thread_prologue_and_epilogue_insns (void)
emit_jump_insn (seq);
/* Retain a map of the epilogue insns. */
- record_insns (seq, &epilogue);
+ record_insns (seq, NULL, &epilogue_insn_hash);
set_insn_locators (seq, epilogue_locator);
seq = get_insns ();
@@ -5199,6 +5233,7 @@ epilogue_done:
}
start_sequence ();
+ emit_note (NOTE_INSN_EPILOGUE_BEG);
emit_insn (gen_sibcall_epilogue ());
seq = get_insns ();
end_sequence ();
@@ -5206,7 +5241,7 @@ epilogue_done:
/* Retain a map of the epilogue insns. Used in life analysis to
avoid getting rid of sibcall epilogue insns. Do this before we
actually emit the sequence. */
- record_insns (seq, &sibcall_epilogue);
+ record_insns (seq, NULL, &epilogue_insn_hash);
set_insn_locators (seq, epilogue_locator);
emit_insn_before (seq, insn);
@@ -5240,23 +5275,29 @@ epilogue_done:
df_update_entry_exit_and_calls ();
}
-/* Reposition the prologue-end and epilogue-begin notes after instruction
- scheduling and delayed branch scheduling. */
+/* Reposition the prologue-end and epilogue-begin notes after
+ instruction scheduling. */
void
reposition_prologue_and_epilogue_notes (void)
{
-#if defined (HAVE_prologue) || defined (HAVE_epilogue)
+#if defined (HAVE_prologue) || defined (HAVE_epilogue) \
+ || defined (HAVE_sibcall_epilogue)
rtx insn, last, note;
- int len;
+ basic_block bb;
- if ((len = VEC_length (int, prologue)) > 0)
+ /* Since the hash table is created on demand, the fact that it is
+ non-null is a signal that it is non-empty. */
+ if (prologue_insn_hash != NULL)
{
+ size_t len = htab_elements (prologue_insn_hash);
last = 0, note = 0;
- /* Scan from the beginning until we reach the last prologue insn.
- We apparently can't depend on basic_block_{head,end} after
- reorg has run. */
+ /* Scan from the beginning until we reach the last prologue insn. */
+ /* ??? While we do have the CFG intact, there are two problems:
+ (1) The prologue can contain loops (typically probing the stack),
+ which means that the end of the prologue isn't in the first bb.
+ (2) Sometimes the PROLOGUE_END note gets pushed into the next bb. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
if (NOTE_P (insn))
@@ -5264,7 +5305,7 @@ reposition_prologue_and_epilogue_notes (void)
if (NOTE_KIND (insn) == NOTE_INSN_PROLOGUE_END)
note = insn;
}
- else if (contains (insn, &prologue))
+ else if (contains (insn, prologue_insn_hash))
{
last = insn;
if (--len == 0)
@@ -5274,14 +5315,17 @@ reposition_prologue_and_epilogue_notes (void)
if (last)
{
- /* Find the prologue-end note if we haven't already, and
- move it to just after the last prologue insn. */
- if (note == 0)
+ if (note == NULL)
{
- for (note = last; (note = NEXT_INSN (note));)
- if (NOTE_P (note)
- && NOTE_KIND (note) == NOTE_INSN_PROLOGUE_END)
- break;
+ /* Scan forward looking for the PROLOGUE_END note. It should
+ be right at the beginning of the block, possibly with other
+ insn notes that got moved there. */
+ for (note = NEXT_INSN (last); ; note = NEXT_INSN (note))
+ {
+ if (NOTE_P (note)
+ && NOTE_KIND (note) == NOTE_INSN_PROLOGUE_END)
+ break;
+ }
}
/* Avoid placing note between CODE_LABEL and BASIC_BLOCK note. */
@@ -5291,41 +5335,39 @@ reposition_prologue_and_epilogue_notes (void)
}
}
- if ((len = VEC_length (int, epilogue)) > 0)
+ if (epilogue_insn_hash != NULL)
{
- last = 0, note = 0;
+ edge_iterator ei;
+ edge e;
- /* Scan from the end until we reach the first epilogue insn.
- We apparently can't depend on basic_block_{head,end} after
- reorg has run. */
- for (insn = get_last_insn (); insn; insn = PREV_INSN (insn))
+ FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
{
- if (NOTE_P (insn))
- {
- if (NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG)
- note = insn;
- }
- else if (contains (insn, &epilogue))
- {
- last = insn;
- if (--len == 0)
- break;
- }
- }
+ last = 0, note = 0;
+ bb = e->src;
- if (last)
- {
- /* Find the epilogue-begin note if we haven't already, and
- move it to just before the first epilogue insn. */
- if (note == 0)
+ /* Scan from the beginning until we reach the first epilogue insn.
+ Take the cue for whether this is a plain or sibcall epilogue
+ from the kind of note we find first. */
+ FOR_BB_INSNS (bb, insn)
{
- for (note = insn; (note = PREV_INSN (note));)
- if (NOTE_P (note)
- && NOTE_KIND (note) == NOTE_INSN_EPILOGUE_BEG)
- break;
+ if (NOTE_P (insn))
+ {
+ if (NOTE_KIND (insn) == NOTE_INSN_EPILOGUE_BEG)
+ {
+ note = insn;
+ if (last)
+ break;
+ }
+ }
+ else if (contains (insn, epilogue_insn_hash))
+ {
+ last = insn;
+ if (note != NULL)
+ break;
+ }
}
-
- if (PREV_INSN (last) != note)
+
+ if (last && note && PREV_INSN (last) != note)
reorder_insns (note, note, PREV_INSN (last));
}
}
diff --git a/gcc/gcc-plugin.h b/gcc/gcc-plugin.h
index e788eb731bb..1588bca372c 100644
--- a/gcc/gcc-plugin.h
+++ b/gcc/gcc-plugin.h
@@ -20,6 +20,13 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_PLUGIN_H
#define GCC_PLUGIN_H
+#ifndef IN_GCC
+#define IN_GCC
+#endif
+
+#include "config.h"
+#include "system.h"
+
/* Event names. Keep in sync with plugin_event_name[]. */
enum plugin_event
{
@@ -28,7 +35,11 @@ enum plugin_event
PLUGIN_FINISH_UNIT, /* Useful for summary processing. */
PLUGIN_CXX_CP_PRE_GENERICIZE, /* Allows to see low level AST in C++ FE. */
PLUGIN_FINISH, /* Called before GCC exits. */
- PLUGIN_INFO, /* Information about the plugin */
+ PLUGIN_INFO, /* Information about the plugin. */
+ PLUGIN_GGC_START, /* Called at start of GCC Garbage Collection. */
+ PLUGIN_GGC_MARKING, /* Extend the GGC marking. */
+ PLUGIN_GGC_END, /* Called at end of GGC. */
+ PLUGIN_REGISTER_GGC_ROOTS, /* Register an extra GGC root table. */
PLUGIN_ATTRIBUTES, /* Called during attribute registration. */
PLUGIN_EVENT_LAST /* Dummy event used for indexing callback
array. */
@@ -128,7 +139,13 @@ typedef void (*plugin_callback_func) (void *gcc_data, void *user_data);
PLUGIN_NAME - display name for this plugin
EVENT - which event the callback is for
CALLBACK - the callback to be called at the event
- USER_DATA - plugin-provided data */
+ USER_DATA - plugin-provided data.
+*/
+
+/* This is also called without a callback routine for the
+ PLUGIN_PASS_MANAGER_SETUP, PLUGIN_INFO, PLUGIN_REGISTER_GGC_ROOTS
+ pseudo-events, with a specific user_data.
+ */
extern void register_callback (const char *plugin_name,
enum plugin_event event,
diff --git a/gcc/gcc.c b/gcc/gcc.c
index 9168a3423d0..f0d986c259a 100644
--- a/gcc/gcc.c
+++ b/gcc/gcc.c
@@ -3636,10 +3636,15 @@ process_command (int argc, const char **argv)
}
/* Convert new-style -- options to old-style. */
- translate_options (&argc, (const char *const **) &argv);
+ translate_options (&argc,
+ CONST_CAST2 (const char *const **, const char ***,
+ &argv));
/* Do language-specific adjustment/addition of flags. */
- lang_specific_driver (&argc, (const char *const **) &argv, &added_libraries);
+ lang_specific_driver (&argc,
+ CONST_CAST2 (const char *const **, const char ***,
+ &argv),
+ &added_libraries);
/* Scan argv twice. Here, the first time, just count how many switches
there will be in their vector, and how many input files in theirs.
@@ -4429,6 +4434,11 @@ set_collect_gcc_options (void)
if ((switches[i].live_cond & SWITCH_IGNORE) != 0)
continue;
+ /* Don't use -fwhole-program when compiling the init and fini routines,
+ since we'd wrongly assume that the routines aren't needed. */
+ if (strcmp (switches[i].part1, "fwhole-program") == 0)
+ continue;
+
obstack_grow (&collect_obstack, "'-", 2);
q = switches[i].part1;
while ((p = strchr (q, '\'')))
@@ -6466,7 +6476,7 @@ main (int argc, char **argv)
Make a table of specified input files (infiles, n_infiles).
Decode switches that are handled locally. */
- process_command (argc, (const char **) argv);
+ process_command (argc, CONST_CAST2 (const char **, char **, argv));
/* Initialize the vector of specs to just the default.
This means one element containing 0s, as a terminator. */
diff --git a/gcc/gcse.c b/gcc/gcse.c
index bfd8c6822ba..3ff47fafc9d 100644
--- a/gcc/gcse.c
+++ b/gcc/gcse.c
@@ -169,6 +169,7 @@ along with GCC; see the file COPYING3. If not see
#include "hashtab.h"
#include "df.h"
#include "dbgcnt.h"
+#include "target.h"
/* Propagate flow information through back edges and thus enable PRE's
moving loop invariant calculations out of loops.
@@ -805,6 +806,11 @@ static GTY(()) rtx test_insn;
/* Return true if we can assign X to a pseudo register such that the
resulting insn does not result in clobbering a hard register as a
side-effect.
+
+ Additionally, if the target requires it, check that the resulting insn
+ can be copied. If it cannot, this means that X is special and probably
+ has hidden side-effects we don't want to mess with.
+
This function is typically used by code motion passes, to verify
that it is safe to insert an insn without worrying about clobbering
maybe live hard regs. */
@@ -837,8 +843,18 @@ can_assign_to_reg_without_clobbers_p (rtx x)
valid. */
PUT_MODE (SET_DEST (PATTERN (test_insn)), GET_MODE (x));
SET_SRC (PATTERN (test_insn)) = x;
- return ((icode = recog (PATTERN (test_insn), test_insn, &num_clobbers)) >= 0
- && (num_clobbers == 0 || ! added_clobbers_hard_reg_p (icode)));
+
+ icode = recog (PATTERN (test_insn), test_insn, &num_clobbers);
+ if (icode < 0)
+ return false;
+
+ if (num_clobbers > 0 && added_clobbers_hard_reg_p (icode))
+ return false;
+
+ if (targetm.cannot_copy_insn_p && targetm.cannot_copy_insn_p (test_insn))
+ return false;
+
+ return true;
}
/* Return nonzero if the operands of expression X are unchanged from the
diff --git a/gcc/gengtype.c b/gcc/gengtype.c
index 2fe6fa5b67e..2866182b275 100644
--- a/gcc/gengtype.c
+++ b/gcc/gengtype.c
@@ -1016,6 +1016,7 @@ adjust_field_rtx_def (type_p t, options_p ARG_UNUSED (opt))
switch (c)
{
case NOTE_INSN_MAX:
+ case NOTE_INSN_DELETED_LABEL:
note_flds = create_field (note_flds, &string_type, "rt_str");
break;
diff --git a/gcc/ggc-common.c b/gcc/ggc-common.c
index 3a86dcfd4da..8758ca1ecdc 100644
--- a/gcc/ggc-common.c
+++ b/gcc/ggc-common.c
@@ -30,6 +30,8 @@ along with GCC; see the file COPYING3. If not see
#include "params.h"
#include "hosthooks.h"
#include "hosthooks-def.h"
+#include "plugin.h"
+#include "vec.h"
#ifdef HAVE_SYS_RESOURCE_H
# include <sys/resource.h>
@@ -86,6 +88,34 @@ ggc_htab_delete (void **slot, void *info)
return 1;
}
+
+/* This extra vector of dynamically registered root_tab-s is used by
+ ggc_mark_roots and gives the ability to dynamically add new GGC root
+ tables, for instance from some plugins; this vector is a heap one
+ [since it is used by GGC internally!] */
+typedef const struct ggc_root_tab* const_ggc_root_tab_t;
+DEF_VEC_P(const_ggc_root_tab_t);
+DEF_VEC_ALLOC_P(const_ggc_root_tab_t, heap);
+static VEC(const_ggc_root_tab_t, heap) *extra_root_vec;
+
+
+/* Dynamically register a new GGC root table RT. This is useful for
+ plugins. */
+
+void
+ggc_register_root_tab (const struct ggc_root_tab* rt)
+{
+ if (!rt)
+ return;
+ if (!extra_root_vec)
+ {
+ int vlen = 32;
+ extra_root_vec = VEC_alloc (const_ggc_root_tab_t, heap, vlen);
+ }
+ VEC_safe_push (const_ggc_root_tab_t, heap, extra_root_vec, rt);
+}
+
+
/* Iterate through all registered roots and mark each element. */
void
ggc_mark_roots (void)
@@ -112,7 +142,21 @@ ggc_mark_roots_extra_marking(gt_pointer_walker extramarker, void*extradata)
for (rt = gt_ggc_rtab; *rt; rt++)
for (rti = *rt; rti->base != NULL; rti++)
for (i = 0; i < rti->nelt; i++)
- (*rti->cb)(*(void **)((char *)rti->base + rti->stride * i));
+ (*rti->cb) (*(void **)((char *)rti->base + rti->stride * i));
+
+ if (extra_root_vec
+ && VEC_length(const_ggc_root_tab_t,extra_root_vec) > 0)
+ {
+ const_ggc_root_tab_t rtp = NULL;
+ for (i=0;
+ VEC_iterate(const_ggc_root_tab_t, extra_root_vec, i, rtp);
+ i++)
+ {
+ for (rti = rtp; rti->base != NULL; rti++)
+ for (i = 0; i < rti->nelt; i++)
+ (*rti->cb) (*(void **) ((char *)rti->base + rti->stride * i));
+ }
+ }
if (ggc_protect_identifiers)
ggc_mark_stringpool ();
@@ -134,6 +178,9 @@ ggc_mark_roots_extra_marking(gt_pointer_walker extramarker, void*extradata)
if (! ggc_protect_identifiers)
ggc_purge_stringpool ();
+
+ /* Some plugins may call ggc_set_mark from here. */
+ invoke_plugin_callbacks (PLUGIN_GGC_MARKING, NULL);
}
/* Allocate a block of memory, then clear it. */
diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c
index c1b8a2918cc..d8517b92c7b 100644
--- a/gcc/ggc-page.c
+++ b/gcc/ggc-page.c
@@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
#include "timevar.h"
#include "params.h"
#include "tree-flow.h"
+#include "plugin.h"
/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
file open. Prefer either to valloc. */
@@ -1938,6 +1939,8 @@ ggc_collect_extra_marking (gt_pointer_walker walkrout, void* walkdata)
/* Indicate that we've seen collections at this context depth. */
G.context_depth_collections = ((unsigned long)1 << (G.context_depth + 1)) - 1;
+ invoke_plugin_callbacks (PLUGIN_GGC_START, NULL);
+
clear_marks ();
ggc_mark_roots_extra_marking (walkrout, walkdata);
#ifdef GATHER_STATISTICS
@@ -1949,6 +1952,8 @@ ggc_collect_extra_marking (gt_pointer_walker walkrout, void* walkdata)
G.allocated_last_gc = G.allocated;
+ invoke_plugin_callbacks (PLUGIN_GGC_END, NULL);
+
timevar_pop (TV_GC);
if (!quiet_flag)
diff --git a/gcc/ggc-zone.c b/gcc/ggc-zone.c
index 926767f43c5..9371eb0400e 100644
--- a/gcc/ggc-zone.c
+++ b/gcc/ggc-zone.c
@@ -36,6 +36,7 @@ along with GCC; see the file COPYING3. If not see
#include "timevar.h"
#include "params.h"
#include "bitmap.h"
+#include "plugin.h"
/* Prefer MAP_ANON(YMOUS) to /dev/zero, since we don't need to keep a
file open. Prefer either to valloc. */
@@ -2030,6 +2031,8 @@ ggc_collect_extra_marking (gt_pointer_walker walkrout, void* walkdata)
}
}
+ invoke_plugin_callbacks (PLUGIN_GGC_START, NULL);
+
/* Start by possibly collecting the main zone. */
main_zone.was_collected = false;
marked |= ggc_collect_1 (&main_zone, true, walkrout, walkdata);
@@ -2094,6 +2097,8 @@ ggc_collect_extra_marking (gt_pointer_walker walkrout, void* walkdata)
}
}
+ invoke_plugin_callbacks (PLUGIN_GGC_END, NULL);
+
timevar_pop (TV_GC);
}
diff --git a/gcc/ggc.h b/gcc/ggc.h
index d5dab9f750b..f727404f5a1 100644
--- a/gcc/ggc.h
+++ b/gcc/ggc.h
@@ -1,6 +1,7 @@
/* Garbage collection for the GNU compiler.
- Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
- Free Software Foundation, Inc.
+
+ Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007,
+ 2008, 2009 Free Software Foundation, Inc.
This file is part of GCC.
@@ -276,6 +277,10 @@ extern void ggc_collect (void);
/* Invoke the collector with an extra marking routine and data */
extern void ggc_collect_extra_marking (gt_pointer_walker, void*);
+/* Register an additional root table. This can be useful for some
+ plugins. Does nothing if the passed pointer is null. */
+extern void ggc_register_root_tab (const struct ggc_root_tab *);
+
/* Return the number of bytes allocated at the indicated address. */
extern size_t ggc_get_size (const void *);
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index bf64b6faf64..264d24c4b4a 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -508,7 +508,7 @@ dump_gimple_call (pretty_printer *buffer, gimple gs, int spc, int flags)
pp_space (buffer);
}
- dump_generic_node (buffer, gimple_call_fn (gs), spc, flags, false);
+ print_call_name (buffer, gimple_call_fn (gs));
pp_string (buffer, " (");
dump_gimple_call_args (buffer, gs, flags);
pp_character (buffer, ')');
diff --git a/gcc/gthr-win32.h b/gcc/gthr-win32.h
index a4fd32b6a34..74ac6179c2c 100644
--- a/gcc/gthr-win32.h
+++ b/gcc/gthr-win32.h
@@ -361,15 +361,14 @@ typedef struct {
__gthread_recursive_mutex_init_function
#define __GTHREAD_RECURSIVE_MUTEX_INIT_DEFAULT {-1, 0, 0, 0}
-#if __MINGW32_MAJOR_VERSION >= 1 || \
- (__MINGW32_MAJOR_VERSION == 0 && __MINGW32_MINOR_VERSION > 2)
+#if defined (_WIN32) && !defined(__CYGWIN__)
#define MINGW32_SUPPORTS_MT_EH 1
/* Mingw runtime >= v0.3 provides a magic variable that is set to nonzero
if -mthreads option was specified, or 0 otherwise. This is to get around
the lack of weak symbols in PE-COFF. */
extern int _CRT_MT;
extern int __mingwthr_key_dtor (unsigned long, void (*) (void *));
-#endif /* __MINGW32__ version */
+#endif /* _WIN32 && !__CYGWIN__ */
/* The Windows95 kernel does not export InterlockedCompareExchange.
This provides a substitute. When building apps that reference
diff --git a/gcc/insn-notes.def b/gcc/insn-notes.def
index 16b4a275477..83161ec14b6 100644
--- a/gcc/insn-notes.def
+++ b/gcc/insn-notes.def
@@ -70,4 +70,8 @@ INSN_NOTE (BASIC_BLOCK)
between hot and cold text sections. */
INSN_NOTE (SWITCH_TEXT_SECTIONS)
+/* Mark the restore point after an epilogue changed CFI data. Used only
+ when an epilogue appears in the middle of a function. */
+INSN_NOTE (CFA_RESTORE_STATE)
+
#undef INSN_NOTE
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 960e1144f91..6754403f5ad 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,19 @@
+2009-06-01 Ian Lance Taylor <iant@google.com>
+
+ * jcf-io.c (find_class): Use CONST_CAST.
+
+2009-05-27 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in ($(XGCJ)$(exeext)): Change $(COMPILER) to
+ $(LINKER).
+ (jc1$(exeext), jcf-dump$(exeext), jvgenmain$(exeext)): Likewise.
+
+2009-05-26 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in (jvspec.o): Use $(COMPILER).
+ ($(XGCJ)$(exeext), jc1$(exeext), jcf-dump$(exeext)): Likewise.
+ (jvgenmain$(exeext), java/jcf-io.o, java/jcf-path.o): Likewise.
+
2009-05-12 Alexandre Oliva <aoliva@redhat.com>
* Make-lang.in (GCJ): Renamed to...
diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in
index fafa94ae766..263ddc39b04 100644
--- a/gcc/java/Make-lang.in
+++ b/gcc/java/Make-lang.in
@@ -1,7 +1,7 @@
# Top level -*- makefile -*- fragment for the GNU compiler for the Java(TM)
# language.
# Copyright (C) 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
-# 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
#This file is part of GCC.
@@ -59,14 +59,14 @@ JAVA_TARGET_INDEPENDENT_BIN_TOOLS = jcf-dump
jvspec.o: $(srcdir)/java/jvspec.c $(SYSTEM_H) coretypes.h $(TM_H) \
$(GCC_H) $(CONFIG_H) java/jcf.h java/javaop.h
(SHLIB_LINK='$(SHLIB_LINK)'; \
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(DRIVER_DEFINES) \
$(INCLUDES) $(srcdir)/java/jvspec.c $(OUTPUT_OPTION))
# Create the compiler driver for $(XGCJ).
$(XGCJ)$(exeext): $(GCC_OBJS) jvspec.o java/jcf-path.o version.o \
prefix.o intl.o $(LIBDEPS) $(EXTRA_GCC_OBJS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) jvspec.o \
- java/jcf-path.o prefix.o intl.o \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(GCC_OBJS) \
+ jvspec.o java/jcf-path.o prefix.o intl.o \
version.o $(EXTRA_GCC_OBJS) $(LIBS)
# Create a version of the $(XGCJ) driver which calls the cross-compiler.
@@ -100,17 +100,18 @@ jvspec.o-warn = -Wno-error
jc1$(exeext): $(JAVA_OBJS) $(BACKEND) $(LIBDEPS) attribs.o
rm -f $@
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(JAVA_OBJS) $(BACKEND) $(ZLIB) $(LIBICONV) $(LIBS) attribs.o $(BACKENDLIBS)
jcf-dump$(exeext): $(JCFDUMP_OBJS) $(LIBDEPS)
rm -f $@
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(JCFDUMP_OBJS) \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(JCFDUMP_OBJS) \
$(CPPLIBS) $(ZLIB) $(LDEXP_LIB) $(LIBS)
jvgenmain$(exeext): $(JVGENMAIN_OBJS) $(LIBDEPS)
rm -f $@
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ $(JVGENMAIN_OBJS) $(LIBS)
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(JVGENMAIN_OBJS) \
+ $(LIBS)
#
# Build hooks:
@@ -305,13 +306,13 @@ java/java-gimplify.o: java/java-gimplify.c $(CONFIG_H) $(SYSTEM_H) \
# jcf-io.o needs $(ZLIBINC) added to cflags.
java/jcf-io.o: java/jcf-io.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(JAVA_TREE_H) java/zipfile.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $(ZLIBINC) \
- $(srcdir)/java/jcf-io.c $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(ZLIBINC) $(srcdir)/java/jcf-io.c $(OUTPUT_OPTION)
# jcf-path.o needs a -D.
java/jcf-path.o: java/jcf-path.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
java/jcf.h
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
-DLIBGCJ_ZIP_FILE='"$(datadir)/java/libgcj-$(version).jar"' \
-DDEFAULT_TARGET_VERSION=\"$(version)\" \
$(srcdir)/java/jcf-path.c $(OUTPUT_OPTION)
diff --git a/gcc/java/jcf-io.c b/gcc/java/jcf-io.c
index b968214e509..28a48bb4504 100644
--- a/gcc/java/jcf-io.c
+++ b/gcc/java/jcf-io.c
@@ -1,6 +1,6 @@
/* Utility routines for finding and reading Java(TM) .class files.
Copyright (C) 1996, 1997, 1998, 1999, 2000, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GCC.
@@ -399,9 +399,8 @@ find_class (const char *classname, int classname_length, JCF *jcf)
/* Remember that this class could not be found so that we do not
have to look again. */
- *(const void **)htab_find_slot_with_hash (memoized_class_lookups,
- classname, hash, INSERT)
- = classname;
+ *htab_find_slot_with_hash (memoized_class_lookups, classname, hash, INSERT)
+ = (void *) CONST_CAST (char *, classname);
return NULL;
found:
diff --git a/gcc/jump.c b/gcc/jump.c
index 90359f8f997..c3af16a06a7 100644
--- a/gcc/jump.c
+++ b/gcc/jump.c
@@ -869,8 +869,21 @@ returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
{
rtx x = *loc;
- return x && (GET_CODE (x) == RETURN
- || (GET_CODE (x) == SET && SET_IS_RETURN_P (x)));
+ if (x == NULL)
+ return false;
+
+ switch (GET_CODE (x))
+ {
+ case RETURN:
+ case EH_RETURN:
+ return true;
+
+ case SET:
+ return SET_IS_RETURN_P (x);
+
+ default:
+ return false;
+ }
}
int
@@ -881,6 +894,22 @@ returnjump_p (rtx insn)
return for_each_rtx (&PATTERN (insn), returnjump_p_1, NULL);
}
+/* Return true if INSN is a (possibly conditional) return insn. */
+
+static int
+eh_returnjump_p_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
+{
+ return *loc && GET_CODE (*loc) == EH_RETURN;
+}
+
+int
+eh_returnjump_p (rtx insn)
+{
+ if (!JUMP_P (insn))
+ return 0;
+ return for_each_rtx (&PATTERN (insn), eh_returnjump_p_1, NULL);
+}
+
/* Return true if INSN is a jump that only transfers control and
nothing more. */
diff --git a/gcc/loop-unroll.c b/gcc/loop-unroll.c
index dfead07648d..8812e68805b 100644
--- a/gcc/loop-unroll.c
+++ b/gcc/loop-unroll.c
@@ -77,6 +77,7 @@ struct iv_to_split
rtx base_var; /* The variable on that the values in the further
iterations are based. */
rtx step; /* Step of the induction variable. */
+ struct iv_to_split *next; /* Next entry in walking order. */
unsigned n_loc;
unsigned loc[3]; /* Location where the definition of the induction
variable occurs in the insn. For example if
@@ -91,6 +92,7 @@ struct var_to_expand
rtx insn; /* The insn in that the variable expansion occurs. */
rtx reg; /* The accumulator which is expanded. */
VEC(rtx,heap) *var_expansions; /* The copies of the accumulator which is expanded. */
+ struct var_to_expand *next; /* Next entry in walking order. */
enum rtx_code op; /* The type of the accumulation - addition, subtraction
or multiplication. */
int expansion_count; /* Count the number of expansions generated so far. */
@@ -110,8 +112,12 @@ struct var_to_expand
struct opt_info
{
htab_t insns_to_split; /* A hashtable of insns to split. */
+ struct iv_to_split *iv_to_split_head; /* The first iv to split. */
+ struct iv_to_split **iv_to_split_tail; /* Pointer to the tail of the list. */
htab_t insns_with_var_to_expand; /* A hashtable of insns with accumulators
to expand. */
+ struct var_to_expand *var_to_expand_head; /* The first var to expand. */
+ struct var_to_expand **var_to_expand_tail; /* Pointer to the tail of the list. */
unsigned first_new_block; /* The first basic block that was
duplicated. */
basic_block loop_exit; /* The loop exit basic block. */
@@ -139,9 +145,10 @@ static struct var_to_expand *analyze_insn_to_expand_var (struct loop*, rtx);
static bool referenced_in_one_insn_in_loop_p (struct loop *, rtx);
static struct iv_to_split *analyze_iv_to_split_insn (rtx);
static void expand_var_during_unrolling (struct var_to_expand *, rtx);
-static int insert_var_expansion_initialization (void **, void *);
-static int combine_var_copies_in_loop_exit (void **, void *);
-static int release_var_copies (void **, void *);
+static void insert_var_expansion_initialization (struct var_to_expand *,
+ basic_block);
+static void combine_var_copies_in_loop_exit (struct var_to_expand *,
+ basic_block);
static rtx get_expansion (struct var_to_expand *);
/* Unroll and/or peel (depending on FLAGS) LOOPS. */
@@ -1646,8 +1653,9 @@ analyze_insn_to_expand_var (struct loop *loop, rtx insn)
/* Record the accumulator to expand. */
ves = XNEW (struct var_to_expand);
ves->insn = insn;
- ves->var_expansions = VEC_alloc (rtx, heap, 1);
ves->reg = copy_rtx (dest);
+ ves->var_expansions = VEC_alloc (rtx, heap, 1);
+ ves->next = NULL;
ves->op = GET_CODE (src);
ves->expansion_count = 0;
ves->reuse_expansion = 0;
@@ -1723,6 +1731,7 @@ analyze_iv_to_split_insn (rtx insn)
ivts->insn = insn;
ivts->base_var = NULL_RTX;
ivts->step = iv.step;
+ ivts->next = NULL;
ivts->n_loc = 1;
ivts->loc[0] = 1;
@@ -1754,8 +1763,12 @@ analyze_insns_in_loop (struct loop *loop)
body = get_loop_body (loop);
if (flag_split_ivs_in_unroller)
- opt_info->insns_to_split = htab_create (5 * loop->num_nodes,
- si_info_hash, si_info_eq, free);
+ {
+ opt_info->insns_to_split = htab_create (5 * loop->num_nodes,
+ si_info_hash, si_info_eq, free);
+ opt_info->iv_to_split_head = NULL;
+ opt_info->iv_to_split_tail = &opt_info->iv_to_split_head;
+ }
/* Record the loop exit bb and loop preheader before the unrolling. */
opt_info->loop_preheader = loop_preheader_edge (loop)->src;
@@ -1772,8 +1785,13 @@ analyze_insns_in_loop (struct loop *loop)
if (flag_variable_expansion_in_unroller
&& can_apply)
- opt_info->insns_with_var_to_expand = htab_create (5 * loop->num_nodes,
- ve_info_hash, ve_info_eq, free);
+ {
+ opt_info->insns_with_var_to_expand = htab_create (5 * loop->num_nodes,
+ ve_info_hash,
+ ve_info_eq, free);
+ opt_info->var_to_expand_head = NULL;
+ opt_info->var_to_expand_tail = &opt_info->var_to_expand_head;
+ }
for (i = 0; i < loop->num_nodes; i++)
{
@@ -1792,7 +1810,10 @@ analyze_insns_in_loop (struct loop *loop)
if (ivts)
{
slot1 = htab_find_slot (opt_info->insns_to_split, ivts, INSERT);
+ gcc_assert (*slot1 == NULL);
*slot1 = ivts;
+ *opt_info->iv_to_split_tail = ivts;
+ opt_info->iv_to_split_tail = &ivts->next;
continue;
}
@@ -1802,7 +1823,10 @@ analyze_insns_in_loop (struct loop *loop)
if (ves)
{
slot2 = htab_find_slot (opt_info->insns_with_var_to_expand, ves, INSERT);
+ gcc_assert (*slot2 == NULL);
*slot2 = ves;
+ *opt_info->var_to_expand_tail = ves;
+ opt_info->var_to_expand_tail = &ves->next;
}
}
}
@@ -1862,18 +1886,14 @@ get_ivts_expr (rtx expr, struct iv_to_split *ivts)
return ret;
}
-/* Allocate basic variable for the induction variable chain. Callback for
- htab_traverse. */
+/* Allocate basic variable for the induction variable chain. */
-static int
-allocate_basic_variable (void **slot, void *data ATTRIBUTE_UNUSED)
+static void
+allocate_basic_variable (struct iv_to_split *ivts)
{
- struct iv_to_split *ivts = (struct iv_to_split *) *slot;
rtx expr = *get_ivts_expr (single_set (ivts->insn), ivts);
ivts->base_var = gen_reg_rtx (GET_MODE (expr));
-
- return 1;
}
/* Insert initialization of basic variable of IVTS before INSN, taking
@@ -2010,14 +2030,13 @@ expand_var_during_unrolling (struct var_to_expand *ve, rtx insn)
}
}
-/* Initialize the variable expansions in loop preheader.
- Callbacks for htab_traverse. PLACE_P is the loop-preheader
- basic block where the initialization of the expansions
- should take place. The expansions are initialized with (-0)
- when the operation is plus or minus to honor sign zero.
- This way we can prevent cases where the sign of the final result is
- effected by the sign of the expansion.
- Here is an example to demonstrate this:
+/* Initialize the variable expansions in loop preheader. PLACE is the
+ loop-preheader basic block where the initialization of the
+ expansions should take place. The expansions are initialized with
+ (-0) when the operation is plus or minus to honor sign zero. This
+ way we can prevent cases where the sign of the final result is
+ effected by the sign of the expansion. Here is an example to
+ demonstrate this:
for (i = 0 ; i < n; i++)
sum += something;
@@ -2038,18 +2057,17 @@ expand_var_during_unrolling (struct var_to_expand *ve, rtx insn)
should be initialized with -zero as well (otherwise we will get +zero
as the final result). */
-static int
-insert_var_expansion_initialization (void **slot, void *place_p)
+static void
+insert_var_expansion_initialization (struct var_to_expand *ve,
+ basic_block place)
{
- struct var_to_expand *ve = (struct var_to_expand *) *slot;
- basic_block place = (basic_block)place_p;
rtx seq, var, zero_init, insn;
unsigned i;
enum machine_mode mode = GET_MODE (ve->reg);
bool honor_signed_zero_p = HONOR_SIGNED_ZEROS (mode);
if (VEC_length (rtx, ve->var_expansions) == 0)
- return 1;
+ return;
start_sequence ();
if (ve->op == PLUS || ve->op == MINUS)
@@ -2077,26 +2095,21 @@ insert_var_expansion_initialization (void **slot, void *place_p)
insn = NEXT_INSN (insn);
emit_insn_after (seq, insn);
- /* Continue traversing the hash table. */
- return 1;
}
-/* Combine the variable expansions at the loop exit.
- Callbacks for htab_traverse. PLACE_P is the loop exit
- basic block where the summation of the expansions should
- take place. */
+/* Combine the variable expansions at the loop exit. PLACE is the
+ loop exit basic block where the summation of the expansions should
+ take place. */
-static int
-combine_var_copies_in_loop_exit (void **slot, void *place_p)
+static void
+combine_var_copies_in_loop_exit (struct var_to_expand *ve, basic_block place)
{
- struct var_to_expand *ve = (struct var_to_expand *) *slot;
- basic_block place = (basic_block)place_p;
rtx sum = ve->reg;
rtx expr, seq, var, insn;
unsigned i;
if (VEC_length (rtx, ve->var_expansions) == 0)
- return 1;
+ return;
start_sequence ();
if (ve->op == PLUS || ve->op == MINUS)
@@ -2123,9 +2136,6 @@ combine_var_copies_in_loop_exit (void **slot, void *place_p)
insn = NEXT_INSN (insn);
emit_insn_after (seq, insn);
-
- /* Continue traversing the hash table. */
- return 1;
}
/* Apply loop optimizations in loop copies using the
@@ -2154,7 +2164,8 @@ apply_opt_in_copies (struct opt_info *opt_info,
/* Allocate the basic variables (i0). */
if (opt_info->insns_to_split)
- htab_traverse (opt_info->insns_to_split, allocate_basic_variable, NULL);
+ for (ivts = opt_info->iv_to_split_head; ivts; ivts = ivts->next)
+ allocate_basic_variable (ivts);
for (i = opt_info->first_new_block; i < (unsigned) last_basic_block; i++)
{
@@ -2218,12 +2229,10 @@ apply_opt_in_copies (struct opt_info *opt_info,
and take care of combining them at the loop exit. */
if (opt_info->insns_with_var_to_expand)
{
- htab_traverse (opt_info->insns_with_var_to_expand,
- insert_var_expansion_initialization,
- opt_info->loop_preheader);
- htab_traverse (opt_info->insns_with_var_to_expand,
- combine_var_copies_in_loop_exit,
- opt_info->loop_exit);
+ for (ves = opt_info->var_to_expand_head; ves; ves = ves->next)
+ insert_var_expansion_initialization (ves, opt_info->loop_preheader);
+ for (ves = opt_info->var_to_expand_head; ves; ves = ves->next)
+ combine_var_copies_in_loop_exit (ves, opt_info->loop_exit);
}
/* Rewrite also the original loop body. Find them as originals of the blocks
@@ -2264,20 +2273,6 @@ apply_opt_in_copies (struct opt_info *opt_info,
}
}
-/* Release the data structures used for the variable expansion
- optimization. Callbacks for htab_traverse. */
-
-static int
-release_var_copies (void **slot, void *data ATTRIBUTE_UNUSED)
-{
- struct var_to_expand *ve = (struct var_to_expand *) *slot;
-
- VEC_free (rtx, heap, ve->var_expansions);
-
- /* Continue traversing the hash table. */
- return 1;
-}
-
/* Release OPT_INFO. */
static void
@@ -2287,8 +2282,10 @@ free_opt_info (struct opt_info *opt_info)
htab_delete (opt_info->insns_to_split);
if (opt_info->insns_with_var_to_expand)
{
- htab_traverse (opt_info->insns_with_var_to_expand,
- release_var_copies, NULL);
+ struct var_to_expand *ves;
+
+ for (ves = opt_info->var_to_expand_head; ves; ves = ves->next)
+ VEC_free (rtx, heap, ves->var_expansions);
htab_delete (opt_info->insns_with_var_to_expand);
}
free (opt_info);
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index f65fa9696ee..a7db6bc0ab9 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,14 @@
+2009-05-27 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in (cc1obj-dummy$(exeext)): Change $(COMPILER) to
+ $(LINKER).
+ (cc1obj$(exeext)): Likewise.
+
+2009-05-26 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in (cc1obj-dummy$(exeext)): Use $(COMPILER).
+ (cc1obj$(exeext)): Likewise.
+
2009-05-20 Ian Lance Taylor <iant@google.com>
* objc-act.c (objc_generate_cxx_ctor_or_dtor): Pass NULL rather
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index 4f854ea78ae..56419eea8bb 100644
--- a/gcc/objc/Make-lang.in
+++ b/gcc/objc/Make-lang.in
@@ -1,6 +1,6 @@
# Top level -*- makefile -*- fragment for GNU Objective-C
# Copyright (C) 1997, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2007,
-# 2008 Free Software Foundation, Inc.
+# 2008, 2009 Free Software Foundation, Inc.
#This file is part of GCC.
@@ -52,7 +52,7 @@ OBJC_OBJS = objc/objc-lang.o objc/objc-act.o
objc_OBJS = $(OBJC_OBJS) cc1obj-checksum.o
cc1obj-dummy$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) dummy-checksum.o $(BACKEND) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(OBJC_OBJS) $(C_AND_OBJC_OBJS) dummy-checksum.o \
$(BACKEND) $(LIBS) $(BACKENDLIBS)
@@ -62,7 +62,7 @@ cc1obj-checksum.c : cc1obj-dummy$(exeext) build/genchecksum$(build_exeext)
cc1obj-checksum.o : cc1obj-checksum.c
cc1obj$(exeext): $(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o $(BACKEND) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o \
$(BACKEND) $(LIBS) $(BACKENDLIBS)
diff --git a/gcc/objcp/ChangeLog b/gcc/objcp/ChangeLog
index 4a4067d3bd7..e2f003de069 100644
--- a/gcc/objcp/ChangeLog
+++ b/gcc/objcp/ChangeLog
@@ -1,3 +1,14 @@
+2009-05-27 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in (cc1objplus-dummy$(exeext)): Change $(COMPILER) to
+ $(LINKER).
+ (cc1objplus$(exeext)): Likewise.
+
+2009-05-26 Ian Lance Taylor <iant@google.com>
+
+ * Make-lang.in (cc1objplus-dummy$(exeext)): Use $(COMPILER).
+ (cc1objplus$(exeext), objcp/objcp-act.o): Likwise.
+
2009-05-10 Ian Lance Taylor <iant@google.com>
* objcp-decl.h (start_struct): Add three new, ignored, macro
diff --git a/gcc/objcp/Make-lang.in b/gcc/objcp/Make-lang.in
index 6e3290cf6de..76f86e52fcb 100644
--- a/gcc/objcp/Make-lang.in
+++ b/gcc/objcp/Make-lang.in
@@ -1,5 +1,5 @@
# Top level -*- makefile -*- fragment for GNU Objective-C++
-# Copyright (C) 2005, 2007, 2008 Free Software Foundation, Inc.
+# Copyright (C) 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
# Contributed by Ziemowit Laski <zlaski@apple.com>
#This file is part of GCC.
@@ -55,7 +55,7 @@ obj-c++_OBJS = $(OBJCXX_OBJS) cc1objplus-checksum.o
cc1objplus-dummy$(exeext): $(OBJCXX_OBJS) dummy-checksum.o $(BACKEND) \
$(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(OBJCXX_OBJS) dummy-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
cc1objplus-checksum.c : cc1objplus-dummy$(exeext) build/genchecksum$(build_exeext)
@@ -64,7 +64,7 @@ cc1objplus-checksum.c : cc1objplus-dummy$(exeext) build/genchecksum$(build_exeex
cc1objplus-checksum.o : cc1objplus-checksum.c
cc1objplus$(exeext): $(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBDEPS)
- $(CC) $(ALL_CFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(OBJCXX_OBJS) cc1objplus-checksum.o $(BACKEND) $(LIBS) $(BACKENDLIBS)
# Objective C++ language specific files.
@@ -87,7 +87,8 @@ objcp/objcp-act.o : objc/objc-act.c \
objc/objc-act.h input.h $(FUNCTION_H) output.h debug.h langhooks.h \
objcp/objcp-decl.h $(LANGHOOKS_DEF_H) $(HASHTAB_H) gt-objc-objc-act.h \
$(GIMPLE_H)
- $(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $< \
+ $(OUTPUT_OPTION)
po-generated:
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index 1a4aea9b37b..e1fb7231c3e 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -1911,7 +1911,11 @@ scan_omp_1_op (tree *tp, int *walk_subtrees, void *data)
if (ctx && TYPE_P (t))
*tp = remap_type (t, &ctx->cb);
else if (!DECL_P (t))
- *walk_subtrees = 1;
+ {
+ *walk_subtrees = 1;
+ if (ctx)
+ TREE_TYPE (t) = remap_type (TREE_TYPE (t), &ctx->cb);
+ }
break;
}
diff --git a/gcc/output.h b/gcc/output.h
index 543164a4c69..9e2b704920a 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -303,6 +303,11 @@ extern bool constructor_static_from_elts_p (const_tree);
arithmetic-combinations of integers. */
extern tree initializer_constant_valid_p (tree, tree);
+/* Return true if VALUE is a valid constant-valued expression
+ for use in initializing a static bit-field; one that can be
+ an element of a "constant" initializer. */
+extern bool initializer_constant_valid_for_bitfield_p (tree);
+
/* Output assembler code for constant EXP to FILE, with no label.
This includes the pseudo-op such as ".int" or ".byte", and a newline.
Assumes output_addressed_constants has been done on EXP already.
diff --git a/gcc/params.def b/gcc/params.def
index dfff1bfbc62..6b0951c84ea 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -38,36 +38,6 @@ along with GCC; see the file COPYING3. If not see
Be sure to add an entry to invoke.texi summarizing the parameter. */
-/* The maximum structure size at which the scalar replacement of
- aggregates (SRA) pass will perform block copies. The default
- value, 0, implies that GCC will select the most appropriate size
- itself. */
-DEFPARAM (PARAM_SRA_MAX_STRUCTURE_SIZE,
- "sra-max-structure-size",
- "The maximum structure size (in bytes) for which GCC will "
- "use by-element copies",
- 0, 0, 0)
-
-/* The maximum number of structure fields which the SRA pass will
- instantiate to avoid block copies. The default value, 0, implies
- that GCC will select the appropriate value itself. */
-DEFPARAM (PARAM_SRA_MAX_STRUCTURE_COUNT,
- "sra-max-structure-count",
- "The maximum number of structure fields for which GCC will "
- "use by-element copies",
- 0, 0, 0)
-
-/* The ratio between instantiated fields and the complete structure
- size. We say that if the ratio of the number of bytes in
- instantiated fields to the number of bytes in the complete
- structure exceeds this parameter, or if the number of instantiated
- fields to the total number of fields exceeds this parameter, then
- block copies are not used. The default is 75%. */
-DEFPARAM (PARAM_SRA_FIELD_STRUCTURE_RATIO,
- "sra-field-structure-ratio",
- "The threshold ratio between instantiated fields and the total structure size",
- 75, 0, 100)
-
/* The threshold ratio between current and hottest structure counts.
We say that if the ratio of the current structure count,
calculated by profiling, to the hottest structure count
diff --git a/gcc/params.h b/gcc/params.h
index 16ed29234ca..828aa7d43cc 100644
--- a/gcc/params.h
+++ b/gcc/params.h
@@ -94,12 +94,6 @@ typedef enum compiler_param
(compiler_params[(int) ENUM].set)
/* Macros for the various parameters. */
-#define SRA_MAX_STRUCTURE_SIZE \
- PARAM_VALUE (PARAM_SRA_MAX_STRUCTURE_SIZE)
-#define SRA_MAX_STRUCTURE_COUNT \
- PARAM_VALUE (PARAM_SRA_MAX_STRUCTURE_COUNT)
-#define SRA_FIELD_STRUCTURE_RATIO \
- PARAM_VALUE (PARAM_SRA_FIELD_STRUCTURE_RATIO)
#define STRUCT_REORG_COLD_STRUCT_RATIO \
PARAM_VALUE (PARAM_STRUCT_REORG_COLD_STRUCT_RATIO)
#define MAX_INLINE_INSNS_SINGLE \
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 6cee526cf76..0b5515e4907 100644
--- a/gcc/plugin.c
+++ b/gcc/plugin.c
@@ -38,6 +38,8 @@ along with GCC; see the file COPYING3. If not see
#include "intl.h"
#include "plugin.h"
#include "timevar.h"
+#include "ggc.h"
+
#ifdef ENABLE_PLUGIN
#include "plugin-version.h"
#endif
@@ -51,6 +53,10 @@ const char *plugin_event_name[] =
"PLUGIN_CXX_CP_PRE_GENERICIZE",
"PLUGIN_FINISH",
"PLUGIN_INFO",
+ "PLUGIN_GGC_START",
+ "PLUGIN_GGC_MARKING",
+ "PLUGIN_GGC_END",
+ "PLUGIN_REGISTER_GGC_ROOTS",
"PLUGIN_EVENT_LAST"
};
@@ -472,14 +478,23 @@ register_callback (const char *plugin_name,
switch (event)
{
case PLUGIN_PASS_MANAGER_SETUP:
+ gcc_assert (!callback);
register_pass (plugin_name, (struct plugin_pass *) user_data);
break;
case PLUGIN_INFO:
+ gcc_assert (!callback);
register_plugin_info (plugin_name, (struct plugin_info *) user_data);
break;
+ case PLUGIN_REGISTER_GGC_ROOTS:
+ gcc_assert (!callback);
+ ggc_register_root_tab ((const struct ggc_root_tab*) user_data);
+ break;
case PLUGIN_FINISH_TYPE:
case PLUGIN_FINISH_UNIT:
case PLUGIN_CXX_CP_PRE_GENERICIZE:
+ case PLUGIN_GGC_START:
+ case PLUGIN_GGC_MARKING:
+ case PLUGIN_GGC_END:
case PLUGIN_ATTRIBUTES:
case PLUGIN_FINISH:
{
@@ -524,6 +539,9 @@ invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
case PLUGIN_CXX_CP_PRE_GENERICIZE:
case PLUGIN_ATTRIBUTES:
case PLUGIN_FINISH:
+ case PLUGIN_GGC_START:
+ case PLUGIN_GGC_MARKING:
+ case PLUGIN_GGC_END:
{
/* Iterate over every callback registered with this event and
call it. */
@@ -535,6 +553,7 @@ invoke_plugin_callbacks (enum plugin_event event, void *gcc_data)
case PLUGIN_PASS_MANAGER_SETUP:
case PLUGIN_EVENT_LAST:
+ case PLUGIN_REGISTER_GGC_ROOTS:
default:
gcc_assert (false);
}
diff --git a/gcc/print-rtl.c b/gcc/print-rtl.c
index 393ffe94e20..596ac8fda01 100644
--- a/gcc/print-rtl.c
+++ b/gcc/print-rtl.c
@@ -1,6 +1,6 @@
/* Print RTL for GCC.
Copyright (C) 1987, 1988, 1992, 1997, 1998, 1999, 2000, 2002, 2003,
- 2004, 2005, 2007, 2008
+ 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
@@ -60,6 +60,11 @@ const char *print_rtx_head = "";
This must be defined here so that programs like gencodes can be linked. */
int flag_dump_unnumbered = 0;
+/* Nonzero means suppress output of instruction numbers for previous
+ and next insns in debugging dumps.
+ This must be defined here so that programs like gencodes can be linked. */
+int flag_dump_unnumbered_links = 0;
+
/* Nonzero means use simplified format without flags, modes, etc. */
int flag_simple = 0;
@@ -199,8 +204,9 @@ print_rtx (const_rtx in_rtx)
fputs ("/i", outfile);
/* Print REG_NOTE names for EXPR_LIST and INSN_LIST. */
- if (GET_CODE (in_rtx) == EXPR_LIST
- || GET_CODE (in_rtx) == INSN_LIST)
+ if ((GET_CODE (in_rtx) == EXPR_LIST
+ || GET_CODE (in_rtx) == INSN_LIST)
+ && (int)GET_MODE (in_rtx) < REG_NOTE_MAX)
fprintf (outfile, ":%s",
GET_REG_NOTE_NAME (GET_MODE (in_rtx)));
@@ -493,7 +499,10 @@ print_rtx (const_rtx in_rtx)
goto do_e;
}
- if (flag_dump_unnumbered)
+ if (flag_dump_unnumbered
+ || (flag_dump_unnumbered_links && (i == 1 || i == 2)
+ && (INSN_P (in_rtx) || NOTE_P (in_rtx)
+ || LABEL_P (in_rtx) || BARRIER_P (in_rtx))))
fputs (" #", outfile);
else
fprintf (outfile, " %d", INSN_UID (sub));
diff --git a/gcc/recog.c b/gcc/recog.c
index 70b0967f709..4ee52af2757 100644
--- a/gcc/recog.c
+++ b/gcc/recog.c
@@ -3056,6 +3056,26 @@ peep2_find_free_register (int from, int to, const char *class_str,
return NULL_RTX;
}
+/* Forget all currently tracked instructions, only remember current
+ LIVE regset. */
+
+static void
+peep2_reinit_state (regset live)
+{
+ int i;
+
+ /* Indicate that all slots except the last holds invalid data. */
+ for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
+ peep2_insn_data[i].insn = NULL_RTX;
+ peep2_current_count = 0;
+
+ /* Indicate that the last slot contains live_after data. */
+ peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
+ peep2_current = MAX_INSNS_PER_PEEP2;
+
+ COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
+}
+
/* Perform the peephole2 optimization pass. */
static void
@@ -3079,19 +3099,11 @@ peephole2_optimize (void)
FOR_EACH_BB_REVERSE (bb)
{
rtl_profile_for_bb (bb);
- /* Indicate that all slots except the last holds invalid data. */
- for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
- peep2_insn_data[i].insn = NULL_RTX;
- peep2_current_count = 0;
-
- /* Indicate that the last slot contains live_after data. */
- peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
- peep2_current = MAX_INSNS_PER_PEEP2;
/* Start up propagation. */
bitmap_copy (live, DF_LR_OUT (bb));
df_simulate_initialize_backwards (bb, live);
- bitmap_copy (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
+ peep2_reinit_state (live);
for (insn = BB_END (bb); ; insn = prev)
{
@@ -3118,7 +3130,7 @@ peephole2_optimize (void)
/* If an insn has RTX_FRAME_RELATED_P set, peephole
substitution would lose the
REG_FRAME_RELATED_EXPR that is attached. */
- peep2_current_count = 0;
+ peep2_reinit_state (live);
attempt = NULL;
}
else
diff --git a/gcc/reg-notes.def b/gcc/reg-notes.def
index 60e41bb9803..90b5fde3feb 100644
--- a/gcc/reg-notes.def
+++ b/gcc/reg-notes.def
@@ -118,6 +118,41 @@ REG_NOTE (BR_PRED)
instead of intuition. */
REG_NOTE (FRAME_RELATED_EXPR)
+/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
+ for FRAME_RELATED_EXPR intuition. The insn's first pattern must be
+ a SET, and the destination must be the CFA register. The attached
+ rtx is an expression that defines the CFA. In the simplest case, the
+ rtx could be just the stack_pointer_rtx; more common would be a PLUS
+ with a base register and a constant offset. In the most complicated
+ cases, this will result in a DW_CFA_def_cfa_expression with the rtx
+ expression rendered in a dwarf location expression. */
+REG_NOTE (CFA_DEF_CFA)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, but are too complex
+ for FRAME_RELATED_EXPR intuition. This note adjusts the expression
+ from which the CFA is computed. The attached rtx defines a new CFA
+ expression, relative to the old CFA expression. This rtx must be of
+ the form (SET new-cfa-reg (PLUS old-cfa-reg const_int)). If the note
+ rtx is NULL, we use the first SET of the insn. */
+REG_NOTE (CFA_ADJUST_CFA)
+
+/* Similar to FRAME_RELATED_EXPR, with the additional information that
+ this is a save to memory, i.e. will result in DW_CFA_offset or the
+ like. The pattern or the insn should be a simple store relative to
+ the CFA. */
+REG_NOTE (CFA_OFFSET)
+
+/* Similar to FRAME_RELATED_EXPR, with the additional information that this
+ is a save to a register, i.e. will result in DW_CFA_register. The insn
+ or the pattern should be simple reg-reg move. */
+REG_NOTE (CFA_REGISTER)
+
+/* Attached to insns that are RTX_FRAME_RELATED_P, with the information
+ that this is a restore operation, i.e. will result in DW_CFA_restore
+ or the like. Either the attached rtx, or the destination of the insn's
+ first pattern is the register to be restored. */
+REG_NOTE (CFA_RESTORE)
+
/* Indicates that REG holds the exception context for the function.
This context is shared by inline functions, so the code to acquire
the real exception context is delayed until after inlining. */
diff --git a/gcc/regstat.c b/gcc/regstat.c
index 383201e4b57..097d0fa8ea8 100644
--- a/gcc/regstat.c
+++ b/gcc/regstat.c
@@ -1,5 +1,5 @@
/* Scanning of rtl for dataflow analysis.
- Copyright (C) 2007, 2008
+ Copyright (C) 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Kenneth Zadeck (zadeck@naturalbridge.com).
@@ -37,7 +37,6 @@ along with GCC; see the file COPYING3. If not see
struct regstat_n_sets_and_refs_t *regstat_n_sets_and_refs;
-struct regstat_n_sets_and_refs_t *regstat_n_sets_and_refs;
/*----------------------------------------------------------------------------
REG_N_SETS and REG_N_REFS.
diff --git a/gcc/rtl.def b/gcc/rtl.def
index 662a9f0c8b7..090546b3ebe 100644
--- a/gcc/rtl.def
+++ b/gcc/rtl.def
@@ -281,6 +281,10 @@ DEF_RTL_EXPR(CALL, "call", "ee", RTX_EXTRA)
DEF_RTL_EXPR(RETURN, "return", "", RTX_EXTRA)
+/* Special for EH return from subroutine. */
+
+DEF_RTL_EXPR(EH_RETURN, "eh_return", "", RTX_EXTRA)
+
/* Conditional trap.
Operand 1 is the condition.
Operand 2 is the trap code.
diff --git a/gcc/rtl.h b/gcc/rtl.h
index 1282b909cf7..152761bcb1c 100644
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -2086,6 +2086,7 @@ extern rtx pc_set (const_rtx);
extern rtx condjump_label (const_rtx);
extern int simplejump_p (const_rtx);
extern int returnjump_p (rtx);
+extern int eh_returnjump_p (rtx);
extern int onlyjump_p (const_rtx);
extern int only_sets_cc0_p (const_rtx);
extern int sets_cc0_p (const_rtx);
@@ -2198,6 +2199,7 @@ extern int prologue_epilogue_contains (const_rtx);
extern int sibcall_epilogue_contains (const_rtx);
extern void mark_temp_addr_taken (rtx);
extern void update_temp_slot_address (rtx, rtx);
+extern void maybe_copy_epilogue_insn (rtx, rtx);
/* In stmt.c */
extern void expand_null_return (void);
diff --git a/gcc/sel-sched-ir.c b/gcc/sel-sched-ir.c
index d3f35627815..655c8732725 100644
--- a/gcc/sel-sched-ir.c
+++ b/gcc/sel-sched-ir.c
@@ -3730,7 +3730,8 @@ get_seqno_of_a_pred (insn_t insn)
return seqno;
}
-/* Find the proper seqno for inserting at INSN. */
+/* Find the proper seqno for inserting at INSN. Returns -1 if no predecessors
+ with positive seqno exist. */
int
get_seqno_by_preds (rtx insn)
{
@@ -3749,7 +3750,6 @@ get_seqno_by_preds (rtx insn)
for (i = 0, seqno = -1; i < n; i++)
seqno = MAX (seqno, INSN_SEQNO (preds[i]));
- gcc_assert (seqno > 0);
return seqno;
}
diff --git a/gcc/sel-sched.c b/gcc/sel-sched.c
index b1a33beb7d0..a7dedc5ef2d 100644
--- a/gcc/sel-sched.c
+++ b/gcc/sel-sched.c
@@ -4524,11 +4524,27 @@ find_seqno_for_bookkeeping (insn_t place_to_insert, insn_t join_point)
if (INSN_P (next)
&& JUMP_P (next)
&& BLOCK_FOR_INSN (next) == BLOCK_FOR_INSN (place_to_insert))
- seqno = INSN_SEQNO (next);
+ {
+ gcc_assert (INSN_SCHED_TIMES (next) == 0);
+ seqno = INSN_SEQNO (next);
+ }
else if (INSN_SEQNO (join_point) > 0)
seqno = INSN_SEQNO (join_point);
else
- seqno = get_seqno_by_preds (place_to_insert);
+ {
+ seqno = get_seqno_by_preds (place_to_insert);
+
+ /* Sometimes the fences can move in such a way that there will be
+ no instructions with positive seqno around this bookkeeping.
+ This means that there will be no way to get to it by a regular
+ fence movement. Never mind because we pick up such pieces for
+ rescheduling anyways, so any positive value will do for now. */
+ if (seqno < 0)
+ {
+ gcc_assert (pipelining_p);
+ seqno = 1;
+ }
+ }
gcc_assert (seqno > 0);
return seqno;
diff --git a/gcc/system.h b/gcc/system.h
index 6e8343e3e44..5ebacb963b4 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -795,6 +795,9 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
change after the fact). Beyond these uses, most other cases of
using this macro should be viewed with extreme caution. */
+#ifdef __cplusplus
+#define CONST_CAST2(TOTYPE,FROMTYPE,X) (const_cast<TOTYPE> (X))
+#else
#if defined(__GNUC__) && GCC_VERSION > 4000
/* GCC 4.0.x has a bug where it may ICE on this expression,
so does GCC 3.4.x (PR17436). */
@@ -802,6 +805,7 @@ extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
#else
#define CONST_CAST2(TOTYPE,FROMTYPE,X) ((TOTYPE)(FROMTYPE)(X))
#endif
+#endif
#define CONST_CAST(TYPE,X) CONST_CAST2(TYPE, const TYPE, (X))
#define CONST_CAST_TREE(X) CONST_CAST(union tree_node *, (X))
#define CONST_CAST_RTX(X) CONST_CAST(struct rtx_def *, (X))
diff --git a/gcc/target-def.h b/gcc/target-def.h
index 2de89a001d3..8aeebeb80f1 100644
--- a/gcc/target-def.h
+++ b/gcc/target-def.h
@@ -423,6 +423,7 @@
/* In cse.c. */
#define TARGET_ADDRESS_COST default_address_cost
+#define TARGET_CONST_ANCHOR 0
/* In builtins.c. */
#define TARGET_INIT_BUILTINS hook_void_void
@@ -922,6 +923,7 @@
TARGET_STACK_PROTECT_FAIL, \
TARGET_INVALID_WITHIN_DOLOOP, \
TARGET_VALID_DLLIMPORT_ATTRIBUTE_P, \
+ TARGET_CONST_ANCHOR, \
TARGET_CALLS, \
TARGET_INVALID_CONVERSION, \
TARGET_INVALID_UNARY_OP, \
diff --git a/gcc/target.h b/gcc/target.h
index d851425a6a7..0d60b1134ce 100644
--- a/gcc/target.h
+++ b/gcc/target.h
@@ -481,7 +481,7 @@ struct gcc_target
/* Target builtin that implements vector permute. */
tree (* builtin_vec_perm) (tree, tree*);
-} vectorize;
+ } vectorize;
/* The initial value of target_flags. */
int default_target_flags;
@@ -825,6 +825,10 @@ struct gcc_target
checks to handle_dll_attribute (). */
bool (* valid_dllimport_attribute_p) (const_tree decl);
+ /* If non-zero, align constant anchors in CSE to a multiple of this
+ value. */
+ unsigned HOST_WIDE_INT const_anchor;
+
/* Functions relating to calls - argument passing, returns, etc. */
struct calls {
bool (*promote_function_args) (const_tree fntype);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 03aa1166e1f..ddfd088b037 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,283 @@
+2009-06-02 Mark Mitchell <mark@codesourcery.com>
+
+ * g++.dg/init/ref15.C: Require unwrapped targets.
+
+2009-06-02 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/initlist13.C: Remove expected error.
+ * g++.dg/cpp0x/initlist18.C: New.
+ * g++.dg/cpp0x/initlist19.C: New.
+
+ * g++.dg/cpp0x/auto14.C: New.
+
+2009-06-02 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/alignment6.adb: Remove XFAIL.
+
+2009-06-02 Simon Martin <simartin@users.sourceforge.net>
+
+ PR c++/38089
+ * g++.dg/template/spec36.C: New test.
+
+2009-06-01 Ian Lance Taylor <iant@google.com>
+
+ * gcc.dg/cast-qual-3.c: New testcase.
+ * g++.dg/warn/Wcast-qual2.C: New testcase.
+
+2009-06-01 Aldy Hernandez <aldyh@redhat.com>
+
+ * lib/gcc-dg.exp (dg-bogus): Override dg-bogus.
+ (process-message): Expect column numbers.
+ * gcc.dg/va-arg-2.c: Use line 0 to indicate no column.
+ * gcc.dg/pch/counter-2.c: Same.
+ * gcc.dg/pch/valid-2.c: Same.
+ * gcc.dg/pch/warn-1.c: Same.
+ * gcc.dg/pch/valid-1.c: Same.
+ * gcc.dg/cpp/include2a.c: Handle lack of columns.
+ * gcc.dg/cpp/syshdr.c: Same.
+ * gcc.dg/cpp/19940712-1.c: Same.
+ * gcc.dg/cpp/missing-header-1.c: Same.
+ * gcc.dg/cpp/unc4.c: Remove -fno-show-column.
+ * gcc.dg/cpp/tr-warn3.c: Same.
+ * gcc.dg/cpp/pr29612-2.c: Same.
+ * gcc.dg/cpp/tr-warn4.c: Same.
+ * gcc.dg/cpp/Wtrigraphs.c: Same.
+ * gcc.dg/cpp/poison.c: Same.
+ * gcc.dg/cpp/arith-3.c: Same.
+ * gcc.dg/cpp/sysmac2.c: Same.
+ * gcc.dg/cpp/cpp.exp: Same.
+ * gcc.dg/cpp/tr-warn5.c: Same.
+ * gcc.dg/cpp/include2.c: Same.
+ * gcc.dg/cpp/Wmissingdirs.c: Same.
+ * gcc.dg/cpp/Wmissingdirs.c: Same.
+ * gcc.dg/cpp/tr-warn6.c: Same.
+ * gcc.dg/cpp/Wtrigraphs-2.c: Same.
+ * gcc.dg/cpp/macspace1.c: Same.
+ * gcc.dg/cpp/escape-2.c: Same.
+ * gcc.dg/cpp/assert2.c: Same.
+ * gcc.dg/cpp/undef2.c: Same.
+ * gcc.dg/cpp/macspace2.c: Same.
+ * gcc.dg/cpp/tr-warn1.c: Same.
+ * gcc.dg/cpp/extratokens2.c: Same.
+ * gcc.dg/cpp/strify2.c: Same.
+ * gcc.dg/cpp/Wsignprom.c: Same.
+ * gcc.dg/cpp/redef2.c: Same.
+ * gcc.dg/cpp/trad/trad.exp: Same.
+ * gcc.dg/cpp/arith-1.c: Same.
+ * gcc.dg/cpp/extratokens.c: Same.
+ * gcc.dg/cpp/if-mpar.c: Same.
+
+2009-06-01 Olivier Hainque <hainque@adacore.com>
+
+ * gnat.dg/nested_float_packed.ads: New test.
+
+2009-06-01 Olivier Hainque <hainque@adacore.com>
+ Eric Botcazou <botcazou@adacore.com>
+
+ * gnat.dg/oconst[1-6].ad[bs]: New tests. Also support for ...
+ * gnat.dg/test_oconst.adb: New test.
+
+2009-05-31 Basile Starynkevitch <basile@starynkevitch.net>
+
+ * gcc.dg/plugin/ggcplug.c: moved comment.
+ (plugin_init): fixed typo, declared i, returned 0 at end.
+
+2009-05-31 Ira Rosen <irar@il.ibm.com>
+
+ PR testsuite/40244
+ * gcc.dg/vect/bb-slp-4.c: Change the number of data accesses to 2.
+ * gcc.dg/vect/bb-slp-10.c: Change the store misalignment to 1.
+
+2009-05-29 Ian Lance Taylor <iant@google.com>
+
+ * gcc.dg/Wcxx-compat-11.c: New testcase.
+
+2009-05-29 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/40019
+ * gfortran.dg/leadz_trailz_1.f90: New test.
+ * gfortran.dg/leadz_trailz_2.f90: New test.
+
+2009-05-29 Martin Jambor <mjambor@suse.cz>
+
+ * gfortran.dg/pr25923.f90: XFAIL warning expectation.
+ * gcc.dg/tree-ssa/ssa-fre-7.c: Compile with -fno-tree-sra.
+ * gcc.dg/tree-ssa/ssa-fre-8.c: Likewise.
+ * gcc.dg/tree-ssa/ssa-fre-9.c: Likewise.
+ * gcc.dg/memcpy-1.c: Removed param sra-max-structure-size.
+ * gcc.dg/tree-ssa/sra-2.c: Likewise.
+ * gcc.dg/tree-ssa/sra-3.c: Likewise.
+ * gcc.dg/tree-ssa/sra-1.c: Likewise.
+ * gcc.dg/tree-ssa/sra-4.c: Changed comment.
+ * gcc.dg/tree-ssa/sra-5.c: New file.
+ * gcc.dg/tree-ssa/sra-6.c: New file.
+ * gcc.c-torture/compile/sra-1.c: New file.
+
+2009-05-29 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40291
+ * gcc.c-torture/compile/pr40291.c: New test.
+
+ PR target/40017
+ * gcc.target/powerpc/altivec-types-1.c: Don't expect error for
+ __vector _Bool.
+ * gcc.target/powerpc/altivec-30.c: New test.
+ * gcc.target/powerpc/altivec-31.c: New test.
+
+2009-05-28 Richard Guenther <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-fre-26.c: New testcase.
+ * gcc.c-torture/execute/20090527-1.c: Likewise.
+
+2009-05-28 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/39754
+ * g++.dg/template/canon-type-1.C: New test.
+ * g++.dg/template/canon-type-2.C: Likewise.
+ * g++.dg/template/canon-type-3.C: Likewise.
+ * g++.dg/template/canon-type-4.C: Likewise.
+ * g++.dg/template/canon-type-5.C: Likewise.
+ * g++.dg/template/canon-type-6.C: Likewise.
+ * g++.dg/template/canon-type-7.C: Likewise.
+
+2009-05-28 Dave Korn <dave.korn.cygwin@gmail.com>
+ Uros Bizjak <ubizjak@gmail.com>
+ Danny Smith <dansmister@gmail.com>
+
+ PR target/37216
+
+ * lib/target-supports.exp (check_effective_target_pe_aligned_commons):
+ New function.
+ * gcc.target/i386/pr37216.c: New test source file.
+ * gcc.dg/compat/struct-layout-1_generate.c (dg_options[]): No longer
+ use -fno-common for testing Cygwin and MinGW targets.
+
+2009-05-28 Kai Tietz <kai.tietz@onevision.com>
+
+ * g++.dg/ext/packed6.C (size_t): Use __extension__ and
+ __SIZE_TYPE__.
+ * g++.dg/opt/memcpy1.C (size_t): Likewise.
+ * g++.dg/pr37742.C (size_t): Likewise.
+ * g++.dg/torture/pr34850.C (size_t): Likewise.
+ * g++.dg/torture/20070621-1.C (ptrdiff_t): Use __extension__ and
+ _PTRDIFF_TYPE__.
+ * g++.dg/torture/pr34222.C (ptrdiff_t): Likewise.
+ * g++.dg/tree-ssa/pr22444.C (ptrdiff_t): Likewise.
+ (size_t): Use __extension__ and __SIZE_TYPE__.
+ * gcc.c-torture/compile/20000211-1.c (size_t): Typedef size_t via
+ __SIZE_TYPE__.
+ * gcc.c-torture/compile/20010328-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/20030320-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/20030405-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/20030902-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/20060202-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/20080613-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/920428-2.c (size_t): Likewise,
+ * gcc.c-torture/compile/980329-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/980816-1.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr32584.c (size_t): Likewise,
+ * (__ssize_t): Likewise.
+ * gcc.c-torture/compile/pr33173.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr33382.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr34334.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr34688.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr35043.c (size_t): Likewise,
+ * gcc.c-torture/compile/pr37669.c (size_t): Likewise,
+ * gcc.dg/20050629-1.c (size_t): Typedef size_t via __SIZE_TYPE__.
+ * gcc.dg/pr33667.c (size_t): Likewise.
+ * gcc.dg/prefetch-loop-arrays-1.c (size_t): Likewise.
+ * gcc.dg/torture/pr39204.c (size_t): Likewise.
+ * gcc.dg/tree-ssa/20041122-1.c (size_t): Likewise.
+ * gcc.dg/tree-ssa/pr36908.c (size_t): Likewise.
+ * gcc.dg/tree-ssa/pr38250.c (size_t): Likewise.
+ * gcc.dg/tree-ssa/ssa-dse-10.c (size_t): Likewise.
+
+2009-05-28 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/40254
+ * gcc.dg/vect/pr40254.c: New test.
+
+2009-05-28 Adam Nemet <anemet@caviumnetworks.com>
+
+ PR middle-end/33699
+ * gcc.target/mips/const-anchor-1.c: New test.
+ * gcc.target/mips/const-anchor-2.c: New test.
+
+2009-05-27 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/initlist15.C: New.
+ * g++.dg/cpp0x/initlist16.C: New.
+ * g++.dg/cpp0x/initlist17.C: New.
+
+2009-05-27 Janne Blomqvist <jb@gcc.gnu.org>
+
+ PR fortran/39178
+ * gfortran.dg/elemental_dependency_1.f90: Fix scan-tree-dump-times
+ patterns to reflect frontend changes.
+ * gfortran.dg/vector_subscript_4.f90: Likewise.
+
+2009-05-27 Olivier Hainque <hainque@adacore.com>
+ Eric Botcazou <botcazou@adacore.com>
+
+ * gcc.c-torture/execute/align-nest.c: New testcase.
+ * gnat.dg/misaligned_nest.adb: New testcase.
+
+2009-05-27 Rafael Avila de Espindola <espindola@google.com>
+
+ * g++.dg/plugin/attribute_plugin.c: Include gcc-plugin.h first.
+ * g++.dg/plugin/dumb_plugin.c: Include gcc-plugin.h first.
+ * g++.dg/plugin/selfassign.c: Include gcc-plugin.h first.
+ * gcc.dg/plugin/selfassign.c: Include gcc-plugin.h first.
+
+2009-05-27 Kai TIetz <kai.tietz@onevision.com>
+
+ * g++.old-deja/g++.brendan/array1.C (array): Use __SIZE_TYPE__
+ cast instead of assuming 0ul.
+ * g++.old-deja/g++.brendan/crash64.C (size_t): Define it via
+ __SIZE_TYPE__.
+ (_type_desc): Make first argument const.
+ * g++.old-deja/g++.jason/new3.C (dg-options): Add -Wno-long-long.
+
+2009-05-27 Thomas Koenig <tkoenig@gcc.gnu.org>
+
+ PR libfortran/40187
+ * gfortran.dg/c_f_pointer_shape_tests_4.f03: New file.
+ * gfortran.dg/c_f_pointer_shape_tests_4_driver.c: New file.
+
+2009-05-26 Basile Starynkevitch <basile@starynkevitch.net>
+
+ * testsuite/gcc.dg/plugin/plugin.exp: Added ggcplug.c test plugin
+ with ggcplug-test-1.c for testing PLUGIN_GGC_MARKING etc...
+ * testsuite/gcc.dg/plugin/ggcplug-test-1.c: Added new file.
+ * testsuite/gcc.dg/plugin/ggcplug.c: Added new file.
+
+2009-05-26 Tobias Burnus <burnus@net-b.de>
+
+ PR fortran/40246
+ * gfortran.dg/nullify_4.f90: New test.
+
+2009-05-26 Richard Guenther <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/inline-3.c: Remove dump file.
+
+2009-05-26 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/40252
+ * gcc.c-torture/compile/pr40252.c: New testcase.
+
+2009-05-26 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/40007
+ * g++.dg/template/typedef18.C: New test.
+ * g++.dg/template/typedef19.C: Likewise.
+ * g++.dg/template/typedef20.C: Likewise.
+ * g++.dg/template/access11.C: Adjust.
+
+2009-05-26 Richard Guenther <rguenther@suse.de>
+
+ PR testsuite/40247
+ * gcc.dg/struct/wo_prof_escape_substr_pointer.c: Obfuscate.
+
2009-05-25 Jason Merrill <jason@redhat.com>
PR c++/38064
diff --git a/gcc/testsuite/g++.dg/cpp0x/auto14.C b/gcc/testsuite/g++.dg/cpp0x/auto14.C
new file mode 100644
index 00000000000..cb2c4e0351a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/auto14.C
@@ -0,0 +1,29 @@
+// PR c++/40306, c++/40307
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+template< typename T >
+struct test {
+ test run() {
+ auto tmp = *this;
+ return tmp;
+ }
+ test run_pass() {
+ test tmp( *this );
+ return tmp;
+ }
+
+ test run_fail() {
+ auto tmp( *this );
+ return tmp;
+ }
+};
+
+int main()
+{
+ test<int> x;
+ x.run();
+ x.run_pass();
+ x.run_fail();
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist13.C b/gcc/testsuite/g++.dg/cpp0x/initlist13.C
index 98af92bca53..9ed6c74419f 100644
--- a/gcc/testsuite/g++.dg/cpp0x/initlist13.C
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist13.C
@@ -2,4 +2,7 @@
// { dg-do compile }
// { dg-options "-std=gnu++0x" }
-__complex__ int i ({0}); // { dg-error "cannot convert" }
+#include <complex>
+
+__complex__ int i ({0});
+std::complex<int> i2 ({0});
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist15.C b/gcc/testsuite/g++.dg/cpp0x/initlist15.C
new file mode 100644
index 00000000000..d59e5af640b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist15.C
@@ -0,0 +1,17 @@
+// { dg-options "-std=c++0x" }
+
+#include <vector>
+#include <typeinfo>
+
+using namespace std;
+
+template< typename ... ArgTypes >
+void test( ArgTypes ... args ) {
+ vector<type_info*> x = { &typeid(ArgTypes)... }; // { dg-error "" }
+}
+
+int main()
+{
+ test( 1, 3.14f, 2.78 );
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist16.C b/gcc/testsuite/g++.dg/cpp0x/initlist16.C
new file mode 100644
index 00000000000..86a00396051
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist16.C
@@ -0,0 +1,12 @@
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+extern "C" void abort();
+
+void f(int i) { if (i != 42) abort(); }
+
+int main()
+{
+ f({42});
+ return {0};
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist17.C b/gcc/testsuite/g++.dg/cpp0x/initlist17.C
new file mode 100644
index 00000000000..86371e81969
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist17.C
@@ -0,0 +1,9 @@
+// { dg-options "-std=c++0x" }
+
+void f(int i);
+
+int main()
+{
+ f({42.0}); // { dg-error "narrowing" }
+ return {1.0}; // { dg-error "narrowing" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist18.C b/gcc/testsuite/g++.dg/cpp0x/initlist18.C
new file mode 100644
index 00000000000..c9a9bcd9415
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist18.C
@@ -0,0 +1,19 @@
+// PR c++/40308, 40311
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+template< typename T >
+struct test {
+ test() : data{} {}
+
+ T data;
+};
+
+int main()
+{
+ test<int> x;
+ test<int*> y;
+ int * a = new int{};
+ int * b = new int{5};
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist19.C b/gcc/testsuite/g++.dg/cpp0x/initlist19.C
new file mode 100644
index 00000000000..418cddc618a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist19.C
@@ -0,0 +1,8 @@
+// { dg-options "-std=c++0x" }
+
+void f(double);
+int main()
+{
+ f({{1}}); // { dg-error "too many braces" }
+ // { dg-error "" "" { target *-*-* } 6 } allow other errors, too
+}
diff --git a/gcc/testsuite/g++.dg/ext/packed6.C b/gcc/testsuite/g++.dg/ext/packed6.C
index f89aafec163..6a176b62442 100644
--- a/gcc/testsuite/g++.dg/ext/packed6.C
+++ b/gcc/testsuite/g++.dg/ext/packed6.C
@@ -1,7 +1,7 @@
// PR c++/15209
// { dg-options "-w" }
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
diff --git a/gcc/testsuite/g++.dg/init/ref15.C b/gcc/testsuite/g++.dg/init/ref15.C
index d3a94227fd0..bc9c01dc229 100644
--- a/gcc/testsuite/g++.dg/init/ref15.C
+++ b/gcc/testsuite/g++.dg/init/ref15.C
@@ -1,6 +1,8 @@
// PR c++/20416. We correctly constructed the temporary S in foo(),
// but incorrectly destroyed it every time foo() was called.
-// { dg-do run }
+// When using a wrapped target, there is no way to override the exit
+// code after returning from main.
+// { dg-do run { target unwrapped } }
extern "C" void abort (void);
extern "C" void _exit (int);
diff --git a/gcc/testsuite/g++.dg/opt/memcpy1.C b/gcc/testsuite/g++.dg/opt/memcpy1.C
index f9887ee2314..f2913459973 100644
--- a/gcc/testsuite/g++.dg/opt/memcpy1.C
+++ b/gcc/testsuite/g++.dg/opt/memcpy1.C
@@ -6,7 +6,7 @@
typedef unsigned char uint8_t;
typedef uint8_t uint8;
-typedef long unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
class csVector2
{
public:float x;
diff --git a/gcc/testsuite/g++.dg/plugin/attribute_plugin.c b/gcc/testsuite/g++.dg/plugin/attribute_plugin.c
index 2624ea2da0c..16b34964350 100644
--- a/gcc/testsuite/g++.dg/plugin/attribute_plugin.c
+++ b/gcc/testsuite/g++.dg/plugin/attribute_plugin.c
@@ -1,5 +1,6 @@
/* Demonstrates how to add custom attributes */
+#include "gcc-plugin.h"
#include <stdlib.h>
#include "config.h"
#include "system.h"
@@ -7,7 +8,6 @@
#include "tree.h"
#include "tree-pass.h"
#include "intl.h"
-#include "gcc-plugin.h"
/* Attribute handler callback */
diff --git a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
index 81e68eb5e51..24da5440391 100644
--- a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
+++ b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
@@ -1,6 +1,7 @@
/* A trivial (dumb) plugin example that shows how to use the GCC plugin
mechanism. */
+#include "gcc-plugin.h"
#include <stdlib.h>
#include "config.h"
#include "system.h"
@@ -8,7 +9,6 @@
#include "tree.h"
#include "tree-pass.h"
#include "intl.h"
-#include "gcc-plugin.h"
/* Callback function to invoke after GCC finishes parsing a struct. */
diff --git a/gcc/testsuite/g++.dg/plugin/selfassign.c b/gcc/testsuite/g++.dg/plugin/selfassign.c
index 9e7e84c2db0..2bc1d861358 100644
--- a/gcc/testsuite/g++.dg/plugin/selfassign.c
+++ b/gcc/testsuite/g++.dg/plugin/selfassign.c
@@ -2,6 +2,7 @@
self-assignment statements. */
/* { dg-options "-O" } */
+#include "gcc-plugin.h"
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -12,7 +13,6 @@
#include "tree.h"
#include "tree-pass.h"
#include "intl.h"
-#include "gcc-plugin.h"
/* Indicate whether to check overloaded operator '=', which is performed by
diff --git a/gcc/testsuite/g++.dg/pr37742.C b/gcc/testsuite/g++.dg/pr37742.C
index 784eb498487..2bbb01723fb 100644
--- a/gcc/testsuite/g++.dg/pr37742.C
+++ b/gcc/testsuite/g++.dg/pr37742.C
@@ -1,6 +1,6 @@
/* { dg-do compile } */
-typedef long unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
void* __valarray_get_memory(size_t __n);
int*__restrict__
__valarray_get_storage(size_t __n)
diff --git a/gcc/testsuite/g++.dg/template/access11.C b/gcc/testsuite/g++.dg/template/access11.C
index 38bd5155f65..c9364a82399 100644
--- a/gcc/testsuite/g++.dg/template/access11.C
+++ b/gcc/testsuite/g++.dg/template/access11.C
@@ -17,7 +17,7 @@ template <> struct X::Y<int> {
A::X x; // { dg-error "this context" }
};
-template <typename T> struct X::Y { // { dg-error "this context" }
+template <typename T> struct X::Y {
typename T::X x; // { dg-error "this context" }
};
diff --git a/gcc/testsuite/g++.dg/template/canon-type-1.C b/gcc/testsuite/g++.dg/template/canon-type-1.C
new file mode 100644
index 00000000000..2a36dc09951
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-1.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+template < typename > struct A ;
+template < typename T , typename = A < T > > struct B { } ;
+template < class W , class > struct D
+{
+ typedef W X ;
+ A<X*> a ;
+};
+
+template < class Y > struct E
+{
+ B<Y*> b ;
+} ;
+E<int> e ;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-2.C b/gcc/testsuite/g++.dg/template/canon-type-2.C
new file mode 100644
index 00000000000..dd23ec5ea6d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-2.C
@@ -0,0 +1,18 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+template < typename > struct A ;
+template < typename T , typename = A < T > > struct B { } ;
+template < class W , class > struct D
+{
+ typedef W X ;
+ A< X()> a ;
+};
+
+template < class Y > struct E
+{
+ B< Y()> b ;
+};
+E<int> e ;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-3.C b/gcc/testsuite/g++.dg/template/canon-type-3.C
new file mode 100644
index 00000000000..a43169addc5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-3.C
@@ -0,0 +1,20 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+template<typename> struct A ;
+template<typename T , typename = A<T> > struct B { } ;
+template<class W , class > struct D
+{
+ typedef W X ;
+ typedef X (FP) ();
+ A<FP&> a ;
+} ;
+
+template < class Y > struct E
+{
+ typedef Y (FP) ();
+ B<FP&> b ;
+} ;
+E < int > e ;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-4.C b/gcc/testsuite/g++.dg/template/canon-type-4.C
new file mode 100644
index 00000000000..ec5e1e6a200
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-4.C
@@ -0,0 +1,22 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+template<typename> struct A ;
+template<typename T ,typename = A<T> > struct B { } ;
+
+template<class W, class>
+struct D
+{
+ typedef W X;
+ A<X[2]> a;
+} ;
+
+template<class Y>
+struct E
+{
+ B<Y[2]> b;
+};
+
+E < int > e;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-5.C b/gcc/testsuite/g++.dg/template/canon-type-5.C
new file mode 100644
index 00000000000..7331c3086fb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-5.C
@@ -0,0 +1,22 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+struct Foo {};
+template<typename> struct A ;
+template<typename T ,typename = A<T> > struct B { } ;
+
+template<class W, class>
+struct D
+{
+ typedef W X ;
+ A<X Foo::*> a ;
+} ;
+
+template<class Y>
+struct E
+{
+ B<Y Foo::*> b ;
+} ;
+E < int > e ;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-6.C b/gcc/testsuite/g++.dg/template/canon-type-6.C
new file mode 100644
index 00000000000..5065c395dc4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-6.C
@@ -0,0 +1,22 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+struct Foo {};
+template<typename> struct A ;
+template<typename T ,typename = A<T> > struct B { } ;
+
+template<class W, class>
+struct D
+{
+ typedef W X;
+ A<void (Foo::*) (X)> a;
+} ;
+
+template<class Y>
+struct E
+{
+ B<void (Foo::*) (Y)> b;
+};
+E < int > e ;
+
diff --git a/gcc/testsuite/g++.dg/template/canon-type-7.C b/gcc/testsuite/g++.dg/template/canon-type-7.C
new file mode 100644
index 00000000000..80e8f87e834
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/canon-type-7.C
@@ -0,0 +1,21 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/39754
+// { dg-do "compile" }
+
+struct Foo {};
+template<typename> struct A ;
+template<typename T ,typename = A<T> > struct B { } ;
+
+template<class W, class>
+struct D
+{
+ typedef W X;
+ A<X (Foo::*) (X)> a ;
+};
+
+template<class Y>
+struct E
+{
+ B<Y (Foo::*) (Y)> b ;
+};
+E<int> e ;
diff --git a/gcc/testsuite/g++.dg/template/spec36.C b/gcc/testsuite/g++.dg/template/spec36.C
new file mode 100644
index 00000000000..71ff3a5c545
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/spec36.C
@@ -0,0 +1,16 @@
+/* PR c++/38089 */
+/* { dg-do "compile" } */
+
+struct basic_string
+{
+ basic_string(const int __s);
+};
+namespace MyNS {
+ class MyClass {
+ template <typename T>
+ T test() { } /* { dg-error "from definition" } */
+ };
+}
+template <>
+basic_string MyNS::MyClass::test() /* { dg-error "specialization of" } */
+{ return 1; }
diff --git a/gcc/testsuite/g++.dg/template/typedef18.C b/gcc/testsuite/g++.dg/template/typedef18.C
new file mode 100644
index 00000000000..8ea3c736a0a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef18.C
@@ -0,0 +1,24 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/40007
+// { dg-do compile }
+
+template<typename T>
+struct x
+{
+ protected:
+ typedef int type;
+};
+
+template<typename T>
+struct y : public x<T>
+{
+ typename x<T>::type z;
+};
+
+template<>
+struct y<void> : public x<void>
+{
+ typedef x<void>::type z;
+};
+
+template class y<int>;
diff --git a/gcc/testsuite/g++.dg/template/typedef19.C b/gcc/testsuite/g++.dg/template/typedef19.C
new file mode 100644
index 00000000000..f576d4828e4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef19.C
@@ -0,0 +1,21 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/40007
+// { dg-do compile }
+
+class A
+{
+ typedef int mytype; // { dg-error "'typedef int A::mytype' is private" }
+};
+
+template <class T>
+class B : public A
+{
+};
+
+template<class T>
+class B<T*> : public A
+{ // { dg-error "within this context" }
+ mytype mem;
+};
+
+B<int*> b;
diff --git a/gcc/testsuite/g++.dg/template/typedef20.C b/gcc/testsuite/g++.dg/template/typedef20.C
new file mode 100644
index 00000000000..a5cbdeb236b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/typedef20.C
@@ -0,0 +1,27 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR c++/40007
+// { dg-do compile }
+
+class x
+{
+ typedef int privtype; // { dg-error "is private" }
+
+protected:
+ typedef int type;
+};
+
+template<typename T>
+struct y : public x
+{
+ typename x::type z;
+};
+
+template<typename T>
+struct y<T*> : public x
+{ // { dg-error "within this context" }
+ typedef x::type good;
+ typedef x::privtype bad;
+};
+
+template class y<int>;
+template class y<int*>;
diff --git a/gcc/testsuite/g++.dg/torture/20070621-1.C b/gcc/testsuite/g++.dg/torture/20070621-1.C
index d17db9763ae..185314a47ca 100644
--- a/gcc/testsuite/g++.dg/torture/20070621-1.C
+++ b/gcc/testsuite/g++.dg/torture/20070621-1.C
@@ -6,7 +6,7 @@
*/
-typedef long int ptrdiff_t;
+__extension__ typedef __PTRDIFF_TYPE__ ptrdiff_t;
namespace std __attribute__ ((__visibility__ ("default"))) {
template<typename, typename> struct __are_same {
enum {
diff --git a/gcc/testsuite/g++.dg/torture/pr34222.C b/gcc/testsuite/g++.dg/torture/pr34222.C
index 1939b5015b1..130896dc9da 100644
--- a/gcc/testsuite/g++.dg/torture/pr34222.C
+++ b/gcc/testsuite/g++.dg/torture/pr34222.C
@@ -3,7 +3,7 @@
namespace std __attribute__ ((__visibility__ ("default"))) {
template<class _CharT> struct char_traits;
}
-typedef long int ptrdiff_t;
+__extension__ typedef __PTRDIFF_TYPE__ ptrdiff_t;
namespace std __attribute__ ((__visibility__ ("default"))) {
typedef ptrdiff_t streamsize;
template<typename _CharT, typename _Traits = char_traits<_CharT> > class basic_ifstream;
diff --git a/gcc/testsuite/g++.dg/torture/pr34850.C b/gcc/testsuite/g++.dg/torture/pr34850.C
index e7caa7b6638..88df5a3382b 100644
--- a/gcc/testsuite/g++.dg/torture/pr34850.C
+++ b/gcc/testsuite/g++.dg/torture/pr34850.C
@@ -5,7 +5,7 @@ typedef unsigned char uint8_t;
typedef unsigned int uint32_t;
typedef uint8_t byte;
typedef uint32_t u32bit;
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
extern "C" {
extern void __warn_memset_zero_len (void) __attribute__((__warning__ ("")));
extern __inline __attribute__ ((__always_inline__)) __attribute__ ((__gnu_inline__, __artificial__))
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr22444.C b/gcc/testsuite/g++.dg/tree-ssa/pr22444.C
index 2cc84bb9d1e..7df4b9cce15 100644
--- a/gcc/testsuite/g++.dg/tree-ssa/pr22444.C
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr22444.C
@@ -4,8 +4,8 @@
// with the subvars leading to the subvars not being renamed when they should
// { dg-do compile }
// { dg-options "-O2" }
-typedef int ptrdiff_t;
-typedef unsigned int size_t;
+__extension__ typedef __PTRDIFF_TYPE__ ptrdiff_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
namespace std
{
template<class _T1, class _T2> struct pair
diff --git a/gcc/testsuite/g++.dg/warn/Wcast-qual2.C b/gcc/testsuite/g++.dg/warn/Wcast-qual2.C
new file mode 100644
index 00000000000..88fdcfb38f5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/Wcast-qual2.C
@@ -0,0 +1,167 @@
+/* { dg-do compile } */
+/* { dg-options "-Wcast-qual" } */
+
+/* The files gcc.dg/cast-qual-3.c and g++.dg/warn/Wcast-qual2.c are
+ duals. they are intended to show that gcc -Wcast-qual and g++
+ -Wcast-qual emit warnings in the same cases. If you change this
+ file, please also change the other one. */
+
+void
+f1 (void *bar)
+{
+ const void *p1 = (const void *) bar;
+ const char *p2 = (const char *) bar;
+ const void **p3 = (const void **) bar;
+ const char **p4 = (const char **) bar;
+ const void * const *p5 = (const void * const *) bar;
+ const char * const *p6 = (const char * const *) bar;
+ void * const *p7 = (void * const *) bar;
+ char * const *p8 = (char * const *) bar;
+ const void ***p9 = (const void ***) bar;
+ const char ***p10 = (const char ***) bar;
+ void * const **p11 = (void * const **) bar;
+ char * const **p12 = (char * const **) bar;
+ void ** const *p13 = (void ** const *) bar;
+ char ** const *p14 = (char ** const *) bar;
+ const void * const **p15 = (const void * const **) bar;
+ const char * const **p16 = (const char * const **) bar;
+ const void ** const *p17 = (const void ** const *) bar;
+ const char ** const *p18 = (const char ** const *) bar;
+ void * const * const * p19 = (void * const * const *) bar;
+ char * const * const * p20 = (char * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+ const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f2 (void **bar)
+{
+ const void *p1 = (const void *) bar;
+ const char *p2 = (const char *) bar;
+ const void **p3 = (const void **) bar; /* { dg-warning "cast" } */
+ const char **p4 = (const char **) bar;
+ const void * const *p5 = (const void * const *) bar;
+ const char * const *p6 = (const char * const *) bar;
+ void * const *p7 = (void * const *) bar;
+ char * const *p8 = (char * const *) bar;
+ const void ***p9 = (const void ***) bar;
+ const char ***p10 = (const char ***) bar;
+ void * const **p11 = (void * const **) bar;
+ char * const **p12 = (char * const **) bar;
+ void ** const *p13 = (void ** const *) bar;
+ char ** const *p14 = (char ** const *) bar;
+ const void * const **p15 = (const void * const **) bar;
+ const char * const **p16 = (const char * const **) bar;
+ const void ** const *p17 = (const void ** const *) bar;
+ const char ** const *p18 = (const char ** const *) bar;
+ void * const * const * p19 = (void * const * const *) bar;
+ char * const * const * p20 = (char * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+ const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f3 (void ***bar)
+{
+ const void *p1 = (const void *) bar;
+ const char *p2 = (const char *) bar;
+ const void **p3 = (const void **) bar;
+ const char **p4 = (const char **) bar;
+ const void * const *p5 = (const void * const *) bar;
+ const char * const *p6 = (const char * const *) bar;
+ void * const *p7 = (void * const *) bar;
+ char * const *p8 = (char * const *) bar;
+ const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
+ const char ***p10 = (const char ***) bar;
+ void * const **p11 = (void * const **) bar; /* { dg-warning "cast" } */
+ char * const **p12 = (char * const **) bar;
+ void ** const *p13 = (void ** const *) bar;
+ char ** const *p14 = (char ** const *) bar;
+ const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
+ const char * const **p16 = (const char * const **) bar;
+ const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
+ const char ** const *p18 = (const char ** const *) bar;
+ void * const * const * p19 = (void * const * const *) bar;
+ char * const * const * p20 = (char * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+ const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f4 (void * const **bar)
+{
+ const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
+ void * const **p11 = (void * const **) bar;
+ void ** const *p13 = (void ** const *) bar; /* { dg-warning "cast" } */
+ const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
+ const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
+ void * const * const * p19 = (void * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+}
+
+void
+f5 (char ***bar)
+{
+ volatile const char ***p9 = (volatile const char ***) bar; /* { dg-warning "cast" } */
+ volatile char * const **p11 = (volatile char * const **) bar; /* { dg-warning "cast" } */
+ volatile char ** const *p13 = (volatile char ** const *) bar; /* { dg-warning "cast" } */
+ volatile const char * const **p15 = (volatile const char * const **) bar; /* { dg-warning "cast" } */
+ volatile const char ** const *p17 = (volatile const char ** const *) bar; /* { dg-warning "cast" } */
+ volatile char * const * const * p19 = (volatile char * const * const *) bar;
+ volatile const char * const * const *p21 = (volatile const char * const * const *) bar;
+}
+
+void
+f6 (char ***bar)
+{
+ const char * volatile **p9 = (const char * volatile **) bar; /* { dg-warning "cast" } */
+ char * volatile const **p11 = (char * volatile const **) bar; /* { dg-warning "cast" } */
+ char * volatile * const *p13 = (char * volatile * const *) bar;
+ const char * volatile const **p15 = (const char * volatile const **) bar; /* { dg-warning "cast" } */
+ const char * volatile * const *p17 = (const char * volatile * const *) bar; /* { dg-warning "cast" } */
+ char * volatile const * const * p19 = (char * volatile const * const *) bar;
+ const char * volatile const * const *p21 = (const char * volatile const * const *) bar;
+}
+
+void
+f7 (char ***bar)
+{
+ const char ** volatile *p9 = (const char ** volatile *) bar; /* { dg-warning "cast" } */
+ char * const * volatile *p11 = (char * const * volatile *) bar; /* { dg-warning "cast" } */
+ char ** volatile const *p13 = (char ** volatile const *) bar;
+ const char * const * volatile *p15 = (const char * const * volatile *) bar; /* { dg-warning "cast" } */
+ const char ** volatile const *p17 = (const char ** volatile const *) bar; /* { dg-warning "cast" } */
+ char * const * volatile const * p19 = (char * const * volatile const *) bar;
+ const char * const * volatile const *p21 = (const char * const * volatile const *) bar;
+}
+
+typedef int (intfn) (int);
+typedef intfn *pintfn;
+typedef const intfn *constfn;
+
+void
+f8 (constfn ***bar)
+{
+ const constfn *p1 = (const constfn *) bar;
+ const pintfn *p2 = (const pintfn *) bar;
+ const constfn **p3 = (const constfn **) bar;
+ const pintfn **p4 = (const pintfn **) bar;
+ const constfn * const *p5 = (const constfn * const *) bar;
+ const pintfn * const *p6 = (const pintfn * const *) bar;
+ constfn * const *p7 = (constfn * const *) bar;
+ pintfn * const *p8 = (pintfn * const *) bar;
+ const constfn ***p9 = (const constfn ***) bar; /* { dg-warning "cast" } */
+ const pintfn ***p10 = (const pintfn ***) bar; /* { dg-warning "cast" } */
+ constfn * const **p11 = (constfn * const **) bar; /* { dg-warning "cast" } */
+ pintfn * const **p12 = (pintfn * const **) bar; /* { dg-warning "cast" } */
+ constfn ** const *p13 = (constfn ** const *) bar;
+ pintfn ** const *p14 = (pintfn ** const *) bar;
+ const constfn * const **p15 = (const constfn * const **) bar; /* { dg-warning "cast" } */
+ const pintfn * const **p16 = (const pintfn * const **) bar; /* { dg-warning "cast" } */
+ const constfn ** const *p17 = (const constfn ** const *) bar; /* { dg-warning "cast" } */
+ const pintfn ** const *p18 = (const pintfn ** const *) bar; /* { dg-warning "cast" } */
+ constfn * const * const * p19 = (constfn * const * const *) bar;
+ pintfn * const * const * p20 = (pintfn * const * const *) bar;
+ const constfn * const * const *p21 = (const constfn * const * const *) bar;
+ const pintfn * const * const *p22 = (const pintfn * const * const *) bar;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/array1.C b/gcc/testsuite/g++.old-deja/g++.brendan/array1.C
index df132ea9024..a58d3363bcd 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/array1.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/array1.C
@@ -3,5 +3,5 @@
// GROUPS passed array-bindings
extern "C" int printf (const char *, ...);
-char array[~(~0ul>>1)|~(0ul>>3)]; // { dg-error "" } overflow in array dimension.*
+char array[~(~((__SIZE_TYPE__)0ul)>>1)|~(((__SIZE_TYPE__)0ul)>>3)]; // { dg-error "" } overflow in array dimension.*
int main () { printf ("PASS\n"); return 0; }
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
index b3717a5d999..6046cb1c9ee 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash64.C
@@ -1,6 +1,6 @@
// { dg-do assemble }
// GROUPS passed old-abort
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef void (*RF_Ptr)(void *);
struct _im_pers_mem_spec {
@@ -9,7 +9,7 @@ struct _im_pers_mem_spec {
};
struct _type_desc {
- _type_desc(char *, int , RF_Ptr , int , int ,...);
+ _type_desc(const char *, int , RF_Ptr , int , int ,...);
};
struct metatype { int base_list; };
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/new3.C b/gcc/testsuite/g++.old-deja/g++.jason/new3.C
index 62e9b7dd1b6..d950259e72a 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/new3.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/new3.C
@@ -1,5 +1,5 @@
// { dg-do run }
-// { dg-options "-fcheck-new -pedantic" }
+// { dg-options "-fcheck-new -pedantic -Wno-long-long" }
// PRMS Id: 6037
extern "C" void * malloc (__SIZE_TYPE__);
diff --git a/gcc/testsuite/gcc.c-torture/compile/20000211-1.c b/gcc/testsuite/gcc.c-torture/compile/20000211-1.c
index 8d8a4074e0f..7a7c8c0cb20 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20000211-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20000211-1.c
@@ -1,4 +1,4 @@
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef unsigned char Bufbyte;
typedef int Bytecount;
typedef int Charcount;
diff --git a/gcc/testsuite/gcc.c-torture/compile/20010328-1.c b/gcc/testsuite/gcc.c-torture/compile/20010328-1.c
index d92c6dae113..951ae78b950 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20010328-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20010328-1.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef unsigned int __u_int;
typedef unsigned long __u_long;
diff --git a/gcc/testsuite/gcc.c-torture/compile/20030320-1.c b/gcc/testsuite/gcc.c-torture/compile/20030320-1.c
index 40243f28f93..72d0d0966c6 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20030320-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20030320-1.c
@@ -2,7 +2,7 @@
conditional returns without updating dominance info.
Extracted from glibc's dl-load.c. */
-typedef unsigned long size_t;
+typedef __SIZE_TYPE__ size_t;
static size_t
is_dst (const char *start, const char *name, const char *str,
diff --git a/gcc/testsuite/gcc.c-torture/compile/20030405-1.c b/gcc/testsuite/gcc.c-torture/compile/20030405-1.c
index f84e606c045..0bdafb9239f 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20030405-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20030405-1.c
@@ -6,7 +6,7 @@
and when the PHI node at the end of the while() is visited the first
time, CCP will try to assign it a value of UNDEFINED, but the default
value for *str is a constant. */
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
size_t strlength (const char * const);
char foo();
diff --git a/gcc/testsuite/gcc.c-torture/compile/20030902-1.c b/gcc/testsuite/gcc.c-torture/compile/20030902-1.c
index 443b43921b8..56c2650b86b 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20030902-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20030902-1.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef unsigned long int reg_syntax_t;
struct re_pattern_buffer
{
diff --git a/gcc/testsuite/gcc.c-torture/compile/20060202-1.c b/gcc/testsuite/gcc.c-torture/compile/20060202-1.c
index 9d440741c6b..d16e7b7c5ad 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20060202-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20060202-1.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef const struct objc_selector
{
void *sel_id;
diff --git a/gcc/testsuite/gcc.c-torture/compile/20080613-1.c b/gcc/testsuite/gcc.c-torture/compile/20080613-1.c
index f64964e7740..20e3878420e 100644
--- a/gcc/testsuite/gcc.c-torture/compile/20080613-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/20080613-1.c
@@ -1,7 +1,7 @@
/* PR middle-end/36520 */
/* Testcase by Richard Guenther <rguenth@gcc.gnu.org> */
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef unsigned short int sa_family_t;
struct cmsghdr {
size_t cmsg_len;
diff --git a/gcc/testsuite/gcc.c-torture/compile/920428-2.c b/gcc/testsuite/gcc.c-torture/compile/920428-2.c
index 23f32a83a9d..f313b32986b 100644
--- a/gcc/testsuite/gcc.c-torture/compile/920428-2.c
+++ b/gcc/testsuite/gcc.c-torture/compile/920428-2.c
@@ -41,7 +41,7 @@ extern struct _iobuf {
short _flag;
char _file;
} _iob[];
-typedef unsigned long size_t;
+typedef __SIZE_TYPE__ size_t;
typedef char *va_list;
struct _iobuf *fopen(const char *filename, const char *type);
struct _iobuf *freopen(const char *filename, const char *type, struct _iobuf *stream);
diff --git a/gcc/testsuite/gcc.c-torture/compile/980329-1.c b/gcc/testsuite/gcc.c-torture/compile/980329-1.c
index d11b49b01c7..3b3fe27cf71 100644
--- a/gcc/testsuite/gcc.c-torture/compile/980329-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/980329-1.c
@@ -1,4 +1,4 @@
-typedef unsigned long int size_t;
+typedef __SIZE_TYPE__ size_t;
struct re_pattern_buffer
{
unsigned char *buffer;
diff --git a/gcc/testsuite/gcc.c-torture/compile/980816-1.c b/gcc/testsuite/gcc.c-torture/compile/980816-1.c
index c56b6c9b92c..a79100fab57 100644
--- a/gcc/testsuite/gcc.c-torture/compile/980816-1.c
+++ b/gcc/testsuite/gcc.c-torture/compile/980816-1.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef void *XtPointer;
typedef struct _WidgetRec *Widget;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr32584.c b/gcc/testsuite/gcc.c-torture/compile/pr32584.c
index 02799fc7449..403ea9b12fa 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr32584.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr32584.c
@@ -1,5 +1,8 @@
-typedef long unsigned int size_t;
-typedef long int __ssize_t;
+typedef __SIZE_TYPE__ size_t;
+/* Kludge */
+#define unsigned
+typedef __SIZE_TYPE__ __ssize_t;
+#undef unsigned
typedef struct
{
} __mbstate_t;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr33173.c b/gcc/testsuite/gcc.c-torture/compile/pr33173.c
index 503c7afbdac..f599297e79a 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr33173.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr33173.c
@@ -1,4 +1,4 @@
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef struct
{
}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr33382.c b/gcc/testsuite/gcc.c-torture/compile/pr33382.c
index d83f74e42cc..c939cf7b772 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr33382.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr33382.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef struct {
int disable;
char *searchconfig[];
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr34334.c b/gcc/testsuite/gcc.c-torture/compile/pr34334.c
index 15f895f1cba..30bb782626f 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr34334.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr34334.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
__extension__ typedef long long int __quad_t;
__extension__ typedef unsigned int __mode_t;
__extension__ typedef __quad_t __off64_t;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr34688.c b/gcc/testsuite/gcc.c-torture/compile/pr34688.c
index 9891c72d93d..60e0f3c9f15 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr34688.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr34688.c
@@ -1,4 +1,4 @@
-typedef unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef struct {
}
HashTable;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr35043.c b/gcc/testsuite/gcc.c-torture/compile/pr35043.c
index 29c685207b9..a14379dc148 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr35043.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr35043.c
@@ -1,4 +1,4 @@
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
typedef struct {
long double dat[2];
} gsl_complex_long_double;
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr37669.c b/gcc/testsuite/gcc.c-torture/compile/pr37669.c
index 9b003cdf099..68e96c621cf 100644
--- a/gcc/testsuite/gcc.c-torture/compile/pr37669.c
+++ b/gcc/testsuite/gcc.c-torture/compile/pr37669.c
@@ -1,6 +1,6 @@
/* This testcase used to fail because a miscompiled execute_fold_all_builtins. */
-typedef long unsigned int size_t;
+typedef __SIZE_TYPE__ size_t;
extern __inline __attribute__ ((__always_inline__)) int __attribute__
((__nothrow__)) snprintf (char *__restrict __s, size_t __n, __const char
*__restrict __fmt, ...) {
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr40252.c b/gcc/testsuite/gcc.c-torture/compile/pr40252.c
new file mode 100644
index 00000000000..f58e799b01f
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40252.c
@@ -0,0 +1,6 @@
+typedef unsigned int uint32_t;
+static void IP(uint32_t v[2])
+{
+ v[0] = ((v[0] << 1) | ((v[0] >> 31) & 1L)) & 0xffffffffL;
+}
+
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr40291.c b/gcc/testsuite/gcc.c-torture/compile/pr40291.c
new file mode 100644
index 00000000000..d50bbee6608
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40291.c
@@ -0,0 +1,7 @@
+/* PR middle-end/40291 */
+
+int
+foo (void *x, char *y, unsigned long long z)
+{
+ return memcmp (x, y, z);
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/sra-1.c b/gcc/testsuite/gcc.c-torture/compile/sra-1.c
new file mode 100644
index 00000000000..06dcf1002be
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/sra-1.c
@@ -0,0 +1,75 @@
+/* { dg-do compile } */
+/* { dg-options "-O1" } */
+/* Let gimple verifier check what SRA does to unions and single-field
+ strucutres . */
+
+struct sim_struct
+{
+ int x;
+};
+
+extern struct sim_struct get_x(void);
+
+struct sim_struct foo (void)
+{
+ struct sim_struct simple;
+
+ simple = get_x ();
+ if (simple.x % 2)
+ simple.x = 39;
+ else
+ simple.x -=8;
+
+ return simple;
+}
+
+struct sim_cmplx
+{
+ _Complex double c;
+};
+
+extern struct sim_cmplx get_sc (void);
+
+_Complex double foo_c (void)
+{
+ struct sim_cmplx simple;
+
+ simple = get_sc ();
+ if (__real__ simple.c > 200.3)
+ __imag__ simple.c -= 2.4;
+
+ return simple.c;
+}
+
+
+union sim_union
+{
+ int i;
+ float d;
+};
+
+extern union sim_union get_y (void);
+
+union sim_union bar (void)
+{
+ union sim_union simple;
+
+ simple = get_y ();
+ if (simple.d > 8.2)
+ simple.i = 300;
+
+ return simple;
+}
+
+extern int get_int (void);
+
+int bar_i (void)
+{
+ union sim_union simple;
+
+ simple = get_y ();
+ if (simple.d > 8.2)
+ simple.i = get_int ();
+
+ return simple.i;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/20090527-1.c b/gcc/testsuite/gcc.c-torture/execute/20090527-1.c
new file mode 100644
index 00000000000..d8e3711cdf6
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20090527-1.c
@@ -0,0 +1,38 @@
+typedef enum { POSITION_ASIS, POSITION_UNSPECIFIED } unit_position;
+
+typedef enum { STATUS_UNKNOWN, STATUS_UNSPECIFIED } unit_status;
+
+typedef struct
+{
+ unit_position position;
+ unit_status status;
+} unit_flags;
+
+extern void abort (void);
+
+void
+new_unit (unit_flags * flags)
+{
+ if (flags->status == STATUS_UNSPECIFIED)
+ flags->status = STATUS_UNKNOWN;
+
+ if (flags->position == POSITION_UNSPECIFIED)
+ flags->position = POSITION_ASIS;
+
+ switch (flags->status)
+ {
+ case STATUS_UNKNOWN:
+ break;
+
+ default:
+ abort ();
+ }
+}
+
+int main()
+{
+ unit_flags f;
+ f.status = STATUS_UNSPECIFIED;
+ new_unit (&f);
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/align-nest.c b/gcc/testsuite/gcc.c-torture/execute/align-nest.c
new file mode 100644
index 00000000000..2ff2952c70c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/align-nest.c
@@ -0,0 +1,28 @@
+
+void foo(int n)
+{
+ typedef struct
+ {
+ int value;
+ } myint;
+
+ struct S
+ {
+ int i[n];
+ unsigned int b:1;
+ myint mi;
+ } __attribute__ ((packed)) __attribute__ ((aligned (4)));
+
+ struct S s[2];
+ int k;
+
+ for (k = 0; k < 2; k ++)
+ s[k].mi.value = 0;
+}
+
+int main ()
+{
+ foo (2);
+ return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/20050629-1.c b/gcc/testsuite/gcc.dg/20050629-1.c
index 67d73f0eb66..0dd47f7024b 100644
--- a/gcc/testsuite/gcc.dg/20050629-1.c
+++ b/gcc/testsuite/gcc.dg/20050629-1.c
@@ -5,7 +5,7 @@
contains many warnings, but it exposes a copy propagation bug that
is somewhat difficult to reproduce otherwise. */
-typedef long unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
extern void fancy_abort (const char *, int, const char *) __attribute__ ((__noreturn__));
typedef union tree_node *tree;
enum tree_code {
diff --git a/gcc/testsuite/gcc.dg/Wcxx-compat-11.c b/gcc/testsuite/gcc.dg/Wcxx-compat-11.c
new file mode 100644
index 00000000000..8818338ad5e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/Wcxx-compat-11.c
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-Wc++-compat" } */
+
+#include <stdarg.h>
+
+enum E { A };
+
+extern void f2 (int);
+void
+f1 (int n, ...)
+{
+ va_list ap;
+
+ va_start (ap, n);
+ f2 (va_arg (ap, int));
+ f2 (va_arg (ap, _Bool)); /* { dg-warning "promoted" } */
+ f2 (va_arg (ap, enum E)); /* { dg-warning "promoted" } */
+}
+
+/* Match extra informative notes. */
+/* { dg-message "note:" "expected" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/cast-qual-3.c b/gcc/testsuite/gcc.dg/cast-qual-3.c
new file mode 100644
index 00000000000..88fdcfb38f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/cast-qual-3.c
@@ -0,0 +1,167 @@
+/* { dg-do compile } */
+/* { dg-options "-Wcast-qual" } */
+
+/* The files gcc.dg/cast-qual-3.c and g++.dg/warn/Wcast-qual2.c are
+ duals. they are intended to show that gcc -Wcast-qual and g++
+ -Wcast-qual emit warnings in the same cases. If you change this
+ file, please also change the other one. */
+
+void
+f1 (void *bar)
+{
+ const void *p1 = (const void *) bar;
+ const char *p2 = (const char *) bar;
+ const void **p3 = (const void **) bar;
+ const char **p4 = (const char **) bar;
+ const void * const *p5 = (const void * const *) bar;
+ const char * const *p6 = (const char * const *) bar;
+ void * const *p7 = (void * const *) bar;
+ char * const *p8 = (char * const *) bar;
+ const void ***p9 = (const void ***) bar;
+ const char ***p10 = (const char ***) bar;
+ void * const **p11 = (void * const **) bar;
+ char * const **p12 = (char * const **) bar;
+ void ** const *p13 = (void ** const *) bar;
+ char ** const *p14 = (char ** const *) bar;
+ const void * const **p15 = (const void * const **) bar;
+ const char * const **p16 = (const char * const **) bar;
+ const void ** const *p17 = (const void ** const *) bar;
+ const char ** const *p18 = (const char ** const *) bar;
+ void * const * const * p19 = (void * const * const *) bar;
+ char * const * const * p20 = (char * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+ const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f2 (void **bar)
+{
+ const void *p1 = (const void *) bar;
+ const char *p2 = (const char *) bar;
+ const void **p3 = (const void **) bar; /* { dg-warning "cast" } */
+ const char **p4 = (const char **) bar;
+ const void * const *p5 = (const void * const *) bar;
+ const char * const *p6 = (const char * const *) bar;
+ void * const *p7 = (void * const *) bar;
+ char * const *p8 = (char * const *) bar;
+ const void ***p9 = (const void ***) bar;
+ const char ***p10 = (const char ***) bar;
+ void * const **p11 = (void * const **) bar;
+ char * const **p12 = (char * const **) bar;
+ void ** const *p13 = (void ** const *) bar;
+ char ** const *p14 = (char ** const *) bar;
+ const void * const **p15 = (const void * const **) bar;
+ const char * const **p16 = (const char * const **) bar;
+ const void ** const *p17 = (const void ** const *) bar;
+ const char ** const *p18 = (const char ** const *) bar;
+ void * const * const * p19 = (void * const * const *) bar;
+ char * const * const * p20 = (char * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+ const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f3 (void ***bar)
+{
+ const void *p1 = (const void *) bar;
+ const char *p2 = (const char *) bar;
+ const void **p3 = (const void **) bar;
+ const char **p4 = (const char **) bar;
+ const void * const *p5 = (const void * const *) bar;
+ const char * const *p6 = (const char * const *) bar;
+ void * const *p7 = (void * const *) bar;
+ char * const *p8 = (char * const *) bar;
+ const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
+ const char ***p10 = (const char ***) bar;
+ void * const **p11 = (void * const **) bar; /* { dg-warning "cast" } */
+ char * const **p12 = (char * const **) bar;
+ void ** const *p13 = (void ** const *) bar;
+ char ** const *p14 = (char ** const *) bar;
+ const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
+ const char * const **p16 = (const char * const **) bar;
+ const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
+ const char ** const *p18 = (const char ** const *) bar;
+ void * const * const * p19 = (void * const * const *) bar;
+ char * const * const * p20 = (char * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+ const char * const * const *p22 = (const char * const * const *) bar;
+}
+
+void
+f4 (void * const **bar)
+{
+ const void ***p9 = (const void ***) bar; /* { dg-warning "cast" } */
+ void * const **p11 = (void * const **) bar;
+ void ** const *p13 = (void ** const *) bar; /* { dg-warning "cast" } */
+ const void * const **p15 = (const void * const **) bar; /* { dg-warning "cast" } */
+ const void ** const *p17 = (const void ** const *) bar; /* { dg-warning "cast" } */
+ void * const * const * p19 = (void * const * const *) bar;
+ const void * const * const *p21 = (const void * const * const *) bar;
+}
+
+void
+f5 (char ***bar)
+{
+ volatile const char ***p9 = (volatile const char ***) bar; /* { dg-warning "cast" } */
+ volatile char * const **p11 = (volatile char * const **) bar; /* { dg-warning "cast" } */
+ volatile char ** const *p13 = (volatile char ** const *) bar; /* { dg-warning "cast" } */
+ volatile const char * const **p15 = (volatile const char * const **) bar; /* { dg-warning "cast" } */
+ volatile const char ** const *p17 = (volatile const char ** const *) bar; /* { dg-warning "cast" } */
+ volatile char * const * const * p19 = (volatile char * const * const *) bar;
+ volatile const char * const * const *p21 = (volatile const char * const * const *) bar;
+}
+
+void
+f6 (char ***bar)
+{
+ const char * volatile **p9 = (const char * volatile **) bar; /* { dg-warning "cast" } */
+ char * volatile const **p11 = (char * volatile const **) bar; /* { dg-warning "cast" } */
+ char * volatile * const *p13 = (char * volatile * const *) bar;
+ const char * volatile const **p15 = (const char * volatile const **) bar; /* { dg-warning "cast" } */
+ const char * volatile * const *p17 = (const char * volatile * const *) bar; /* { dg-warning "cast" } */
+ char * volatile const * const * p19 = (char * volatile const * const *) bar;
+ const char * volatile const * const *p21 = (const char * volatile const * const *) bar;
+}
+
+void
+f7 (char ***bar)
+{
+ const char ** volatile *p9 = (const char ** volatile *) bar; /* { dg-warning "cast" } */
+ char * const * volatile *p11 = (char * const * volatile *) bar; /* { dg-warning "cast" } */
+ char ** volatile const *p13 = (char ** volatile const *) bar;
+ const char * const * volatile *p15 = (const char * const * volatile *) bar; /* { dg-warning "cast" } */
+ const char ** volatile const *p17 = (const char ** volatile const *) bar; /* { dg-warning "cast" } */
+ char * const * volatile const * p19 = (char * const * volatile const *) bar;
+ const char * const * volatile const *p21 = (const char * const * volatile const *) bar;
+}
+
+typedef int (intfn) (int);
+typedef intfn *pintfn;
+typedef const intfn *constfn;
+
+void
+f8 (constfn ***bar)
+{
+ const constfn *p1 = (const constfn *) bar;
+ const pintfn *p2 = (const pintfn *) bar;
+ const constfn **p3 = (const constfn **) bar;
+ const pintfn **p4 = (const pintfn **) bar;
+ const constfn * const *p5 = (const constfn * const *) bar;
+ const pintfn * const *p6 = (const pintfn * const *) bar;
+ constfn * const *p7 = (constfn * const *) bar;
+ pintfn * const *p8 = (pintfn * const *) bar;
+ const constfn ***p9 = (const constfn ***) bar; /* { dg-warning "cast" } */
+ const pintfn ***p10 = (const pintfn ***) bar; /* { dg-warning "cast" } */
+ constfn * const **p11 = (constfn * const **) bar; /* { dg-warning "cast" } */
+ pintfn * const **p12 = (pintfn * const **) bar; /* { dg-warning "cast" } */
+ constfn ** const *p13 = (constfn ** const *) bar;
+ pintfn ** const *p14 = (pintfn ** const *) bar;
+ const constfn * const **p15 = (const constfn * const **) bar; /* { dg-warning "cast" } */
+ const pintfn * const **p16 = (const pintfn * const **) bar; /* { dg-warning "cast" } */
+ const constfn ** const *p17 = (const constfn ** const *) bar; /* { dg-warning "cast" } */
+ const pintfn ** const *p18 = (const pintfn ** const *) bar; /* { dg-warning "cast" } */
+ constfn * const * const * p19 = (constfn * const * const *) bar;
+ pintfn * const * const * p20 = (pintfn * const * const *) bar;
+ const constfn * const * const *p21 = (const constfn * const * const *) bar;
+ const pintfn * const * const *p22 = (const pintfn * const * const *) bar;
+}
diff --git a/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c b/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c
index f563c2774bd..4f5315df2c2 100644
--- a/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c
+++ b/gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c
@@ -46,7 +46,7 @@ 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 -fno-common\" { target hppa*-*-hpux* powerpc*-*-darwin* } } */\n",
"/* { dg-options \"%s-I%s -mno-mmx -fno-common -Wno-abi\" { target i?86-*-darwin* x86_64-*-darwin* } } */\n",
"/* { dg-options \"%s-I%s -mno-base-addresses\" { target mmix-*-* } } */\n",
"/* { dg-options \"%s-I%s -mlongcalls -mtext-section-literals\" { target xtensa*-*-* } } */\n"
diff --git a/gcc/testsuite/gcc.dg/cpp/19940712-1.c b/gcc/testsuite/gcc.dg/cpp/19940712-1.c
index 98bcd767966..a79b2f5484d 100644
--- a/gcc/testsuite/gcc.dg/cpp/19940712-1.c
+++ b/gcc/testsuite/gcc.dg/cpp/19940712-1.c
@@ -5,8 +5,9 @@
/* { dg-error "unterminated comment" "" { target *-*-* } 4 } */
/* { dg-error "unterminated comment" "header error" { target *-*-* } 8 } */
-#include "19940712-1.h" /* { dg-message "" } // In file included from: */
-#include "19940712-1a.h" /* { dg-message "" } // In file included from: */
+#include "19940712-1.h"
+/* { dg-message "" "In file included from:" { target *-*-* } 0 } */
+#include "19940712-1a.h"
#include "19940712-1b.h"
/* comment start in comment error
diff --git a/gcc/testsuite/gcc.dg/cpp/Wmissingdirs.c b/gcc/testsuite/gcc.dg/cpp/Wmissingdirs.c
index 915aaa8de98..69b3aae3da6 100644
--- a/gcc/testsuite/gcc.dg/cpp/Wmissingdirs.c
+++ b/gcc/testsuite/gcc.dg/cpp/Wmissingdirs.c
@@ -1,5 +1,5 @@
/* { dg-do preprocess } */
-/* { dg-options "-std=gnu99 -I /jolly/well/better/not/exist -Wmissing-include-dirs -fno-show-column" } */
+/* { dg-options "-std=gnu99 -I /jolly/well/better/not/exist -Wmissing-include-dirs" } */
/* Test that -Wmissing-include-dirs issues a warning when a specified
directory does not exist. Source Ben Elliston, 2004-05-13. */
diff --git a/gcc/testsuite/gcc.dg/cpp/Wsignprom.c b/gcc/testsuite/gcc.dg/cpp/Wsignprom.c
index 7cdbccb3cac..87d422b794f 100644
--- a/gcc/testsuite/gcc.dg/cpp/Wsignprom.c
+++ b/gcc/testsuite/gcc.dg/cpp/Wsignprom.c
@@ -1,5 +1,5 @@
/* { dg-do preprocess } */
-/* { dg-options "-Wall -fshow-column" } */
+/* { dg-options "-Wall" } */
/* Test that -Wall emits the warnings about integer promotion changing
the sign of an operand. */
diff --git a/gcc/testsuite/gcc.dg/cpp/Wtrigraphs-2.c b/gcc/testsuite/gcc.dg/cpp/Wtrigraphs-2.c
index 43bf134842a..8d61f2841f0 100644
--- a/gcc/testsuite/gcc.dg/cpp/Wtrigraphs-2.c
+++ b/gcc/testsuite/gcc.dg/cpp/Wtrigraphs-2.c
@@ -1,5 +1,5 @@
/* { dg-do preprocess } */
-/* { dg-options "-std=c99 -Wtrigraphs -fno-show-column" } */
+/* { dg-options "-std=c99 -Wtrigraphs" } */
/* Test warnings for trigraphs in comments, with trigraphs enabled.
Neil Booth. 4 May 2003. */
diff --git a/gcc/testsuite/gcc.dg/cpp/Wtrigraphs.c b/gcc/testsuite/gcc.dg/cpp/Wtrigraphs.c
index 5ed6c98ad49..d4be2040c18 100644
--- a/gcc/testsuite/gcc.dg/cpp/Wtrigraphs.c
+++ b/gcc/testsuite/gcc.dg/cpp/Wtrigraphs.c
@@ -1,5 +1,5 @@
/* { dg-do preprocess } */
-/* { dg-options "-std=gnu99 -Wtrigraphs -fno-show-column" } */
+/* { dg-options "-std=gnu99 -Wtrigraphs" } */
/* Test we don't double warn for trigraphs immediately after preceding
text. Source Neil Booth. 22 Nov 2000. */
diff --git a/gcc/testsuite/gcc.dg/cpp/arith-1.c b/gcc/testsuite/gcc.dg/cpp/arith-1.c
index 85d5848d800..99e3cd7be2e 100644
--- a/gcc/testsuite/gcc.dg/cpp/arith-1.c
+++ b/gcc/testsuite/gcc.dg/cpp/arith-1.c
@@ -7,7 +7,7 @@
independent of target precision. */
/* { dg-do preprocess } */
-/* { dg-options -fno-show-column } */
+/* { dg-options "" } */
/* Test || operator and its short circuiting. */
#if 0 || 0
diff --git a/gcc/testsuite/gcc.dg/cpp/arith-3.c b/gcc/testsuite/gcc.dg/cpp/arith-3.c
index cc5fd1b3bf7..3015d31657a 100644
--- a/gcc/testsuite/gcc.dg/cpp/arith-3.c
+++ b/gcc/testsuite/gcc.dg/cpp/arith-3.c
@@ -9,7 +9,7 @@
Please keep changes to arith-2.c and arith-3.c in sync. */
/* { dg-do preprocess } */
-/* { dg-options "-std=c99 -fno-show-column" } */
+/* { dg-options "-std=c99" } */
#include <limits.h>
diff --git a/gcc/testsuite/gcc.dg/cpp/assert2.c b/gcc/testsuite/gcc.dg/cpp/assert2.c
index 130f7f5320a..5228bcbb3a9 100644
--- a/gcc/testsuite/gcc.dg/cpp/assert2.c
+++ b/gcc/testsuite/gcc.dg/cpp/assert2.c
@@ -1,6 +1,6 @@
/* Malformed assertion tests. */
/* { dg-do preprocess } */
-/* { dg-options "-fno-show-column -Wno-deprecated" } */
+/* { dg-options "-Wno-deprecated" } */
#assert /* { dg-error "without predicate" "assert w/o predicate" } */
#assert % /* { dg-error "an identifier" "assert punctuation" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/cpp.exp b/gcc/testsuite/gcc.dg/cpp/cpp.exp
index 1dc504e30ba..acf0898407b 100644
--- a/gcc/testsuite/gcc.dg/cpp/cpp.exp
+++ b/gcc/testsuite/gcc.dg/cpp/cpp.exp
@@ -37,7 +37,7 @@ dg-init
# Main loop.
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.{c,S} ]] \
- "-fno-show-column" $DEFAULT_CFLAGS
+ "" $DEFAULT_CFLAGS
# All done.
dg-finish
diff --git a/gcc/testsuite/gcc.dg/cpp/escape-2.c b/gcc/testsuite/gcc.dg/cpp/escape-2.c
index e79fa91cbe9..902fad3a2c2 100644
--- a/gcc/testsuite/gcc.dg/cpp/escape-2.c
+++ b/gcc/testsuite/gcc.dg/cpp/escape-2.c
@@ -1,7 +1,7 @@
/* Copyright (C) 2001 Free Software Foundation, Inc. */
/* { dg-do compile } */
-/* { dg-options "-pedantic -std=c99 -fno-show-column" } */
+/* { dg-options "-pedantic -std=c99" } */
/* This tests various diagnostics with -pedantic about escape
sequences, for both the preprocessor and the compiler.
diff --git a/gcc/testsuite/gcc.dg/cpp/escape.c b/gcc/testsuite/gcc.dg/cpp/escape.c
index c9dd44e43e5..e7d5e08dd49 100644
--- a/gcc/testsuite/gcc.dg/cpp/escape.c
+++ b/gcc/testsuite/gcc.dg/cpp/escape.c
@@ -1,7 +1,7 @@
/* Copyright (C) 2001 Free Software Foundation, Inc. */
/* { dg-do compile } */
-/* { dg-options "-Wtraditional -std=c89 -fno-show-column" } */
+/* { dg-options "-Wtraditional -std=c89" } */
/* This tests various diagnostics with -Wtraditioanl about escape
sequences, for both the preprocessor and the compiler.
diff --git a/gcc/testsuite/gcc.dg/cpp/extratokens.c b/gcc/testsuite/gcc.dg/cpp/extratokens.c
index d3e941bfff0..11d094af572 100644
--- a/gcc/testsuite/gcc.dg/cpp/extratokens.c
+++ b/gcc/testsuite/gcc.dg/cpp/extratokens.c
@@ -1,7 +1,7 @@
/* Copyright (C) 2000, 2008 Free Software Foundation, Inc. */
/* { dg-do preprocess } */
-/* { dg-options "-fno-show-column -Wno-deprecated" } */
+/* { dg-options "-Wno-deprecated" } */
/* Tests all directives that do not permit excess tokens at the end of
the line. */
diff --git a/gcc/testsuite/gcc.dg/cpp/extratokens2.c b/gcc/testsuite/gcc.dg/cpp/extratokens2.c
index fe682bfa59d..8e69a96c5b5 100644
--- a/gcc/testsuite/gcc.dg/cpp/extratokens2.c
+++ b/gcc/testsuite/gcc.dg/cpp/extratokens2.c
@@ -1,7 +1,7 @@
/* Copyright (C) 2002 Free Software Foundation, Inc. */
/* { dg-do preprocess } */
-/* { dg-options "-fno-show-column -Wno-endif-labels" } */
+/* { dg-options "-Wno-endif-labels" } */
/* Tests that -Wno-endif-labels correctly disables the checks done by
default (and tested in extratokens.c). */
diff --git a/gcc/testsuite/gcc.dg/cpp/if-mpar.c b/gcc/testsuite/gcc.dg/cpp/if-mpar.c
index 633cefcb442..45dd78b1e67 100644
--- a/gcc/testsuite/gcc.dg/cpp/if-mpar.c
+++ b/gcc/testsuite/gcc.dg/cpp/if-mpar.c
@@ -4,7 +4,6 @@
missing parenthesis message. */
/* { dg-do preprocess } */
-/* { dg-options "-fshow-column" } */
#if (1 /* { dg-error "5:missing '\\)'" "missing ')' no. 1" } */
#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/include2.c b/gcc/testsuite/gcc.dg/cpp/include2.c
index 67f1065ae8c..de34255ec35 100644
--- a/gcc/testsuite/gcc.dg/cpp/include2.c
+++ b/gcc/testsuite/gcc.dg/cpp/include2.c
@@ -11,5 +11,5 @@
/* These error is No such file or directory, just once. However, this
message is locale-dependent, so don't test for it. */
-/* { dg-error "silly" "" { target *-*-* } 10 } */
+/* { dg-error "silly" "" { target *-*-* } 0 } */
/* { dg-message "terminated" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/cpp/include2a.c b/gcc/testsuite/gcc.dg/cpp/include2a.c
index 974f3f33263..6a11c92cff2 100644
--- a/gcc/testsuite/gcc.dg/cpp/include2a.c
+++ b/gcc/testsuite/gcc.dg/cpp/include2a.c
@@ -11,6 +11,6 @@
/* These error is No such file or directory, just once. However, this
message is locale-dependent, so don't test for it. */
-/* { dg-error "silly" "" { target *-*-* } 10 } */
-/* { dg-error "missing" "" { target *-*-* } 10 } */
+/* { dg-error "silly" "" { target *-*-* } 0 } */
+/* { dg-error "missing" "" { target *-*-* } 0 } */
/* { dg-message "terminated" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/cpp/macspace1.c b/gcc/testsuite/gcc.dg/cpp/macspace1.c
index daf14d2b1f1..d8578448b64 100644
--- a/gcc/testsuite/gcc.dg/cpp/macspace1.c
+++ b/gcc/testsuite/gcc.dg/cpp/macspace1.c
@@ -1,6 +1,6 @@
/* PR preprocessor/19475 */
/* { dg-do preprocess } */
-/* { dg-options "-std=iso9899:1990 -pedantic-errors -fno-show-column" } */
+/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
#define a! /* { dg-warning "missing whitespace" } */
#define b" /* { dg-warning "missing whitespace" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/macspace2.c b/gcc/testsuite/gcc.dg/cpp/macspace2.c
index 7a81eceeac8..1494fed18c3 100644
--- a/gcc/testsuite/gcc.dg/cpp/macspace2.c
+++ b/gcc/testsuite/gcc.dg/cpp/macspace2.c
@@ -1,6 +1,6 @@
/* PR preprocessor/19475 */
/* { dg-do preprocess } */
-/* { dg-options "-std=iso9899:1999 -pedantic-errors -fno-show-column" } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
#define a! /* { dg-error "requires whitespace" } */
#define b" /* { dg-error "requires whitespace" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/missing-header-1.c b/gcc/testsuite/gcc.dg/cpp/missing-header-1.c
index 5445d4c4fec..dbcc2b36167 100644
--- a/gcc/testsuite/gcc.dg/cpp/missing-header-1.c
+++ b/gcc/testsuite/gcc.dg/cpp/missing-header-1.c
@@ -2,7 +2,8 @@
/* { dg-do compile } */
/* { dg-options "" } */
-#include "nonexistent.h" /* { dg-error "nonexistent.h" } */
+#include "nonexistent.h"
+/* { dg-message "nonexistent.h" "" { target *-*-* } 0 } */
/* { dg-message "terminated" "" { target *-*-* } 0 } */
/* This declaration should not receive any diagnostic. */
diff --git a/gcc/testsuite/gcc.dg/cpp/poison.c b/gcc/testsuite/gcc.dg/cpp/poison.c
index d667183de31..f85405c0983 100644
--- a/gcc/testsuite/gcc.dg/cpp/poison.c
+++ b/gcc/testsuite/gcc.dg/cpp/poison.c
@@ -1,5 +1,4 @@
-/* { dg-do preprocess }
- { dg-options "-fno-show-column" } */
+/* { dg-do preprocess } */
#pragma GCC poison foo
foo /* { dg-error "foo" "use of foo" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/pr29612-2.c b/gcc/testsuite/gcc.dg/cpp/pr29612-2.c
index 813eb77af13..fff10a843b4 100644
--- a/gcc/testsuite/gcc.dg/cpp/pr29612-2.c
+++ b/gcc/testsuite/gcc.dg/cpp/pr29612-2.c
@@ -1,6 +1,6 @@
/* PR preprocessor/29612 */
/* { dg-do preprocess } */
-/* { dg-options "-Wtraditional -fno-show-column" } */
+/* { dg-options "-Wtraditional" } */
# 6 "pr29612-2.c"
diff --git a/gcc/testsuite/gcc.dg/cpp/redef2.c b/gcc/testsuite/gcc.dg/cpp/redef2.c
index 57fa3b1930b..1dbc10033ed 100644
--- a/gcc/testsuite/gcc.dg/cpp/redef2.c
+++ b/gcc/testsuite/gcc.dg/cpp/redef2.c
@@ -1,7 +1,7 @@
/* Test for redefining macros with significant differences. */
/* { dg-do preprocess }
- { dg-options "-ansi -Wall -fno-show-column" } */
+ { dg-options "-ansi -Wall" } */
#define mac(a, b) (a) + (b)
#define mac(a, b) (a) * (b)
diff --git a/gcc/testsuite/gcc.dg/cpp/strify2.c b/gcc/testsuite/gcc.dg/cpp/strify2.c
index 2c768dcd05e..c24220c70e0 100644
--- a/gcc/testsuite/gcc.dg/cpp/strify2.c
+++ b/gcc/testsuite/gcc.dg/cpp/strify2.c
@@ -1,7 +1,7 @@
/* Copyright (C) 2000 Free Software Foundation, Inc. */
/* { dg-do run } */
-/* { dg-options "-std=c99 -pedantic-errors -fno-show-column" } */
+/* { dg-options "-std=c99 -pedantic-errors" } */
/* Tests a whole bunch of things are correctly stringified. */
diff --git a/gcc/testsuite/gcc.dg/cpp/syshdr.c b/gcc/testsuite/gcc.dg/cpp/syshdr.c
index 75137739327..310d5d0d288 100644
--- a/gcc/testsuite/gcc.dg/cpp/syshdr.c
+++ b/gcc/testsuite/gcc.dg/cpp/syshdr.c
@@ -8,5 +8,6 @@
/* { dg-do preprocess } */
/* { dg-error "include_next" "good error" { target *-*-* } 4 } */
-#include "syshdr1.h" /* { dg-message "" "In file included from:" } */
+#include "syshdr1.h"
+/* { dg-message "" "In file included from:" { target *-*-* } 0 } */
#include "syshdr2.h"
diff --git a/gcc/testsuite/gcc.dg/cpp/sysmac2.c b/gcc/testsuite/gcc.dg/cpp/sysmac2.c
index 0d1efabdc07..6d493a9ed1b 100644
--- a/gcc/testsuite/gcc.dg/cpp/sysmac2.c
+++ b/gcc/testsuite/gcc.dg/cpp/sysmac2.c
@@ -1,7 +1,7 @@
/* Copyright (C) 2001 Free Software Foundation, Inc. */
/* { dg-do compile } */
-/* { dg-options "-std=gnu99 -pedantic -Wtraditional -fno-show-column" } */
+/* { dg-options "-std=gnu99 -pedantic -Wtraditional" } */
/* Tests diagnostics are suppressed for some macros defined in system
headers. */
diff --git a/gcc/testsuite/gcc.dg/cpp/tr-warn1.c b/gcc/testsuite/gcc.dg/cpp/tr-warn1.c
index 259f9288253..37b5efe5df1 100644
--- a/gcc/testsuite/gcc.dg/cpp/tr-warn1.c
+++ b/gcc/testsuite/gcc.dg/cpp/tr-warn1.c
@@ -1,6 +1,6 @@
/* Test for warnings about nontraditional directives. */
/* { dg-do preprocess } */
-/* { dg-options "-pedantic -Wtraditional -fno-show-column" } */
+/* { dg-options "-pedantic -Wtraditional" } */
/* Block 1: K+R directives should have the # indented. */
diff --git a/gcc/testsuite/gcc.dg/cpp/tr-warn3.c b/gcc/testsuite/gcc.dg/cpp/tr-warn3.c
index e802b4dd0f7..33517188cd8 100644
--- a/gcc/testsuite/gcc.dg/cpp/tr-warn3.c
+++ b/gcc/testsuite/gcc.dg/cpp/tr-warn3.c
@@ -3,7 +3,7 @@
warnings inside unused clauses because they are often hidden this
way on purpose. However they do still require indentation for K&R. */
/* { dg-do preprocess } */
-/* { dg-options "-pedantic -Wtraditional -fno-show-column" } */
+/* { dg-options "-pedantic -Wtraditional" } */
#if 1
diff --git a/gcc/testsuite/gcc.dg/cpp/tr-warn4.c b/gcc/testsuite/gcc.dg/cpp/tr-warn4.c
index 14dd8a3163e..f5b5779bfd7 100644
--- a/gcc/testsuite/gcc.dg/cpp/tr-warn4.c
+++ b/gcc/testsuite/gcc.dg/cpp/tr-warn4.c
@@ -2,7 +2,7 @@
Note, gcc should omit these warnings in system header files.
By Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 8/22/2000. */
/* { dg-do preprocess } */
-/* { dg-options "-Wtraditional -fno-show-column" } */
+/* { dg-options "-Wtraditional" } */
#if 1U /* { dg-warning "traditional C rejects" "numeric constant suffix" } */
#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/tr-warn5.c b/gcc/testsuite/gcc.dg/cpp/tr-warn5.c
index 16dcf4c0866..6867b88c219 100644
--- a/gcc/testsuite/gcc.dg/cpp/tr-warn5.c
+++ b/gcc/testsuite/gcc.dg/cpp/tr-warn5.c
@@ -2,7 +2,7 @@
Note, gcc should omit these warnings in system header files.
By Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 8/22/2000. */
/* { dg-do preprocess } */
-/* { dg-options "-Wtraditional -fno-show-column" } */
+/* { dg-options "-Wtraditional" } */
#if +1 /* { dg-warning "unary plus operator" "unary plus operator" } */
#endif
diff --git a/gcc/testsuite/gcc.dg/cpp/tr-warn6.c b/gcc/testsuite/gcc.dg/cpp/tr-warn6.c
index e9aa851d041..d95409ef8f9 100644
--- a/gcc/testsuite/gcc.dg/cpp/tr-warn6.c
+++ b/gcc/testsuite/gcc.dg/cpp/tr-warn6.c
@@ -2,7 +2,7 @@
Note, gcc should omit these warnings in system header files.
By Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 9/8/2000. */
/* { dg-do preprocess } */
-/* { dg-options "-Wtraditional -fno-show-column" } */
+/* { dg-options "-Wtraditional" } */
#define foo1(h) sdf "h3" fds "h" /* { dg-warning "macro argument \"h\" would be stringified" "traditional stringification" } */
#define foo2(h2) sdf "h2" fds "h3" /* { dg-warning "macro argument \"h2\" would be stringified" "traditional stringification" } */
diff --git a/gcc/testsuite/gcc.dg/cpp/trad/trad.exp b/gcc/testsuite/gcc.dg/cpp/trad/trad.exp
index 22225e51915..190cfcfdee6 100644
--- a/gcc/testsuite/gcc.dg/cpp/trad/trad.exp
+++ b/gcc/testsuite/gcc.dg/cpp/trad/trad.exp
@@ -37,7 +37,7 @@ dg-init
# Main loop.
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \
- "-fno-show-column" $DEFAULT_TRADCPPFLAGS
+ "" $DEFAULT_TRADCPPFLAGS
# All done.
dg-finish
diff --git a/gcc/testsuite/gcc.dg/cpp/unc4.c b/gcc/testsuite/gcc.dg/cpp/unc4.c
index 758e5bbc6d9..10c49e9d4db 100644
--- a/gcc/testsuite/gcc.dg/cpp/unc4.c
+++ b/gcc/testsuite/gcc.dg/cpp/unc4.c
@@ -1,5 +1,4 @@
/* { dg-do preprocess } */
-/* { dg-options "-fno-show-column" } */
/* Tests for un-terminated conditional diagnostics.
Copyright (c) 1999 Free Software Foundation.
diff --git a/gcc/testsuite/gcc.dg/cpp/undef2.c b/gcc/testsuite/gcc.dg/cpp/undef2.c
index 4e6a690dcc9..5614e039b22 100644
--- a/gcc/testsuite/gcc.dg/cpp/undef2.c
+++ b/gcc/testsuite/gcc.dg/cpp/undef2.c
@@ -1,9 +1,7 @@
/* C99 6.10.8 para 4: None of [the predefined macro names] shall be
- the subject of a #define or an #undef preprocessing directive. We
- pass -fno-show-column as otherwise dejagnu gets confused. */
+ the subject of a #define or an #undef preprocessing directive. */
/* { dg-do preprocess } */
-/* { dg-options "-fno-show-column" } */
#undef __DATE__ /* { dg-warning "undefining" "__DATE__" } */
#undef __TIME__ /* { dg-warning "undefining" "__TIME__" } */
diff --git a/gcc/testsuite/gcc.dg/memcpy-1.c b/gcc/testsuite/gcc.dg/memcpy-1.c
index cc602423793..2b11098b286 100644
--- a/gcc/testsuite/gcc.dg/memcpy-1.c
+++ b/gcc/testsuite/gcc.dg/memcpy-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized --param sra-max-structure-size=32" } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
/* PR36598 AVR fail maybe due to cost metrics */
/* { dg-final { scan-tree-dump-times "nasty_local" 0 "optimized" { xfail { "avr-*-*" } } } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/pch/counter-2.c b/gcc/testsuite/gcc.dg/pch/counter-2.c
index 6dd2245d7d8..14ce24909c8 100644
--- a/gcc/testsuite/gcc.dg/pch/counter-2.c
+++ b/gcc/testsuite/gcc.dg/pch/counter-2.c
@@ -8,7 +8,7 @@
#endif
#include "counter-2.h" /* { dg-warning "not used because `__COUNTER__' is invalid" } */
-/* { dg-error "counter-2.h: No such file or directory" "no such file" { target *-*-* } 10 } */
+/* { dg-error "counter-2.h: No such file or directory" "no such file" { target *-*-* } 0 } */
/* { dg-error "one or more PCH files were found, but they were invalid" "invalid files" { target *-*-* } 10 } */
/* { dg-message "terminated" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/pch/valid-1.c b/gcc/testsuite/gcc.dg/pch/valid-1.c
index 3ee90916591..b7f22d0dc17 100644
--- a/gcc/testsuite/gcc.dg/pch/valid-1.c
+++ b/gcc/testsuite/gcc.dg/pch/valid-1.c
@@ -1,8 +1,8 @@
/* { dg-options "-I. -Winvalid-pch -g" } */
#include "valid-1.h"/* { dg-warning "created with -gnone, but used with -g" } */
-/* { dg-error "No such file" "no such file" { target *-*-* } 3 } */
-/* { dg-error "they were invalid" "invalid files" { target *-*-* } 3 } */
+/* { dg-error "No such file" "no such file" { target *-*-* } 0 } */
+/* { dg-error "they were invalid" "invalid files" { target *-*-* } 0 } */
/* { dg-message "terminated" "" { target *-*-* } 0 } */
int x;
diff --git a/gcc/testsuite/gcc.dg/pch/valid-2.c b/gcc/testsuite/gcc.dg/pch/valid-2.c
index 34269a87960..3d8cb1427f3 100644
--- a/gcc/testsuite/gcc.dg/pch/valid-2.c
+++ b/gcc/testsuite/gcc.dg/pch/valid-2.c
@@ -1,7 +1,7 @@
/* { dg-options "-I. -Winvalid-pch -fexceptions" } */
#include "valid-2.h" /* { dg-warning "settings for -fexceptions do not match" } */
-/* { dg-error "No such file" "no such file" { target *-*-* } 3 } */
-/* { dg-error "they were invalid" "invalid files" { target *-*-* } 3 } */
+/* { dg-error "No such file" "no such file" { target *-*-* } 0 } */
+/* { dg-error "they were invalid" "invalid files" { target *-*-* } 0 } */
/* { dg-message "terminated" "" { target *-*-* } 0 } */
int x;
diff --git a/gcc/testsuite/gcc.dg/pch/warn-1.c b/gcc/testsuite/gcc.dg/pch/warn-1.c
index 64944c776d8..1d31cef0544 100644
--- a/gcc/testsuite/gcc.dg/pch/warn-1.c
+++ b/gcc/testsuite/gcc.dg/pch/warn-1.c
@@ -3,8 +3,8 @@
#define DEFINED_VALUE 3
#include "warn-1.h"/* { dg-warning "not used because .DEFINED_VALUE. is defined" } */
-/* { dg-error "No such file" "no such file" { target *-*-* } 5 } */
-/* { dg-error "they were invalid" "invalid files" { target *-*-* } 5 } */
+/* { dg-error "No such file" "no such file" { target *-*-* } 0 } */
+/* { dg-error "they were invalid" "invalid files" { target *-*-* } 0 } */
/* { dg-message "terminated" "" { target *-*-* } 0 } */
diff --git a/gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c b/gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c
new file mode 100644
index 00000000000..74e68bb82ec
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c
@@ -0,0 +1,12 @@
+/* Test the ggcplug plugin. */
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+
+int main()
+{
+ int i=0, j=0;
+ for (i= 0; i<1000; i++)
+ if (i%8 == 0)
+ j++;
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/ggcplug.c b/gcc/testsuite/gcc.dg/plugin/ggcplug.c
new file mode 100644
index 00000000000..f90e77bcf72
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/ggcplug.c
@@ -0,0 +1,112 @@
+/* This plugin tests the GGC related plugin events. */
+/* { dg-options "-O" } */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "toplev.h"
+#include "basic-block.h"
+#include "gimple.h"
+#include "tree.h"
+#include "tree-pass.h"
+#include "intl.h"
+#include "gcc-plugin.h"
+
+
+
+/* our callback is the same for all PLUGIN_GGC_START,
+ PLUGIN_GGC_MARKING, PLUGIN_GGC_END events; it just increments the
+ user_data which is an int */
+static void increment_callback (void *gcc_data, void *user_data);
+
+/* our counters are user_data */
+static int our_ggc_start_counter;
+static int our_ggc_end_counter;
+static int our_ggc_marking_counter;
+
+/* our empty GGC extra root table */
+static const struct ggc_root_tab our_xtratab[] = {
+ LAST_GGC_ROOT_TAB
+};
+
+
+/* The initialization routine exposed to and called by GCC. The spec of this
+ function is defined in gcc/gcc-plugin.h.
+
+ Note that this function needs to be named exactly "plugin_init". */
+int
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
+{
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ int i = 0;
+ struct plugin_argument *argv = plugin_info->argv;
+ if (!plugin_default_version_check (version, version))
+ return 1;
+ /* Process the plugin arguments. This plugin takes the following arguments:
+ count-ggc-start count-ggc-end count-ggc-mark */
+ for (i = 0; i < argc; ++i)
+ {
+ if (!strcmp (argv[i].key, "count-ggc-start"))
+ {
+ if (argv[i].value)
+ warning (0, G_ ("option '-fplugin-arg-%s-count-ggc-start=%s'"
+ " ignored (superfluous '=%s')"),
+ plugin_name, argv[i].value, argv[i].value);
+ else
+ register_callback ("ggcplug",
+ PLUGIN_GGC_START,
+ increment_callback,
+ (void *) &our_ggc_start_counter);
+ }
+ else if (!strcmp (argv[i].key, "count-ggc-end"))
+ {
+ if (argv[i].value)
+ warning (0, G_ ("option '-fplugin-arg-%s-count-ggc-end=%s'"
+ " ignored (superfluous '=%s')"),
+ plugin_name, argv[i].value, argv[i].value);
+ else
+ register_callback ("ggcplug",
+ PLUGIN_GGC_END,
+ increment_callback,
+ (void *) &our_ggc_end_counter);
+ }
+ else if (!strcmp (argv[i].key, "count-ggc-mark"))
+ {
+ if (argv[i].value)
+ warning (0, G_ ("option '-fplugin-arg-%s-count-ggc-mark=%s'"
+ " ignored (superfluous '=%s')"),
+ plugin_name, argv[i].value, argv[i].value);
+ else
+ register_callback ("ggcplug",
+ PLUGIN_GGC_MARKING,
+ increment_callback,
+ (void *) &our_ggc_marking_counter);
+ }
+ else if (!strcmp (argv[i].key, "test-extra-root"))
+ {
+ if (argv[i].value)
+ warning (0, G_ ("option '-fplugin-arg-%s-test-extra-root=%s'"
+ " ignored (superfluous '=%s')"),
+ plugin_name, argv[i].value, argv[i].value);
+ else
+ register_callback ("ggcplug",
+ PLUGIN_REGISTER_GGC_ROOTS,
+ NULL,
+ (void *) our_xtratab);
+ }
+ }
+ /* plugin initialization succeeded */
+ return 0;
+ }
+
+static void
+increment_callback (void *gcc_data, void *user_data)
+{
+ int *usercountptr = (int *) user_data;
+ gcc_assert (!gcc_data);
+ gcc_assert (user_data);
+ (*usercountptr)++;
+}
diff --git a/gcc/testsuite/gcc.dg/plugin/plugin.exp b/gcc/testsuite/gcc.dg/plugin/plugin.exp
index 93c0c5cb848..63ee74427f6 100644
--- a/gcc/testsuite/gcc.dg/plugin/plugin.exp
+++ b/gcc/testsuite/gcc.dg/plugin/plugin.exp
@@ -47,7 +47,9 @@ load_lib plugin-support.exp
# Specify the plugin source file and the associated test files in a list.
# plugin_test_list={ {plugin1 test1 test2 ...} {plugin2 test1 ...} ... }
set plugin_test_list [list \
- { selfassign.c self-assign-test-1.c self-assign-test-2.c } ]
+ { selfassign.c self-assign-test-1.c self-assign-test-2.c } \
+ { ggcplug.c ggcplug-test-1.c } \
+]
foreach plugin_test $plugin_test_list {
# Replace each source file with its full-path name
diff --git a/gcc/testsuite/gcc.dg/plugin/selfassign.c b/gcc/testsuite/gcc.dg/plugin/selfassign.c
index 9e7e84c2db0..2bc1d861358 100644
--- a/gcc/testsuite/gcc.dg/plugin/selfassign.c
+++ b/gcc/testsuite/gcc.dg/plugin/selfassign.c
@@ -2,6 +2,7 @@
self-assignment statements. */
/* { dg-options "-O" } */
+#include "gcc-plugin.h"
#include "config.h"
#include "system.h"
#include "coretypes.h"
@@ -12,7 +13,6 @@
#include "tree.h"
#include "tree-pass.h"
#include "intl.h"
-#include "gcc-plugin.h"
/* Indicate whether to check overloaded operator '=', which is performed by
diff --git a/gcc/testsuite/gcc.dg/pr33667.c b/gcc/testsuite/gcc.dg/pr33667.c
index d3c039b51df..676c4a46dac 100644
--- a/gcc/testsuite/gcc.dg/pr33667.c
+++ b/gcc/testsuite/gcc.dg/pr33667.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O2" } */
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned long long int uint64_t;
diff --git a/gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c b/gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c
index ba91d69650d..59cebc52e96 100644
--- a/gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c
+++ b/gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c
@@ -3,7 +3,7 @@
/* { dg-options "-O2 -fprefetch-loop-arrays -w" } */
/* { dg-options "-O2 -fprefetch-loop-arrays -march=i686 -msse -w" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } */
-typedef unsigned long size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
struct re_pattern_buffer
{
diff --git a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_pointer.c b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_pointer.c
index 8e54632454e..4cb94afc5df 100644
--- a/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_pointer.c
+++ b/gcc/testsuite/gcc.dg/struct/wo_prof_escape_substr_pointer.c
@@ -24,6 +24,8 @@ typedef struct
int c;
}str_with_substr_t;
+int foo;
+
int
main (void)
{
@@ -37,6 +39,8 @@ main (void)
for (i=0; i < N; i++)
A[i].sub_str->a = 5;
+ foo = A[56].sub_str->a;
+
return 0;
}
diff --git a/gcc/testsuite/gcc.dg/torture/pr39204.c b/gcc/testsuite/gcc.dg/torture/pr39204.c
index 4604b7079d1..1389a52ec58 100644
--- a/gcc/testsuite/gcc.dg/torture/pr39204.c
+++ b/gcc/testsuite/gcc.dg/torture/pr39204.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-w" } */
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
typedef unsigned char __u_char;
typedef unsigned short int __u_short;
typedef unsigned int __u_int;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c
index d5cabb0bd37..d72d133e154 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c
@@ -2,7 +2,7 @@
/* { dg-options "-O1 -fdump-tree-dom2" } */
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
extern void *xmalloc (size_t) __attribute__ ((__malloc__));
struct edge_def
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-3.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-3.c
index 5132aa3d69e..f7ebb33d2a5 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/inline-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-3.c
@@ -27,3 +27,4 @@ inline_me_too (void)
}
/* { dg-final { scan-tree-dump-times "Inlining inline_me " 1 "einline2"} } */
/* { dg-final { scan-tree-dump-times "Inlining inline_me_too " 1 "einline2"} } */
+/* { dg-final { cleanup-tree-dump "einline2" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c b/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c
index a135bcff238..8fa2ed2ca1f 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c
@@ -2,7 +2,7 @@
/* { dg-options "-O2 -ftree-loop-distribution" } */
#define NULL ((void *)0)
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
extern void *foo(size_t nelem, size_t elsize);
extern void bar (char*, ...);
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c b/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c
index 79039066808..fac6cd3b806 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O2 -ftree-loop-distribution" } */
-typedef long unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
typedef struct {
long dat[2];
} gsl_complex_long_double;
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-1.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-1.c
index c2e45eb1f84..e5af2475115 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/sra-1.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-1.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized --param sra-max-structure-size=32" } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
/* Tests for SRA. */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-2.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-2.c
index 177c4bcace4..5682b8afbcf 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/sra-2.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-2.c
@@ -1,5 +1,5 @@
-/* { dg-do compile } */
-/* { dg-options "-O1 -fno-tree-fre -fdump-tree-optimized --param sra-max-structure-size=32" } */
+/* { dg-do compile } */
+/* { dg-options "-O1 -fno-tree-fre -fdump-tree-optimized" } */
/* Test for SRA. */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-3.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-3.c
index 661dc58ff09..d8908152384 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/sra-3.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-3.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized --param sra-max-structure-size=32" } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
/* Test for SRA. */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-4.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-4.c
index 6fdf37ffb34..73a68f90043 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/sra-4.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-4.c
@@ -1,6 +1,6 @@
/* { dg-do compile } */
/* { dg-options "-O1 -fdump-tree-optimized -w" } */
-/* Check that SRA does non block copies for structs that just contain vectors. */
+/* Check that SRA replaces strucutres containing vectors. */
#define vector __attribute__((vector_size(16)))
@@ -20,7 +20,5 @@ vector int f(vector int t1, vector int t2)
return st3.t;
}
-/* There should be no references to st as SRA should not have done block copy. */
/* { dg-final { scan-tree-dump-times "st" 0 "optimized" } } */
/* { dg-final { cleanup-tree-dump "optimized" } } */
-
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-5.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-5.c
new file mode 100644
index 00000000000..869d2f55f95
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-5.c
@@ -0,0 +1,74 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized" } */
+
+/* Tests for SRA of unions. */
+
+
+typedef union testunion
+{
+ double d;
+ char f1;
+} testunion;
+
+void
+copyunion1 (testunion param)
+{
+ testunion local;
+ param.f1 = 0;
+ local = param;
+ if (local.f1 != 0)
+ link_error ();
+}
+
+void
+copyunion11 (testunion *param)
+{
+ testunion local;
+ param->f1 = 0;
+ local = *param;
+ if (local.f1 != 0)
+ link_error ();
+}
+
+void
+copyunion111 (testunion param)
+{
+ testunion *local = &param;
+ param.f1 = 0;
+ if (local->f1 != 0)
+ link_error ();
+}
+
+testunion globuf;
+void
+copyunion1111 (void)
+{
+ testunion local;
+ globuf.f1 = 0;
+ local = globuf;
+ if (local.f1 != 0)
+ link_error ();
+}
+
+void
+copyunion11111 (void)
+{
+ testunion *local = &globuf;
+ globuf.f1 = 0;
+ if (local->f1 != 0)
+ link_error ();
+}
+
+void
+copyunion111111 (testunion param)
+{
+ static testunion local;
+ param.f1 = 0;
+ local = param;
+ if (local.f1 != 0)
+ link_error ();
+}
+
+/* There should be no reference to link_error. */
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-6.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-6.c
new file mode 100644
index 00000000000..e59b536c12d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-6.c
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-O1 -fdump-tree-optimized -fdump-tree-esra-details" } */
+
+typedef struct teststruct
+{
+ double d;
+ int i1;
+ char c1;
+ float z;
+ char c2;
+ int i2;
+} teststruct;
+
+
+void cow (int i)
+{
+ teststruct a, b, c, d;
+
+ a.d = 3.2;
+ a.i1 = i;
+
+ b = a;
+ c = b;
+ d = c;
+
+ if (d.i1 != i)
+ link_error ();
+}
+
+
+/* Suaccesses of b and c should have been created. */
+/* { dg-final { scan-tree-dump "expr = b.d" "esra"} } */
+/* { dg-final { scan-tree-dump "expr = b.i1" "esra"} } */
+/* { dg-final { scan-tree-dump "expr = c.d" "esra"} } */
+/* { dg-final { scan-tree-dump "expr = c.i1" "esra"} } */
+/* { dg-final { cleanup-tree-dump "esra" } } */
+
+/* There should be no reference to link_error. */
+/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c
index dd0da7913dc..bce2c315a66 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c
@@ -1,7 +1,7 @@
/* { dg-do compile } */
/* { dg-options "-O -w -fdump-tree-dse-vops" } */
-typedef unsigned int size_t;
+__extension__ typedef __SIZE_TYPE__ size_t;
typedef struct _IO_FILE FILE;
typedef struct
{
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-26.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-26.c
new file mode 100644
index 00000000000..144d146b935
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-26.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details" } */
+
+union U {
+ float f;
+ int i;
+};
+
+int foo (union U *p)
+{
+ union U u;
+ p->f = 0.0;
+ u = *p;
+ return u.i;
+}
+
+/* { dg-final { scan-tree-dump "Replaced u.i with 0 in" "fre" } } */
+/* { dg-final { cleanup-tree-dump "fre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c
index bd81831eba8..895c05fdf91 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-fre-details -fdump-tree-optimized" } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details -fdump-tree-optimized" } */
#if (__SIZEOF_INT__ == __SIZEOF_FLOAT__)
typedef int intflt;
#elif (__SIZEOF_LONG__ == __SIZEOF_FLOAT__)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c
index 6e17bd531b3..bc9f8e3992e 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-fre-details" } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details" } */
#if (__SIZEOF_INT__ == __SIZEOF_FLOAT__)
typedef int intflt;
#elif (__SIZEOF_LONG__ == __SIZEOF_FLOAT__)
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-9.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-9.c
index 18595ed6fe5..c8a434a2bba 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-9.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-9.c
@@ -1,5 +1,5 @@
/* { dg-do compile } */
-/* { dg-options "-O -fdump-tree-fre-stats" } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-stats" } */
union loc {
unsigned reg;
diff --git a/gcc/testsuite/gcc.dg/va-arg-2.c b/gcc/testsuite/gcc.dg/va-arg-2.c
index 2fd0ed97e3f..e1c915ffc92 100644
--- a/gcc/testsuite/gcc.dg/va-arg-2.c
+++ b/gcc/testsuite/gcc.dg/va-arg-2.c
@@ -5,7 +5,7 @@
#include <varargs.h> /* { dg-bogus "varargs.h" "missing file" } */
-/* { dg-message "" "In file included from" { target *-*-* } 6 } */
+/* { dg-message "file included from" "file included from" { target *-*-* } 0 } */
/* { dg-error "no longer implements" "#error 1" { target *-*-* } 4 } */
/* { dg-error "Revise your code" "#error 2" { target *-*-* } 5 } */
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-10.c b/gcc/testsuite/gcc.dg/vect/bb-slp-10.c
index abac3c31a40..1a678ca3677 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-10.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-10.c
@@ -14,7 +14,7 @@ main1 (unsigned int x, unsigned int y)
{
int i;
unsigned int *pin = &in[0];
- unsigned int *pout = &out[2];
+ unsigned int *pout = &out[1];
unsigned int a0, a1, a2, a3;
/* Misaligned store. */
@@ -29,10 +29,10 @@ main1 (unsigned int x, unsigned int y)
*pout++ = a3 * y;
/* Check results. */
- if (out[2] != (in[0] + 23) * x
- || out[3] != (in[1] + 142) * y
- || out[4] != (in[2] + 2) * x
- || out[5] != (in[3] + 31) * y)
+ if (out[1] != (in[0] + 23) * x
+ || out[2] != (in[1] + 142) * y
+ || out[3] != (in[2] + 2) * x
+ || out[4] != (in[3] + 31) * y)
abort();
return 0;
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-4.c b/gcc/testsuite/gcc.dg/vect/bb-slp-4.c
index 3e74fff29b5..4ed8d7c6b39 100644
--- a/gcc/testsuite/gcc.dg/vect/bb-slp-4.c
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-4.c
@@ -18,14 +18,10 @@ main1 ()
*pout++ = *pin++;
*pout++ = *pin++;
- *pout++ = *pin++;
- *pout++ = *pin++;
/* Check results. */
if (out[0] != in[0]
- || out[1] != in[1]
- || out[2] != in[2]
- || out[3] != in[3])
+ || out[1] != in[1])
abort();
return 0;
diff --git a/gcc/testsuite/gcc.dg/vect/pr40254.c b/gcc/testsuite/gcc.dg/vect/pr40254.c
new file mode 100644
index 00000000000..b890a449312
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr40254.c
@@ -0,0 +1,39 @@
+#include <stdlib.h>
+#include <stdarg.h>
+#include "tree-vect.h"
+
+struct s
+{
+ int *x;
+ int x1;
+ int x2;
+ int x3;
+ int *y;
+};
+
+struct s arr[64] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+
+__attribute__ ((noinline)) void
+foo (int i, int *in_x, int *in_y)
+{
+ arr[i].x = in_x;
+ arr[i].y = in_y;
+}
+
+int
+main (void)
+{
+ int a, b;
+
+ check_vect ();
+
+ foo (5, &a, &b);
+
+ if (arr[5].x != &a || arr[5].y != &b)
+ abort ();
+
+ return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
diff --git a/gcc/testsuite/gcc.target/i386/pr37216.c b/gcc/testsuite/gcc.target/i386/pr37216.c
new file mode 100644
index 00000000000..5c847a70cfb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr37216.c
@@ -0,0 +1,17 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -msse2" } */
+/* { dg-options "-O3 -msse2 -mpe-aligned-commons" { target pe_aligned_commons } } */
+
+#include "sse2-check.h"
+
+int iarr[64];
+int iint = 0;
+
+void
+sse2_test (void)
+{
+ int i;
+
+ for (i = 0; i < 64; i++)
+ iarr[i] = -2;
+}
diff --git a/gcc/testsuite/gcc.target/mips/const-anchor-1.c b/gcc/testsuite/gcc.target/mips/const-anchor-1.c
new file mode 100644
index 00000000000..66981671d02
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/const-anchor-1.c
@@ -0,0 +1,10 @@
+/* Derive a constant (0x1233ffff) from an intermediate value
+ (0x1234000) used to build another constant. */
+/* { dg-options "-O" } */
+/* { dg-final { scan-assembler-not "0x12330000|305332224" } } */
+/* { dg-final { scan-assembler "addiu\t\\\$5,\\\$\[0-9\]*,-1" } } */
+
+NOMIPS16 void f ()
+{
+ g (0x12340001, 0x1233ffff);
+}
diff --git a/gcc/testsuite/gcc.target/mips/const-anchor-2.c b/gcc/testsuite/gcc.target/mips/const-anchor-2.c
new file mode 100644
index 00000000000..ccb89bb766c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/const-anchor-2.c
@@ -0,0 +1,9 @@
+/* Derive a constant (0x30001) from another constant. */
+/* { dg-options "-O" } */
+/* { dg-final { scan-assembler-not "0x300000|196608" } } */
+/* { dg-final { scan-assembler "addiu\t\\\$5,\\\$\[0-9\]*,32763" } } */
+
+NOMIPS16 void f ()
+{
+ g (0x28006, 0x30001);
+}
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-30.c b/gcc/testsuite/gcc.target/powerpc/altivec-30.c
new file mode 100644
index 00000000000..99783191db9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-30.c
@@ -0,0 +1,32 @@
+/* { dg-do compile { target powerpc*-*-* } } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec" } */
+
+#include <stdbool.h>
+#include <altivec.h>
+
+#define f0(type) void x0##type (vector bool type x) { }
+f0 (int)
+
+#define f1(v, type) void x1##type (v bool type x) { }
+f1 (vector, int)
+
+#define f2(b, type) void x2##type (vector b type x) { }
+f2 (bool, int)
+
+#define f3(v, b, type) void x3##type (v b type x) { }
+f3 (vector, bool, int)
+
+#define f4(v, b, type) void x4##type (v type b x) { }
+f4 (vector, bool, int)
+
+#define B bool
+#define I int
+#define BI bool int
+#define VBI vector bool int
+
+vector bool int a;
+vector B int b;
+vector B I c;
+vector BI d;
+VBI e;
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-31.c b/gcc/testsuite/gcc.target/powerpc/altivec-31.c
new file mode 100644
index 00000000000..233efe1bebb
--- /dev/null
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-31.c
@@ -0,0 +1,29 @@
+/* { dg-do compile { target powerpc*-*-* } } */
+/* { dg-require-effective-target powerpc_altivec_ok } */
+/* { dg-options "-maltivec" } */
+
+#define f0(type) void x0##type (vector _Bool type x) { }
+f0 (int)
+
+#define f1(v, type) void x1##type (v _Bool type x) { }
+f1 (vector, int)
+
+#define f2(b, type) void x2##type (vector b type x) { }
+f2 (_Bool, int)
+
+#define f3(v, b, type) void x3##type (v b type x) { }
+f3 (vector, _Bool, int)
+
+#define f4(v, b, type) void x4##type (v type b x) { }
+f4 (vector, _Bool, int)
+
+#define B _Bool
+#define I int
+#define BI _Bool int
+#define VBI vector _Bool int
+
+vector _Bool int a;
+vector B int b;
+vector B I c;
+vector BI d;
+VBI e;
diff --git a/gcc/testsuite/gcc.target/powerpc/altivec-types-1.c b/gcc/testsuite/gcc.target/powerpc/altivec-types-1.c
index d293042d64f..41de95225b3 100644
--- a/gcc/testsuite/gcc.target/powerpc/altivec-types-1.c
+++ b/gcc/testsuite/gcc.target/powerpc/altivec-types-1.c
@@ -24,6 +24,7 @@ __vector unsigned vuj;
__vector signed vsj;
__vector __bool vbj;
__vector float vf;
+__vector _Bool vb;
/* These should be rejected as invalid AltiVec types. */
@@ -37,7 +38,6 @@ __vector signed long long int vslli; /* { dg-error "AltiVec types" "" } */
__vector __bool long long int vblli; /* { dg-error "AltiVec types" "" } */
__vector double vd1; /* { dg-error "AltiVec types" "" } */
__vector long double vld; /* { dg-error "AltiVec types" "" } */
-__vector _Bool vb; /* { dg-error "AltiVec types" "" } */
__vector _Complex float vcf; /* { dg-error "AltiVec types" "" } */
__vector _Complex double vcd; /* { dg-error "AltiVec types" "" } */
__vector _Complex long double vcld; /* { dg-error "AltiVec types" "" } */
diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03 b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03
new file mode 100644
index 00000000000..89b8666d7ae
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4.f03
@@ -0,0 +1,115 @@
+! { dg-do run }
+! { dg-additional-sources c_f_pointer_shape_tests_2_driver.c }
+! Verify that the optional SHAPE parameter to c_f_pointer can be of any
+! valid integer kind. We don't test all kinds here since it would be
+! difficult to know what kinds are valid for the architecture we're running on.
+! However, testing ones that should be different should be sufficient.
+module c_f_pointer_shape_tests_4
+ use, intrinsic :: iso_c_binding
+ implicit none
+contains
+ subroutine test_long_long_1d(cPtr, num_elems) bind(c)
+ use, intrinsic :: iso_c_binding
+ type(c_ptr), value :: cPtr
+ integer(c_int), value :: num_elems
+ integer, dimension(:), pointer :: myArrayPtr
+ integer(c_long_long), dimension(1) :: shape
+ integer :: i
+
+ shape(1) = num_elems
+ call c_f_pointer(cPtr, myArrayPtr, shape)
+ do i = 1, num_elems
+ if(myArrayPtr(i) /= (i-1)) call abort ()
+ end do
+ end subroutine test_long_long_1d
+
+ subroutine test_long_long_2d(cPtr, num_rows, num_cols) bind(c)
+ use, intrinsic :: iso_c_binding
+ type(c_ptr), value :: cPtr
+ integer(c_int), value :: num_rows
+ integer(c_int), value :: num_cols
+ integer, dimension(:,:), pointer :: myArrayPtr
+ integer(c_long_long), dimension(3) :: shape
+ integer :: i,j
+
+ shape(1) = num_rows
+ shape(2) = -3;
+ shape(3) = num_cols
+ call c_f_pointer(cPtr, myArrayPtr, shape(1:3:2))
+ do j = 1, num_cols
+ do i = 1, num_rows
+ if(myArrayPtr(i,j) /= ((j-1)*num_rows)+(i-1)) call abort ()
+ end do
+ end do
+ end subroutine test_long_long_2d
+
+ subroutine test_long_1d(cPtr, num_elems) bind(c)
+ use, intrinsic :: iso_c_binding
+ type(c_ptr), value :: cPtr
+ integer(c_int), value :: num_elems
+ integer, dimension(:), pointer :: myArrayPtr
+ integer(c_long), dimension(1) :: shape
+ integer :: i
+
+ shape(1) = num_elems
+ call c_f_pointer(cPtr, myArrayPtr, shape)
+ do i = 1, num_elems
+ if(myArrayPtr(i) /= (i-1)) call abort ()
+ end do
+ end subroutine test_long_1d
+
+ subroutine test_int_1d(cPtr, num_elems) bind(c)
+ use, intrinsic :: iso_c_binding
+ type(c_ptr), value :: cPtr
+ integer(c_int), value :: num_elems
+ integer, dimension(:), pointer :: myArrayPtr
+ integer(c_int), dimension(1) :: shape
+ integer :: i
+
+ shape(1) = num_elems
+ call c_f_pointer(cPtr, myArrayPtr, shape)
+ do i = 1, num_elems
+ if(myArrayPtr(i) /= (i-1)) call abort ()
+ end do
+ end subroutine test_int_1d
+
+ subroutine test_short_1d(cPtr, num_elems) bind(c)
+ use, intrinsic :: iso_c_binding
+ type(c_ptr), value :: cPtr
+ integer(c_int), value :: num_elems
+ integer, dimension(:), pointer :: myArrayPtr
+ integer(c_short), dimension(1) :: shape
+ integer :: i
+
+ shape(1) = num_elems
+ call c_f_pointer(cPtr, myArrayPtr, shape)
+ do i = 1, num_elems
+ if(myArrayPtr(i) /= (i-1)) call abort ()
+ end do
+ end subroutine test_short_1d
+
+ subroutine test_mixed(cPtr, num_elems) bind(c)
+ use, intrinsic :: iso_c_binding
+ type(c_ptr), value :: cPtr
+ integer(c_int), value :: num_elems
+ integer, dimension(:), pointer :: myArrayPtr
+ integer(c_int), dimension(1) :: shape1
+ integer(c_long_long), dimension(1) :: shape2
+ integer :: i
+
+ shape1(1) = num_elems
+ call c_f_pointer(cPtr, myArrayPtr, shape1)
+ do i = 1, num_elems
+ if(myArrayPtr(i) /= (i-1)) call abort ()
+ end do
+
+ nullify(myArrayPtr)
+ shape2(1) = num_elems
+ call c_f_pointer(cPtr, myArrayPtr, shape2)
+ do i = 1, num_elems
+ if(myArrayPtr(i) /= (i-1)) call abort ()
+ end do
+ end subroutine test_mixed
+end module c_f_pointer_shape_tests_4
+! { dg-final { cleanup-modules "c_f_pointer_shape_tests_4" } }
+
diff --git a/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c
new file mode 100644
index 00000000000..1282beb12d7
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/c_f_pointer_shape_tests_4_driver.c
@@ -0,0 +1,46 @@
+#define NUM_ELEMS 10
+#define NUM_ROWS 2
+#define NUM_COLS 3
+
+void test_long_long_1d(int *array, int num_elems);
+void test_long_long_2d(int *array, int num_rows, int num_cols);
+void test_long_1d(int *array, int num_elems);
+void test_int_1d(int *array, int num_elems);
+void test_short_1d(int *array, int num_elems);
+void test_mixed(int *array, int num_elems);
+
+int main(int argc, char **argv)
+{
+ int my_array[NUM_ELEMS];
+ int my_2d_array[NUM_ROWS][NUM_COLS];
+ int i, j;
+
+ for(i = 0; i < NUM_ELEMS; i++)
+ my_array[i] = i;
+
+ for(i = 0; i < NUM_ROWS; i++)
+ for(j = 0; j < NUM_COLS; j++)
+ my_2d_array[i][j] = (i*NUM_COLS) + j;
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long. */
+ test_long_long_1d(my_array, NUM_ELEMS);
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_long_long.
+ The indices are transposed for Fortran. */
+ test_long_long_2d(my_2d_array[0], NUM_COLS, NUM_ROWS);
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_long. */
+ test_long_1d(my_array, NUM_ELEMS);
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_int. */
+ test_int_1d(my_array, NUM_ELEMS);
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_short. */
+ test_short_1d(my_array, NUM_ELEMS);
+
+ /* Test c_f_pointer where SHAPE is of type integer, kind=c_int and
+ kind=c_long_long. */
+ test_mixed(my_array, NUM_ELEMS);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gfortran.dg/elemental_dependency_1.f90 b/gcc/testsuite/gfortran.dg/elemental_dependency_1.f90
index 3e1f67b9a71..d76fad642e3 100644
--- a/gcc/testsuite/gfortran.dg/elemental_dependency_1.f90
+++ b/gcc/testsuite/gfortran.dg/elemental_dependency_1.f90
@@ -40,14 +40,14 @@ PROGRAM main
b = a
CALL double((a(1:sz-1)), a(2:sz)) ! paren expression, temporary created
-! { dg-final { scan-tree-dump-times "A\.17\\\[4\\\]" 1 "original" } }
+! { dg-final { scan-tree-dump-times "A\.16\\\[4\\\]" 1 "original" } }
IF (ANY(a /= (/ b(1), (2*b(i), i=1,sz-1) /))) CALL abort
b = a
CALL double(a(1:sz-1)+1, a(2:sz)) ! op expression, temporary created
-! { dg-final { scan-tree-dump-times "A\.26\\\[4\\\]" 1 "original" } }
+! { dg-final { scan-tree-dump-times "A\.25\\\[4\\\]" 1 "original" } }
IF (ANY(a /= (/ b(1), (2*b(i)+2, i=1,sz-1) /))) CALL abort
@@ -59,7 +59,7 @@ PROGRAM main
b = a
CALL double(self(a(1:sz-1)), a(2:sz)) ! function expr, temporary created
-! { dg-final { scan-tree-dump-times "A\.38\\\[4\\\]" 1 "original" } }
+! { dg-final { scan-tree-dump-times "A\.37\\\[4\\\]" 1 "original" } }
IF (ANY(a /= (/ b(1), (2*b(i), i=1,sz-1) /))) CALL abort
diff --git a/gcc/testsuite/gfortran.dg/leadz_trailz_1.f90 b/gcc/testsuite/gfortran.dg/leadz_trailz_1.f90
new file mode 100644
index 00000000000..a0cd1979225
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/leadz_trailz_1.f90
@@ -0,0 +1,133 @@
+! { dg-do run }
+
+ integer(kind=1) :: i1
+ integer(kind=2) :: i2
+ integer(kind=4) :: i4
+ integer(kind=8) :: i8
+
+ i1 = -1
+ i2 = -1
+ i4 = -1
+ i8 = -1
+
+ if (leadz(i1) /= 0) call abort
+ if (leadz(i2) /= 0) call abort
+ if (leadz(i4) /= 0) call abort
+ if (leadz(i8) /= 0) call abort
+
+ if (trailz(i1) /= 0) call abort
+ if (trailz(i2) /= 0) call abort
+ if (trailz(i4) /= 0) call abort
+ if (trailz(i8) /= 0) call abort
+
+ if (leadz(-1_1) /= 0) call abort
+ if (leadz(-1_2) /= 0) call abort
+ if (leadz(-1_4) /= 0) call abort
+ if (leadz(-1_8) /= 0) call abort
+
+ if (trailz(-1_1) /= 0) call abort
+ if (trailz(-1_2) /= 0) call abort
+ if (trailz(-1_4) /= 0) call abort
+ if (trailz(-1_8) /= 0) call abort
+
+ i1 = -64
+ i2 = -64
+ i4 = -64
+ i8 = -64
+
+ if (leadz(i1) /= 0) call abort
+ if (leadz(i2) /= 0) call abort
+ if (leadz(i4) /= 0) call abort
+ if (leadz(i8) /= 0) call abort
+
+ if (trailz(i1) /= 6) call abort
+ if (trailz(i2) /= 6) call abort
+ if (trailz(i4) /= 6) call abort
+ if (trailz(i8) /= 6) call abort
+
+ if (leadz(-64_1) /= 0) call abort
+ if (leadz(-64_2) /= 0) call abort
+ if (leadz(-64_4) /= 0) call abort
+ if (leadz(-64_8) /= 0) call abort
+
+ if (trailz(-64_1) /= 6) call abort
+ if (trailz(-64_2) /= 6) call abort
+ if (trailz(-64_4) /= 6) call abort
+ if (trailz(-64_8) /= 6) call abort
+
+ i1 = -108
+ i2 = -108
+ i4 = -108
+ i8 = -108
+
+ if (leadz(i1) /= 0) call abort
+ if (leadz(i2) /= 0) call abort
+ if (leadz(i4) /= 0) call abort
+ if (leadz(i8) /= 0) call abort
+
+ if (trailz(i1) /= 2) call abort
+ if (trailz(i2) /= 2) call abort
+ if (trailz(i4) /= 2) call abort
+ if (trailz(i8) /= 2) call abort
+
+ if (leadz(-108_1) /= 0) call abort
+ if (leadz(-108_2) /= 0) call abort
+ if (leadz(-108_4) /= 0) call abort
+ if (leadz(-108_8) /= 0) call abort
+
+ if (trailz(-108_1) /= 2) call abort
+ if (trailz(-108_2) /= 2) call abort
+ if (trailz(-108_4) /= 2) call abort
+ if (trailz(-108_8) /= 2) call abort
+
+ i1 = 1
+ i2 = 1
+ i4 = 1
+ i8 = 1
+
+ if (leadz(i1) /= bit_size(i1) - 1) call abort
+ if (leadz(i2) /= bit_size(i2) - 1) call abort
+ if (leadz(i4) /= bit_size(i4) - 1) call abort
+ if (leadz(i8) /= bit_size(i8) - 1) call abort
+
+ if (trailz(i1) /= 0) call abort
+ if (trailz(i2) /= 0) call abort
+ if (trailz(i4) /= 0) call abort
+ if (trailz(i8) /= 0) call abort
+
+ if (leadz(1_1) /= bit_size(1_1) - 1) call abort
+ if (leadz(1_2) /= bit_size(1_2) - 1) call abort
+ if (leadz(1_4) /= bit_size(1_4) - 1) call abort
+ if (leadz(1_8) /= bit_size(1_8) - 1) call abort
+
+ if (trailz(1_1) /= 0) call abort
+ if (trailz(1_2) /= 0) call abort
+ if (trailz(1_4) /= 0) call abort
+ if (trailz(1_8) /= 0) call abort
+
+ i1 = 64
+ i2 = 64
+ i4 = 64
+ i8 = 64
+
+ if (leadz(i1) /= 1) call abort
+ if (leadz(i2) /= 9) call abort
+ if (leadz(i4) /= 25) call abort
+ if (leadz(i8) /= 57) call abort
+
+ if (trailz(i1) /= 6) call abort
+ if (trailz(i2) /= 6) call abort
+ if (trailz(i4) /= 6) call abort
+ if (trailz(i8) /= 6) call abort
+
+ if (leadz(64_1) /= 1) call abort
+ if (leadz(64_2) /= 9) call abort
+ if (leadz(64_4) /= 25) call abort
+ if (leadz(64_8) /= 57) call abort
+
+ if (trailz(64_1) /= 6) call abort
+ if (trailz(64_2) /= 6) call abort
+ if (trailz(64_4) /= 6) call abort
+ if (trailz(64_8) /= 6) call abort
+
+end
diff --git a/gcc/testsuite/gfortran.dg/leadz_trailz_2.f90 b/gcc/testsuite/gfortran.dg/leadz_trailz_2.f90
new file mode 100644
index 00000000000..08701d8a537
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/leadz_trailz_2.f90
@@ -0,0 +1,36 @@
+! { dg-do run }
+! { dg-require-effective-target fortran_large_int }
+
+ integer(kind=16) :: i16
+
+ i16 = -1
+ if (leadz(i16) /= 0) call abort
+ if (trailz(i16) /= 0) call abort
+ if (leadz(-1_16) /= 0) call abort
+ if (trailz(-1_16) /= 0) call abort
+
+ i16 = -64
+ if (leadz(i16) /= 0) call abort
+ if (trailz(i16) /= 6) call abort
+ if (leadz(-64_16) /= 0) call abort
+ if (trailz(-64_16) /= 6) call abort
+
+ i16 = -108
+ if (leadz(i16) /= 0) call abort
+ if (trailz(i16) /= 2) call abort
+ if (leadz(-108_16) /= 0) call abort
+ if (trailz(-108_16) /= 2) call abort
+
+ i16 = 1
+ if (leadz(i16) /= bit_size(i16) - 1) call abort
+ if (trailz(i16) /= 0) call abort
+ if (leadz(1_16) /= bit_size(1_16) - 1) call abort
+ if (trailz(1_16) /= 0) call abort
+
+ i16 = 64
+ if (leadz(i16) /= 121) call abort
+ if (trailz(i16) /= 6) call abort
+ if (leadz(64_16) /= 121) call abort
+ if (trailz(64_16) /= 6) call abort
+
+end
diff --git a/gcc/testsuite/gfortran.dg/nullify_4.f90 b/gcc/testsuite/gfortran.dg/nullify_4.f90
new file mode 100644
index 00000000000..48dcf72ca9d
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/nullify_4.f90
@@ -0,0 +1,8 @@
+! { dg-do compile }
+! PR fortran/40246
+!
+! Check error recovery; was crashing before.
+!
+real, pointer :: ptr
+nullify(ptr, mesh%coarser) ! { dg-error "Syntax error in NULLIFY statement" }
+end
diff --git a/gcc/testsuite/gfortran.dg/pr25923.f90 b/gcc/testsuite/gfortran.dg/pr25923.f90
index f075944b92b..b6979ec8896 100644
--- a/gcc/testsuite/gfortran.dg/pr25923.f90
+++ b/gcc/testsuite/gfortran.dg/pr25923.f90
@@ -10,7 +10,7 @@ implicit none
contains
- function baz(arg) result(res) ! { dg-warning "res.yr' may be" }
+ function baz(arg) result(res) ! { dg-warning "res.yr' may be" "" { xfail *-*-* } }
type(bar), intent(in) :: arg
type(bar) :: res
logical, external:: some_func
diff --git a/gcc/testsuite/gfortran.dg/vector_subscript_4.f90 b/gcc/testsuite/gfortran.dg/vector_subscript_4.f90
index 204468456e1..5c341dab4a5 100644
--- a/gcc/testsuite/gfortran.dg/vector_subscript_4.f90
+++ b/gcc/testsuite/gfortran.dg/vector_subscript_4.f90
@@ -9,5 +9,5 @@
integer :: i(-1:1) = 1, j(3) = 1, k(3)
k = j((/1,1,1/)+i)
end
-! { dg-final { scan-tree-dump-times "A\.3\\\[3\\\]" 1 "original" } }
+! { dg-final { scan-tree-dump-times "A\.2\\\[3\\\]" 1 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
diff --git a/gcc/testsuite/gnat.dg/alignment6.adb b/gcc/testsuite/gnat.dg/alignment6.adb
index 548574f5cc9..f2889a50ecf 100644
--- a/gcc/testsuite/gnat.dg/alignment6.adb
+++ b/gcc/testsuite/gnat.dg/alignment6.adb
@@ -28,5 +28,5 @@ begin
B_REC := A_REC;
end;
--- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "gimple" { xfail *-*-* } } }
+-- { dg-final { scan-tree-dump-not "VIEW_CONVERT_EXPR" "gimple" } }
-- { dg-final { cleanup-tree-dump "gimple" } }
diff --git a/gcc/testsuite/gnat.dg/misaligned_nest.adb b/gcc/testsuite/gnat.dg/misaligned_nest.adb
new file mode 100644
index 00000000000..3b6fd845da4
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/misaligned_nest.adb
@@ -0,0 +1,26 @@
+-- { dg-do run }
+-- { dg-options "-gnatp" }
+
+procedure Misaligned_Nest is
+
+ type Int is record
+ V : Integer;
+ end record;
+
+ type Block is record
+ B : Boolean;
+ I : Int;
+ end record;
+ pragma Pack (Block);
+ for Block'Alignment use 1;
+
+ type Pair is array (1 .. 2) of Block;
+
+ P : Pair;
+begin
+ for K in P'Range loop
+ P(K).I.V := 1;
+ end loop;
+end;
+
+
diff --git a/gcc/testsuite/gnat.dg/nested_float_packed.ads b/gcc/testsuite/gnat.dg/nested_float_packed.ads
new file mode 100644
index 00000000000..ae7f5239068
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/nested_float_packed.ads
@@ -0,0 +1,24 @@
+-- { dg-do compile }
+
+package Nested_Float_Packed is
+
+ type Float_Type is record
+ Value : Float;
+ Valid : Boolean;
+ end record;
+
+ type Data_Type is record
+ Data : Float_Type;
+ end record;
+
+ Default_Data : constant Data_Type :=
+ (Data => (Value => 1.0, Valid => False));
+
+ type Range_Type is (RV1, RV2, RV3);
+ for Range_Type use (1, 2, 3);
+
+ Data_Block : array (Range_Type)
+ of Data_Type := (others => Default_Data);
+end;
+
+
diff --git a/gcc/testsuite/gnat.dg/oconst1.adb b/gcc/testsuite/gnat.dg/oconst1.adb
new file mode 100644
index 00000000000..1e97ad8f2eb
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst1.adb
@@ -0,0 +1,18 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package body OCONST1 is
+
+ procedure check (arg : R) is
+ begin
+ if arg.u /= 1
+ or else arg.b.i1 /= 2
+ or else arg.b.i2 /= 3
+ or else arg.b.i3 /= 4
+ then
+ raise Program_Error;
+ end if;
+ end;
+
+end;
+
diff --git a/gcc/testsuite/gnat.dg/oconst1.ads b/gcc/testsuite/gnat.dg/oconst1.ads
new file mode 100644
index 00000000000..93b35f79bae
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst1.ads
@@ -0,0 +1,25 @@
+package OCONST1 is
+
+ type u8 is mod 2**8;
+
+ type Base is record
+ i1 : Integer;
+ i2 : Integer;
+ i3 : Integer;
+ end Record;
+
+ type R is record
+ u : u8;
+ b : Base;
+ end record;
+
+ for R use record
+ u at 0 range 0 .. 7;
+ b at 1 range 0 .. 95; -- BLKmode bitfield
+ end record;
+
+ My_R : constant R := (u=>1, b=>(2, 3, 4));
+
+ procedure check (arg : R);
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst2.adb b/gcc/testsuite/gnat.dg/oconst2.adb
new file mode 100644
index 00000000000..d4f45ad5d04
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst2.adb
@@ -0,0 +1,15 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package body OCONST2 is
+
+ procedure check (arg : R) is
+ begin
+ if arg.u /= 1
+ or else arg.b.i1 /= 2
+ then
+ raise Program_Error;
+ end if;
+ end;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst2.ads b/gcc/testsuite/gnat.dg/oconst2.ads
new file mode 100644
index 00000000000..23e57a74cc2
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst2.ads
@@ -0,0 +1,23 @@
+package OCONST2 is
+
+ type u8 is mod 2**8;
+
+ type Base is record
+ i1 : Integer;
+ end Record;
+
+ type R is record
+ u : u8;
+ b : Base;
+ end record;
+
+ for R use record
+ u at 0 range 0 .. 7;
+ b at 1 range 0 .. 31; -- aligned SImode bitfield
+ end record;
+
+ My_R : constant R := (u=>1, b=>(i1=>2));
+
+ procedure check (arg : R);
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst3.adb b/gcc/testsuite/gnat.dg/oconst3.adb
new file mode 100644
index 00000000000..c9a94d4f491
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst3.adb
@@ -0,0 +1,16 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package body OCONST3 is
+
+ procedure check (arg : R) is
+ begin
+ if arg.u /= 1
+ or else arg.f /= one
+ or else arg.b.i1 /= 3
+ then
+ raise Program_Error;
+ end if;
+ end;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst3.ads b/gcc/testsuite/gnat.dg/oconst3.ads
new file mode 100644
index 00000000000..6a0094b57e9
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst3.ads
@@ -0,0 +1,26 @@
+package OCONST3 is
+
+ type bit is (zero, one);
+ type u8 is mod 2**8;
+
+ type Base is record
+ i1 : Integer;
+ end Record;
+
+ type R is record
+ u : u8;
+ f : bit;
+ b : Base;
+ end record;
+
+ for R use record
+ u at 0 range 0 .. 7;
+ f at 1 range 0 .. 0;
+ b at 1 range 1 .. 32; -- unaligned SImode bitfield
+ end record;
+
+ My_R : constant R := (u=>1, f=>one, b=>(i1=>3));
+
+ procedure check (arg : R);
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst4.adb b/gcc/testsuite/gnat.dg/oconst4.adb
new file mode 100644
index 00000000000..f97f217b3da
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst4.adb
@@ -0,0 +1,24 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package body OCONST4 is
+
+ procedure check (arg : R) is
+ begin
+ if arg.u /= 1
+ or else arg.d.f1 /= 17
+ or else arg.d.b.f1 /= one
+ or else arg.d.b.f2 /= 2
+ or else arg.d.b.f3 /= 17
+ or else arg.d.b.f4 /= 42
+ or else arg.d.f2 /= one
+ or else arg.d.f3 /= 1
+ or else arg.d.f4 /= 111
+ or else arg.d.i1 /= 2
+ or else arg.d.i2 /= 3
+ then
+ raise Program_Error;
+ end if;
+ end;
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst4.ads b/gcc/testsuite/gnat.dg/oconst4.ads
new file mode 100644
index 00000000000..cde0935fe8d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst4.ads
@@ -0,0 +1,66 @@
+package OCONST4 is
+
+ type bit is (zero, one);
+ type u2 is mod 2**2;
+ type u5 is mod 2**5;
+ type u8 is mod 2**8;
+
+ type Base is record
+ f1 : bit;
+ f2 : u2;
+ f3 : u5;
+ f4 : u8;
+ end record;
+
+ for Base use record
+ f1 at 0 range 0 .. 0;
+ f2 at 0 range 1 .. 2;
+ f3 at 0 range 3 .. 7;
+ f4 at 1 range 0 .. 7;
+ end record;
+
+ type Derived is record
+ f1 : u5;
+ b : Base;
+ f2 : bit;
+ f3 : u2;
+ f4 : u8;
+ i1 : Integer;
+ i2 : Integer;
+ end record;
+
+ for Derived use record
+ f1 at 0 range 0 .. 4;
+ b at 0 range 5 .. 20; -- unaligned HImode bitfield
+ f2 at 0 range 21 .. 21;
+ f3 at 0 range 22 .. 23;
+ f4 at 0 range 24 .. 31;
+ i1 at 4 range 0 .. 31;
+ i2 at 8 range 0 .. 31;
+ end record;
+
+ type R is record
+ u : u8;
+ d : Derived;
+ end record;
+
+ for R use record
+ u at 0 range 0 .. 7;
+ d at 1 range 0 .. 95; -- BLKmode bitfield
+ end record;
+
+ My_R : constant R := (u=>1,
+ d=>(f1=>17,
+ b=>(f1=>one,
+ f2=>2,
+ f3=>17,
+ f4=>42),
+ f2=>one,
+ f3=>1,
+ f4=>111,
+ i1=>2,
+ i2=>3));
+
+ procedure check (arg : R);
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst5.adb b/gcc/testsuite/gnat.dg/oconst5.adb
new file mode 100644
index 00000000000..4d4896aea58
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst5.adb
@@ -0,0 +1,15 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package body OCONST5 is
+
+ procedure Check (Arg : R; Bit : U1) is
+ begin
+ if Arg.Bit /= Bit
+ or else Arg.Agg.A /= 3
+ or else Arg.Agg.B /= 7
+ then
+ raise Program_Error;
+ end if;
+ end;
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst5.ads b/gcc/testsuite/gnat.dg/oconst5.ads
new file mode 100644
index 00000000000..f12a265d0d3
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst5.ads
@@ -0,0 +1,27 @@
+package OCONST5 is
+
+ type u1 is mod 2**1;
+ type u8 is mod 2**8;
+
+ type HI_Record is record
+ A, B : U8;
+ end record;
+ pragma Suppress_Initialization (HI_Record);
+
+ type R is record
+ Bit : U1;
+ Agg : HI_Record;
+ end record;
+ pragma Suppress_Initialization (R);
+
+ for R use record
+ Bit at 0 range 0 .. 0;
+ Agg at 0 range 1 .. 16;
+ end record;
+
+ My_R0 : R := (Bit => 0, Agg => (A => 3, B => 7));
+ My_R1 : R := (Bit => 1, Agg => (A => 3, B => 7));
+
+ procedure Check (Arg : R; Bit : U1);
+
+end;
diff --git a/gcc/testsuite/gnat.dg/oconst6.ads b/gcc/testsuite/gnat.dg/oconst6.ads
new file mode 100644
index 00000000000..e4c3c50eb0d
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/oconst6.ads
@@ -0,0 +1,18 @@
+-- { dg-do compile }
+-- { dg-final { scan-assembler-not "elabs" } }
+
+package OCONST6 is
+
+ type Sequence is array (1 .. 1) of Natural;
+
+ type Message is record
+ Data : Sequence;
+ end record;
+
+ for Message'Alignment use 1;
+ pragma PACK (Message);
+
+ ACK : Message := (Data => (others => 1));
+
+end;
+
diff --git a/gcc/testsuite/gnat.dg/pack9.adb b/gcc/testsuite/gnat.dg/pack9.adb
index 64d71b11cc9..232904ac1e1 100644
--- a/gcc/testsuite/gnat.dg/pack9.adb
+++ b/gcc/testsuite/gnat.dg/pack9.adb
@@ -1,5 +1,5 @@
-- { dg-do compile }
--- { dg-options "-O2 -gnatp -cargs --param sra-max-structure-size=24 --param sra-max-structure-count=6 -fdump-tree-optimized" }
+-- { dg-options "-O2 -gnatp -cargs -fdump-tree-optimized" }
package body Pack9 is
diff --git a/gcc/testsuite/gnat.dg/test_oconst.adb b/gcc/testsuite/gnat.dg/test_oconst.adb
new file mode 100644
index 00000000000..23e5a97d537
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/test_oconst.adb
@@ -0,0 +1,13 @@
+-- { dg-do run }
+
+with OCONST1, OCONST2, OCONST3, OCONST4, OCONST5;
+
+procedure Test_Oconst is
+begin
+ OCONST1.check (OCONST1.My_R);
+ OCONST2.check (OCONST2.My_R);
+ OCONST3.check (OCONST3.My_R);
+ OCONST4.check (OCONST4.My_R);
+ OCONST5.check (OCONST5.My_R0, 0);
+ OCONST5.check (OCONST5.My_R1, 1);
+end;
diff --git a/gcc/testsuite/lib/gcc-dg.exp b/gcc/testsuite/lib/gcc-dg.exp
index 7d00acf6d1a..e906265e40c 100644
--- a/gcc/testsuite/lib/gcc-dg.exp
+++ b/gcc/testsuite/lib/gcc-dg.exp
@@ -620,6 +620,17 @@ if { [info procs saved-dg-error] == [list] \
process-message saved-dg-error "$gcc_error_prefix" "$args"
}
+
+ # Override dg-bogus at the same time. It doesn't handle a prefix
+ # but its expression should include a column number. Otherwise the
+ # line number can match the column number for other messages, leading
+ # to insanity.
+ rename dg-bogus saved-dg-bogus
+
+ proc dg-bogus { args } {
+ upvar dg-messages dg-messages
+ process-message saved-dg-bogus "" $args
+ }
}
# Modify the regular expression saved by a DejaGnu message directive to
@@ -641,20 +652,26 @@ proc process-message { msgproc msgprefix dgargs } {
return;
}
- # Prepend the message prefix to the regular expression and make
- # it match a single line.
+ # Get the entry for the new message. Prepend the message prefix to
+ # the regular expression and make it match a single line.
set newentry [lindex ${dg-messages} end]
set expmsg [lindex $newentry 2]
- # If we have a column...
+ # Handle column numbers from the specified expression (if there is
+ # one) and set up the search expression that will be used by DejaGnu.
if [regexp "^(\[0-9\]+):" $expmsg "" column] {
- # Remove "COLUMN:"
+ # The expression in the directive included a column number.
+ # Remove "COLUMN:" from the original expression and move it
+ # to the proper place in the search expression.
regsub "^\[0-9\]+:" $expmsg "" expmsg
-
- # Include the column in the search expression.
- set expmsg "$column: $msgprefix\[^\n]*$expmsg"
+ set expmsg "$column: $msgprefix\[^\n\]*$expmsg"
+ } elseif [string match "" [lindex $newentry 0]] {
+ # The specified line number is 0; don't expect a column number.
+ set expmsg "$msgprefix\[^\n\]*$expmsg"
} else {
- set expmsg "$msgprefix\[^\n]*$expmsg"
+ # There is no column number in the search expression, but we
+ # should expect one in the message itself.
+ set expmsg "\[0-9\]+: $msgprefix\[^\n\]*$expmsg"
}
set newentry [lreplace $newentry 2 2 $expmsg]
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index f726e6f05d0..e2d24c8c156 100644
--- a/gcc/testsuite/lib/target-supports.exp
+++ b/gcc/testsuite/lib/target-supports.exp
@@ -611,6 +611,18 @@ proc check_effective_target_pthread {} {
} "-pthread"]
}
+# Return 1 if compilation with -mpe-aligned-commons is error-free
+# for trivial code, 0 otherwise.
+
+proc check_effective_target_pe_aligned_commons {} {
+ if { [istarget *-*-cygwin*] || [istarget *-*-mingw*] } {
+ return [check_no_compiler_messages pe_aligned_commons object {
+ int foo;
+ } "-mpe-aligned-commons"]
+ }
+ return 0
+}
+
# Return 1 if the target supports -fstack-protector
proc check_effective_target_fstack_protector {} {
return [check_runtime fstack_protector {
diff --git a/gcc/toplev.c b/gcc/toplev.c
index aa3ca5c210f..467623a156c 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -1,6 +1,6 @@
/* Top level of GCC compilers (cc1, cc1plus, etc.)
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
@@ -2384,14 +2384,14 @@ toplev_main (int argc, char **argv)
{
expandargv (&argc, &argv);
- save_argv = (const char **) argv;
+ save_argv = CONST_CAST2 (const char **, char **, argv);
/* Initialization of GCC's environment, and diagnostics. */
general_init (argv[0]);
/* Parse the options and do minimal processing; basically just
enough to default flags appropriately. */
- decode_options (argc, (const char **) argv);
+ decode_options (argc, CONST_CAST2 (const char **, char **, argv));
init_local_tick ();
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index dc79e8a8bc4..2181f469ca0 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -718,17 +718,26 @@ dr_analyze_innermost (struct data_reference *dr)
base_iv.no_overflow = true;
}
- if (!poffset || !in_loop)
+ if (!poffset)
{
offset_iv.base = ssize_int (0);
offset_iv.step = ssize_int (0);
}
- else if (!simple_iv (loop, loop_containing_stmt (stmt),
- poffset, &offset_iv, false))
+ else
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "failed: evolution of offset is not affine.\n");
- return false;
+ if (!in_loop)
+ {
+ offset_iv.base = poffset;
+ offset_iv.step = ssize_int (0);
+ }
+ else if (!simple_iv (loop, loop_containing_stmt (stmt),
+ poffset, &offset_iv, false))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "failed: evolution of offset is not"
+ " affine.\n");
+ return false;
+ }
}
init = ssize_int (pbitpos / BITS_PER_UNIT);
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index d4a379c333c..4fecd01c423 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -750,7 +750,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
switch (TREE_CODE (exp))
{
case BIT_FIELD_REF:
- bit_offset += tree_low_cst (TREE_OPERAND (exp, 2), 0);
+ bit_offset += TREE_INT_CST_LOW (TREE_OPERAND (exp, 2));
break;
case COMPONENT_REF:
@@ -761,13 +761,14 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
if (TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == UNION_TYPE)
seen_union = true;
- if (this_offset && TREE_CODE (this_offset) == INTEGER_CST)
+ if (this_offset
+ && TREE_CODE (this_offset) == INTEGER_CST
+ && host_integerp (this_offset, 0))
{
- HOST_WIDE_INT hthis_offset = tree_low_cst (this_offset, 0);
-
+ HOST_WIDE_INT hthis_offset = TREE_INT_CST_LOW (this_offset);
hthis_offset *= BITS_PER_UNIT;
bit_offset += hthis_offset;
- bit_offset += tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 0);
+ bit_offset += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
}
else
{
@@ -787,18 +788,20 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
case ARRAY_RANGE_REF:
{
tree index = TREE_OPERAND (exp, 1);
- tree low_bound = array_ref_low_bound (exp);
- tree unit_size = array_ref_element_size (exp);
+ tree low_bound, unit_size;
/* If the resulting bit-offset is constant, track it. */
- if (host_integerp (index, 0)
- && host_integerp (low_bound, 0)
- && host_integerp (unit_size, 1))
+ if (TREE_CODE (index) == INTEGER_CST
+ && host_integerp (index, 0)
+ && (low_bound = array_ref_low_bound (exp),
+ host_integerp (low_bound, 0))
+ && (unit_size = array_ref_element_size (exp),
+ host_integerp (unit_size, 1)))
{
- HOST_WIDE_INT hindex = tree_low_cst (index, 0);
+ HOST_WIDE_INT hindex = TREE_INT_CST_LOW (index);
- hindex -= tree_low_cst (low_bound, 0);
- hindex *= tree_low_cst (unit_size, 1);
+ hindex -= TREE_INT_CST_LOW (low_bound);
+ hindex *= TREE_INT_CST_LOW (unit_size);
hindex *= BITS_PER_UNIT;
bit_offset += hindex;
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index df14eeb2268..7585de5990a 100644
--- a/gcc/tree-flow.h
+++ b/gcc/tree-flow.h
@@ -679,7 +679,6 @@ int loop_depth_of_name (tree);
tree degenerate_phi_result (gimple);
/* In tree-ssa-copy.c */
-extern void merge_alias_info (tree, tree);
extern void propagate_value (use_operand_p, tree);
extern void propagate_tree_value (tree *, tree);
extern void propagate_tree_value_into_stmt (gimple_stmt_iterator *, tree);
@@ -911,6 +910,7 @@ void mark_addressable (tree);
/* In tree-ssa-live.c */
extern void remove_unused_locals (void);
extern void dump_scope_blocks (FILE *, int);
+extern void debug_scope_blocks (int);
/* In tree-ssa-address.c */
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c
index b9632a9df8f..f79424d9756 100644
--- a/gcc/tree-inline.c
+++ b/gcc/tree-inline.c
@@ -501,7 +501,7 @@ remap_decls (tree decls, VEC(tree,gc) **nonlocalized_list, copy_body_data *id)
&& (var_ann (old_var) || !gimple_in_ssa_p (cfun)))
cfun->local_decls = tree_cons (NULL_TREE, old_var,
cfun->local_decls);
- if (debug_info_level > DINFO_LEVEL_TERSE
+ if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE)
&& !DECL_IGNORED_P (old_var)
&& nonlocalized_list)
VEC_safe_push (tree, gc, *nonlocalized_list, origin_var);
@@ -519,7 +519,7 @@ remap_decls (tree decls, VEC(tree,gc) **nonlocalized_list, copy_body_data *id)
;
else if (!new_var)
{
- if (debug_info_level > DINFO_LEVEL_TERSE
+ if ((!optimize || debug_info_level > DINFO_LEVEL_TERSE)
&& !DECL_IGNORED_P (old_var)
&& nonlocalized_list)
VEC_safe_push (tree, gc, *nonlocalized_list, origin_var);
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index ff7ffca1347..0605c2f1836 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -40,7 +40,6 @@ along with GCC; see the file COPYING3. If not see
/* Local functions, macros and variables. */
static const char *op_symbol (const_tree);
static void pretty_print_string (pretty_printer *, const char*);
-static void print_call_name (pretty_printer *, const_tree);
static void newline_and_indent (pretty_printer *, int);
static void maybe_init_pretty_print (FILE *);
static void print_struct_decl (pretty_printer *, const_tree, int, int);
@@ -423,6 +422,135 @@ dump_omp_clauses (pretty_printer *buffer, tree clause, int spc, int flags)
}
+/* Dump location LOC to BUFFER. */
+
+static void
+dump_location (pretty_printer *buffer, location_t loc)
+{
+ expanded_location xloc = expand_location (loc);
+
+ pp_character (buffer, '[');
+ if (xloc.file)
+ {
+ pp_string (buffer, xloc.file);
+ pp_string (buffer, " : ");
+ }
+ pp_decimal_int (buffer, xloc.line);
+ pp_string (buffer, "] ");
+}
+
+
+/* Dump lexical block BLOCK. BUFFER, SPC and FLAGS are as in
+ dump_generic_node. */
+
+static void
+dump_block_node (pretty_printer *buffer, tree block, int spc, int flags)
+{
+ tree t;
+
+ pp_printf (buffer, "BLOCK #%d ", BLOCK_NUMBER (block));
+
+ if (flags & TDF_ADDRESS)
+ pp_printf (buffer, "[%p] ", (void *) block);
+
+ if (BLOCK_ABSTRACT (block))
+ pp_string (buffer, "[abstract] ");
+
+ if (TREE_ASM_WRITTEN (block))
+ pp_string (buffer, "[written] ");
+
+ if (flags & TDF_SLIM)
+ return;
+
+ if (BLOCK_SOURCE_LOCATION (block))
+ dump_location (buffer, BLOCK_SOURCE_LOCATION (block));
+
+ newline_and_indent (buffer, spc + 2);
+
+ if (BLOCK_SUPERCONTEXT (block))
+ {
+ pp_string (buffer, "SUPERCONTEXT: ");
+ dump_generic_node (buffer, BLOCK_SUPERCONTEXT (block), 0,
+ flags | TDF_SLIM, false);
+ newline_and_indent (buffer, spc + 2);
+ }
+
+ if (BLOCK_SUBBLOCKS (block))
+ {
+ pp_string (buffer, "SUBBLOCKS: ");
+ for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
+ {
+ dump_generic_node (buffer, t, 0, flags | TDF_SLIM, false);
+ pp_string (buffer, " ");
+ }
+ newline_and_indent (buffer, spc + 2);
+ }
+
+ if (BLOCK_CHAIN (block))
+ {
+ pp_string (buffer, "SIBLINGS: ");
+ for (t = BLOCK_CHAIN (block); t; t = BLOCK_CHAIN (t))
+ {
+ dump_generic_node (buffer, t, 0, flags | TDF_SLIM, false);
+ pp_string (buffer, " ");
+ }
+ newline_and_indent (buffer, spc + 2);
+ }
+
+ if (BLOCK_VARS (block))
+ {
+ pp_string (buffer, "VARS: ");
+ for (t = BLOCK_VARS (block); t; t = TREE_CHAIN (t))
+ {
+ dump_generic_node (buffer, t, 0, flags, false);
+ pp_string (buffer, " ");
+ }
+ newline_and_indent (buffer, spc + 2);
+ }
+
+ if (VEC_length (tree, BLOCK_NONLOCALIZED_VARS (block)) > 0)
+ {
+ unsigned i;
+ VEC(tree,gc) *nlv = BLOCK_NONLOCALIZED_VARS (block);
+
+ pp_string (buffer, "NONLOCALIZED_VARS: ");
+ for (i = 0; VEC_iterate (tree, nlv, i, t); i++)
+ {
+ dump_generic_node (buffer, t, 0, flags, false);
+ pp_string (buffer, " ");
+ }
+ newline_and_indent (buffer, spc + 2);
+ }
+
+ if (BLOCK_ABSTRACT_ORIGIN (block))
+ {
+ pp_string (buffer, "ABSTRACT_ORIGIN: ");
+ dump_generic_node (buffer, BLOCK_ABSTRACT_ORIGIN (block), 0,
+ flags | TDF_SLIM, false);
+ newline_and_indent (buffer, spc + 2);
+ }
+
+ if (BLOCK_FRAGMENT_ORIGIN (block))
+ {
+ pp_string (buffer, "FRAGMENT_ORIGIN: ");
+ dump_generic_node (buffer, BLOCK_FRAGMENT_ORIGIN (block), 0,
+ flags | TDF_SLIM, false);
+ newline_and_indent (buffer, spc + 2);
+ }
+
+ if (BLOCK_FRAGMENT_CHAIN (block))
+ {
+ pp_string (buffer, "FRAGMENT_CHAIN: ");
+ for (t = BLOCK_FRAGMENT_CHAIN (block); t; t = BLOCK_FRAGMENT_CHAIN (t))
+ {
+ dump_generic_node (buffer, t, 0, flags | TDF_SLIM, false);
+ pp_string (buffer, " ");
+ }
+ newline_and_indent (buffer, spc + 2);
+ }
+}
+
+
/* Dump the node NODE on the pretty_printer BUFFER, SPC spaces of
indent. FLAGS specifies details to show in the dump (see TDF_* in
tree-pass.h). If IS_STMT is true, the object printed is considered
@@ -446,17 +574,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
pp_printf (buffer, "<&%p> ", (void *)node);
if ((flags & TDF_LINENO) && EXPR_HAS_LOCATION (node))
- {
- expanded_location xloc = expand_location (EXPR_LOCATION (node));
- pp_character (buffer, '[');
- if (xloc.file)
- {
- pp_string (buffer, xloc.file);
- pp_string (buffer, " : ");
- }
- pp_decimal_int (buffer, xloc.line);
- pp_string (buffer, "] ");
- }
+ dump_location (buffer, EXPR_LOCATION (node));
switch (TREE_CODE (node))
{
@@ -1210,7 +1328,7 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
break;
case CALL_EXPR:
- print_call_name (buffer, node);
+ print_call_name (buffer, CALL_EXPR_FN (node));
/* Print parameters. */
pp_space (buffer);
@@ -2002,62 +2120,8 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
break;
case BLOCK:
- {
- tree t;
- pp_string (buffer, "BLOCK");
-
- if (BLOCK_ABSTRACT (node))
- pp_string (buffer, " [abstract]");
-
- if (TREE_ASM_WRITTEN (node))
- pp_string (buffer, " [written]");
-
- newline_and_indent (buffer, spc + 2);
-
- if (BLOCK_SUPERCONTEXT (node))
- {
- pp_string (buffer, "SUPERCONTEXT: ");
- if (TREE_CODE (BLOCK_SUPERCONTEXT (node)) == BLOCK)
- pp_printf (buffer, "BLOCK %p",
- (void *)BLOCK_SUPERCONTEXT (node));
- else
- dump_generic_node (buffer, BLOCK_SUPERCONTEXT (node), 0, flags,
- false);
- newline_and_indent (buffer, spc + 2);
- }
-
- if (BLOCK_SUBBLOCKS (node))
- {
- pp_string (buffer, "SUBBLOCKS: ");
- for (t = BLOCK_SUBBLOCKS (node); t; t = BLOCK_CHAIN (t))
- pp_printf (buffer, "%p ", (void *)t);
- newline_and_indent (buffer, spc + 2);
- }
-
- if (BLOCK_VARS (node))
- {
- pp_string (buffer, "VARS: ");
- for (t = BLOCK_VARS (node); t; t = TREE_CHAIN (t))
- {
- dump_generic_node (buffer, t, 0, flags, false);
- pp_string (buffer, " ");
- }
- newline_and_indent (buffer, spc + 2);
- }
-
- if (BLOCK_ABSTRACT_ORIGIN (node))
- {
- pp_string (buffer, "ABSTRACT_ORIGIN: ");
- if (TREE_CODE (BLOCK_ABSTRACT_ORIGIN (node)) == BLOCK)
- pp_printf (buffer, "BLOCK %p",
- (void *)BLOCK_ABSTRACT_ORIGIN (node));
- else
- dump_generic_node (buffer, BLOCK_ABSTRACT_ORIGIN (node), 0, flags,
- false);
- newline_and_indent (buffer, spc + 2);
- }
- }
- break;
+ dump_block_node (buffer, node, spc, flags);
+ break;
case VEC_EXTRACT_EVEN_EXPR:
pp_string (buffer, " VEC_EXTRACT_EVEN_EXPR < ");
@@ -2597,32 +2661,31 @@ op_symbol (const_tree op)
return op_symbol_code (TREE_CODE (op));
}
-/* Prints the name of a CALL_EXPR. */
+/* Prints the name of a call. NODE is the CALL_EXPR_FN of a CALL_EXPR or
+ the gimple_call_fn of a GIMPLE_CALL. */
-static void
-print_call_name (pretty_printer *buffer, const_tree node)
+void
+print_call_name (pretty_printer *buffer, tree node)
{
- tree op0;
-
- gcc_assert (TREE_CODE (node) == CALL_EXPR);
-
- op0 = CALL_EXPR_FN (node);
+ tree op0 = node;
if (TREE_CODE (op0) == NON_LVALUE_EXPR)
op0 = TREE_OPERAND (op0, 0);
+ again:
switch (TREE_CODE (op0))
{
case VAR_DECL:
case PARM_DECL:
+ case FUNCTION_DECL:
dump_function_name (buffer, op0);
break;
case ADDR_EXPR:
case INDIRECT_REF:
case NOP_EXPR:
- dump_generic_node (buffer, TREE_OPERAND (op0, 0), 0, 0, false);
- break;
+ op0 = TREE_OPERAND (op0, 0);
+ goto again;
case COND_EXPR:
pp_string (buffer, "(");
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 0f689417163..825d6e80ae7 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -1,19 +1,18 @@
/* Scalar Replacement of Aggregates (SRA) converts some structure
references into scalar references, exposing them to the scalar
optimizers.
- Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009
- Free Software Foundation, Inc.
- Contributed by Diego Novillo <dnovillo@redhat.com>
+ Copyright (C) 2008, 2009 Free Software Foundation, Inc.
+ Contributed by Martin Jambor <mjambor@suse.cz>
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 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
+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.
@@ -21,3660 +20,2295 @@ You should have received a copy of the GNU General Public License
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
+/* This file implements Scalar Reduction of Aggregates (SRA). SRA is run
+ twice, once in the early stages of compilation (early SRA) and once in the
+ late stages (late SRA). The aim of both is to turn references to scalar
+ parts of aggregates into uses of independent scalar variables.
+
+ The two passes are nearly identical, the only difference is that early SRA
+ does not scalarize unions which are used as the result in a GIMPLE_RETURN
+ statement because together with inlining this can lead to weird type
+ conversions.
+
+ Both passes operate in four stages:
+
+ 1. The declarations that have properties which make them candidates for
+ scalarization are identified in function find_var_candidates(). The
+ candidates are stored in candidate_bitmap.
+
+ 2. The function body is scanned. In the process, declarations which are
+ used in a manner that prevent their scalarization are removed from the
+ candidate bitmap. More importantly, for every access into an aggregate,
+ an access structure (struct access) is created by create_access() and
+ stored in a vector associated with the aggregate. Among other
+ information, the aggregate declaration, the offset and size of the access
+ and its type are stored in the structure.
+
+ On a related note, assign_link structures are created for every assign
+ statement between candidate aggregates and attached to the related
+ accesses.
+
+ 3. The vectors of accesses are analyzed. They are first sorted according to
+ their offset and size and then scanned for partially overlapping accesses
+ (i.e. those which overlap but one is not entirely within another). Such
+ an access disqualifies the whole aggregate from being scalarized.
+
+ If there is no such inhibiting overlap, a representative access structure
+ is chosen for every unique combination of offset and size. Afterwards,
+ the pass builds a set of trees from these structures, in which children
+ of an access are within their parent (in terms of offset and size).
+
+ Then accesses are propagated whenever possible (i.e. in cases when it
+ does not create a partially overlapping access) across assign_links from
+ the right hand side to the left hand side.
+
+ Then the set of trees for each declaration is traversed again and those
+ accesses which should be replaced by a scalar are identified.
+
+ 4. The function is traversed again, and for every reference into an
+ aggregate that has some component which is about to be scalarized,
+ statements are amended and new statements are created as necessary.
+ Finally, if a parameter got scalarized, the scalar replacements are
+ initialized with values from respective parameter aggregates. */
+
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "alloc-pool.h"
#include "tm.h"
-#include "ggc.h"
#include "tree.h"
-
-/* These RTL headers are needed for basic-block.h. */
-#include "rtl.h"
-#include "tm_p.h"
-#include "hard-reg-set.h"
-#include "basic-block.h"
-#include "diagnostic.h"
-#include "langhooks.h"
-#include "tree-inline.h"
-#include "tree-flow.h"
#include "gimple.h"
+#include "tree-flow.h"
+#include "diagnostic.h"
#include "tree-dump.h"
-#include "tree-pass.h"
#include "timevar.h"
-#include "flags.h"
-#include "bitmap.h"
-#include "obstack.h"
-#include "target.h"
-/* expr.h is needed for MOVE_RATIO. */
-#include "expr.h"
#include "params.h"
+#include "target.h"
+#include "flags.h"
+/* Enumeration of all aggregate reductions we can do. */
+enum sra_mode { SRA_MODE_EARLY_INTRA, /* early intraprocedural SRA */
+ SRA_MODE_INTRA }; /* late intraprocedural SRA */
-/* This object of this pass is to replace a non-addressable aggregate with a
- set of independent variables. Most of the time, all of these variables
- will be scalars. But a secondary objective is to break up larger
- aggregates into smaller aggregates. In the process we may find that some
- bits of the larger aggregate can be deleted as unreferenced.
-
- This substitution is done globally. More localized substitutions would
- be the purvey of a load-store motion pass.
-
- The optimization proceeds in phases:
-
- (1) Identify variables that have types that are candidates for
- decomposition.
-
- (2) Scan the function looking for the ways these variables are used.
- In particular we're interested in the number of times a variable
- (or member) is needed as a complete unit, and the number of times
- a variable (or member) is copied.
-
- (3) Based on the usage profile, instantiate substitution variables.
-
- (4) Scan the function making replacements.
-*/
-
+/* Global variable describing which aggregate reduction we are performing at
+ the moment. */
+static enum sra_mode sra_mode;
-/* True if this is the "early" pass, before inlining. */
-static bool early_sra;
+struct assign_link;
-/* The set of aggregate variables that are candidates for scalarization. */
-static bitmap sra_candidates;
+/* ACCESS represents each access to an aggregate variable (as a whole or a
+ part). It can also represent a group of accesses that refer to exactly the
+ same fragment of an aggregate (i.e. those that have exactly the same offset
+ and size). Such representatives for a single aggregate, once determined,
+ are linked in a linked list and have the group fields set.
-/* Set of scalarizable PARM_DECLs that need copy-in operations at the
- beginning of the function. */
-static bitmap needs_copy_in;
+ Moreover, when doing intraprocedural SRA, a tree is built from those
+ representatives (by the means of first_child and next_sibling pointers), in
+ which all items in a subtree are "within" the root, i.e. their offset is
+ greater or equal to offset of the root and offset+size is smaller or equal
+ to offset+size of the root. Children of an access are sorted by offset.
-/* Sets of bit pairs that cache type decomposition and instantiation. */
-static bitmap sra_type_decomp_cache;
-static bitmap sra_type_inst_cache;
+ Note that accesses to parts of vector and complex number types always
+ represented by an access to the whole complex number or a vector. It is a
+ duty of the modifying functions to replace them appropriately. */
-/* One of these structures is created for each candidate aggregate and
- each (accessed) member or group of members of such an aggregate. */
-struct sra_elt
+struct access
{
- /* A tree of the elements. Used when we want to traverse everything. */
- struct sra_elt *parent;
- struct sra_elt *groups;
- struct sra_elt *children;
- struct sra_elt *sibling;
-
- /* If this element is a root, then this is the VAR_DECL. If this is
- a sub-element, this is some token used to identify the reference.
- In the case of COMPONENT_REF, this is the FIELD_DECL. In the case
- of an ARRAY_REF, this is the (constant) index. In the case of an
- ARRAY_RANGE_REF, this is the (constant) RANGE_EXPR. In the case
- of a complex number, this is a zero or one. */
- tree element;
-
- /* The type of the element. */
- tree type;
+ /* Values returned by `get_ref_base_and_extent' for each component reference
+ If EXPR isn't a component reference just set `BASE = EXPR', `OFFSET = 0',
+ `SIZE = TREE_SIZE (TREE_TYPE (expr))'. */
+ HOST_WIDE_INT offset;
+ HOST_WIDE_INT size;
+ tree base;
- /* A VAR_DECL, for any sub-element we've decided to replace. */
- tree replacement;
+ /* Expression. */
+ tree expr;
+ /* Type. */
+ tree type;
- /* The number of times the element is referenced as a whole. I.e.
- given "a.b.c", this would be incremented for C, but not for A or B. */
- unsigned int n_uses;
+ /* Next group representative for this aggregate. */
+ struct access *next_grp;
+
+ /* Pointer to the group representative. Pointer to itself if the struct is
+ the representative. */
+ struct access *group_representative;
+
+ /* If this access has any children (in terms of the definition above), this
+ points to the first one. */
+ struct access *first_child;
+
+ /* Pointer to the next sibling in the access tree as described above. */
+ struct access *next_sibling;
+
+ /* Pointers to the first and last element in the linked list of assign
+ links. */
+ struct assign_link *first_link, *last_link;
+
+ /* Pointer to the next access in the work queue. */
+ struct access *next_queued;
+
+ /* Replacement variable for this access "region." Never to be accessed
+ directly, always only by the means of get_access_replacement() and only
+ when grp_to_be_replaced flag is set. */
+ tree replacement_decl;
+
+ /* Is this particular access write access? */
+ unsigned write : 1;
+
+ /* Is this access currently in the work queue? */
+ unsigned grp_queued : 1;
+ /* Does this group contain a write access? This flag is propagated down the
+ access tree. */
+ unsigned grp_write : 1;
+ /* Does this group contain a read access? This flag is propagated down the
+ access tree. */
+ unsigned grp_read : 1;
+ /* Is the subtree rooted in this access fully covered by scalar
+ replacements? */
+ unsigned grp_covered : 1;
+ /* If set to true, this access and all below it in an access tree must not be
+ scalarized. */
+ unsigned grp_unscalarizable_region : 1;
+ /* Whether data have been written to parts of the aggregate covered by this
+ access which is not to be scalarized. This flag is propagated up in the
+ access tree. */
+ unsigned grp_unscalarized_data : 1;
+ /* Does this access and/or group contain a write access through a
+ BIT_FIELD_REF? */
+ unsigned grp_partial_lhs : 1;
+
+ /* Set when a scalar replacement should be created for this variable. We do
+ the decision and creation at different places because create_tmp_var
+ cannot be called from within FOR_EACH_REFERENCED_VAR. */
+ unsigned grp_to_be_replaced : 1;
+};
- /* The number of times the element is copied to or from another
- scalarizable element. */
- unsigned int n_copies;
+typedef struct access *access_p;
- /* True if TYPE is scalar. */
- bool is_scalar;
+DEF_VEC_P (access_p);
+DEF_VEC_ALLOC_P (access_p, heap);
- /* True if this element is a group of members of its parent. */
- bool is_group;
+/* Alloc pool for allocating access structures. */
+static alloc_pool access_pool;
- /* True if we saw something about this element that prevents scalarization,
- such as non-constant indexing. */
- bool cannot_scalarize;
+/* A structure linking lhs and rhs accesses from an aggregate assignment. They
+ are used to propagate subaccesses from rhs to lhs as long as they don't
+ conflict with what is already there. */
+struct assign_link
+{
+ struct access *lacc, *racc;
+ struct assign_link *next;
+};
- /* True if we've decided that structure-to-structure assignment
- should happen via memcpy and not per-element. */
- bool use_block_copy;
+/* Alloc pool for allocating assign link structures. */
+static alloc_pool link_pool;
- /* True if everything under this element has been marked TREE_NO_WARNING. */
- bool all_no_warning;
+/* Base (tree) -> Vector (VEC(access_p,heap) *) map. */
+static struct pointer_map_t *base_access_vec;
- /* A flag for use with/after random access traversals. */
- bool visited;
+/* Bitmap of bases (candidates). */
+static bitmap candidate_bitmap;
+/* Obstack for creation of fancy names. */
+static struct obstack name_obstack;
- /* True if there is BIT_FIELD_REF on the lhs with a vector. */
- bool is_vector_lhs;
+/* Head of a linked list of accesses that need to have its subaccesses
+ propagated to their assignment counterparts. */
+static struct access *work_queue_head;
- /* 1 if the element is a field that is part of a block, 2 if the field
- is the block itself, 0 if it's neither. */
- char in_bitfld_block;
-};
+/* Dump contents of ACCESS to file F in a human friendly way. If GRP is true,
+ representative fields are dumped, otherwise those which only describe the
+ individual access are. */
-#define IS_ELEMENT_FOR_GROUP(ELEMENT) (TREE_CODE (ELEMENT) == RANGE_EXPR)
+static void
+dump_access (FILE *f, struct access *access, bool grp)
+{
+ fprintf (f, "access { ");
+ fprintf (f, "base = (%d)'", DECL_UID (access->base));
+ print_generic_expr (f, access->base, 0);
+ fprintf (f, "', offset = " HOST_WIDE_INT_PRINT_DEC, access->offset);
+ fprintf (f, ", size = " HOST_WIDE_INT_PRINT_DEC, access->size);
+ fprintf (f, ", expr = ");
+ print_generic_expr (f, access->expr, 0);
+ fprintf (f, ", type = ");
+ print_generic_expr (f, access->type, 0);
+ if (grp)
+ fprintf (f, ", grp_write = %d, grp_read = %d, grp_covered = %d, "
+ "grp_unscalarizable_region = %d, grp_unscalarized_data = %d, "
+ "grp_partial_lhs = %d, grp_to_be_replaced = %d\n",
+ access->grp_write, access->grp_read, access->grp_covered,
+ access->grp_unscalarizable_region, access->grp_unscalarized_data,
+ access->grp_partial_lhs, access->grp_to_be_replaced);
+ else
+ fprintf (f, ", write = %d, grp_partial_lhs = %d\n", access->write,
+ access->grp_partial_lhs);
+}
-#define FOR_EACH_ACTUAL_CHILD(CHILD, ELT) \
- for ((CHILD) = (ELT)->is_group \
- ? next_child_for_group (NULL, (ELT)) \
- : (ELT)->children; \
- (CHILD); \
- (CHILD) = (ELT)->is_group \
- ? next_child_for_group ((CHILD), (ELT)) \
- : (CHILD)->sibling)
+/* Dump a subtree rooted in ACCESS to file F, indent by LEVEL. */
-/* Helper function for above macro. Return next child in group. */
-static struct sra_elt *
-next_child_for_group (struct sra_elt *child, struct sra_elt *group)
+static void
+dump_access_tree_1 (FILE *f, struct access *access, int level)
{
- gcc_assert (group->is_group);
-
- /* Find the next child in the parent. */
- if (child)
- child = child->sibling;
- else
- child = group->parent->children;
-
- /* Skip siblings that do not belong to the group. */
- while (child)
+ do
{
- tree g_elt = group->element;
- if (TREE_CODE (g_elt) == RANGE_EXPR)
- {
- if (!tree_int_cst_lt (child->element, TREE_OPERAND (g_elt, 0))
- && !tree_int_cst_lt (TREE_OPERAND (g_elt, 1), child->element))
- break;
- }
- else
- gcc_unreachable ();
-
- child = child->sibling;
- }
-
- return child;
-}
+ int i;
-/* Random access to the child of a parent is performed by hashing.
- This prevents quadratic behavior, and allows SRA to function
- reasonably on larger records. */
-static htab_t sra_map;
+ for (i = 0; i < level; i++)
+ fputs ("* ", dump_file);
-/* All structures are allocated out of the following obstack. */
-static struct obstack sra_obstack;
+ dump_access (f, access, true);
-/* Debugging functions. */
-static void dump_sra_elt_name (FILE *, struct sra_elt *);
-extern void debug_sra_elt_name (struct sra_elt *);
+ if (access->first_child)
+ dump_access_tree_1 (f, access->first_child, level + 1);
-/* Forward declarations. */
-static tree generate_element_ref (struct sra_elt *);
-static gimple_seq sra_build_assignment (tree dst, tree src);
-static void mark_all_v_defs_seq (gimple_seq);
+ access = access->next_sibling;
+ }
+ while (access);
+}
-
-/* Return true if DECL is an SRA candidate. */
+/* Dump all access trees for a variable, given the pointer to the first root in
+ ACCESS. */
-static bool
-is_sra_candidate_decl (tree decl)
+static void
+dump_access_tree (FILE *f, struct access *access)
{
- return DECL_P (decl) && bitmap_bit_p (sra_candidates, DECL_UID (decl));
+ for (; access; access = access->next_grp)
+ dump_access_tree_1 (f, access, 0);
}
-/* Return true if TYPE is a scalar type. */
+/* Return true iff ACC is non-NULL and has subaccesses. */
-static bool
-is_sra_scalar_type (tree type)
+static inline bool
+access_has_children_p (struct access *acc)
{
- enum tree_code code = TREE_CODE (type);
- return (code == INTEGER_TYPE || code == REAL_TYPE || code == VECTOR_TYPE
- || code == FIXED_POINT_TYPE
- || code == ENUMERAL_TYPE || code == BOOLEAN_TYPE
- || code == POINTER_TYPE || code == OFFSET_TYPE
- || code == REFERENCE_TYPE);
+ return acc && acc->first_child;
}
-/* Return true if TYPE can be decomposed into a set of independent variables.
-
- Note that this doesn't imply that all elements of TYPE can be
- instantiated, just that if we decide to break up the type into
- separate pieces that it can be done. */
+/* Return a vector of pointers to accesses for the variable given in BASE or
+ NULL if there is none. */
-static bool
-sra_type_can_be_decomposed_p (tree type)
+static VEC (access_p, heap) *
+get_base_access_vector (tree base)
{
- unsigned int cache = TYPE_UID (TYPE_MAIN_VARIANT (type)) * 2;
- tree t;
+ void **slot;
- /* Avoid searching the same type twice. */
- if (bitmap_bit_p (sra_type_decomp_cache, cache+0))
- return true;
- if (bitmap_bit_p (sra_type_decomp_cache, cache+1))
- return false;
+ slot = pointer_map_contains (base_access_vec, base);
+ if (!slot)
+ return NULL;
+ else
+ return *(VEC (access_p, heap) **) slot;
+}
- /* The type must have a definite nonzero size. */
- if (TYPE_SIZE (type) == NULL || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
- || integer_zerop (TYPE_SIZE (type)))
- goto fail;
+/* Find an access with required OFFSET and SIZE in a subtree of accesses rooted
+ in ACCESS. Return NULL if it cannot be found. */
- /* The type must be a non-union aggregate. */
- switch (TREE_CODE (type))
+static struct access *
+find_access_in_subtree (struct access *access, HOST_WIDE_INT offset,
+ HOST_WIDE_INT size)
+{
+ while (access && (access->offset != offset || access->size != size))
{
- case RECORD_TYPE:
- {
- bool saw_one_field = false;
+ struct access *child = access->first_child;
- for (t = TYPE_FIELDS (type); t ; t = TREE_CHAIN (t))
- if (TREE_CODE (t) == FIELD_DECL)
- {
- /* Reject incorrectly represented bit fields. */
- if (DECL_BIT_FIELD (t)
- && INTEGRAL_TYPE_P (TREE_TYPE (t))
- && (tree_low_cst (DECL_SIZE (t), 1)
- != TYPE_PRECISION (TREE_TYPE (t))))
- goto fail;
-
- /* And volatile fields. */
- if (TREE_THIS_VOLATILE (t))
- goto fail;
-
- saw_one_field = true;
- }
-
- /* Record types must have at least one field. */
- if (!saw_one_field)
- goto fail;
- }
- break;
+ while (child && (child->offset + child->size <= offset))
+ child = child->next_sibling;
+ access = child;
+ }
- case ARRAY_TYPE:
- /* Array types must have a fixed lower and upper bound. */
- t = TYPE_DOMAIN (type);
- if (t == NULL)
- goto fail;
- if (TYPE_MIN_VALUE (t) == NULL || !TREE_CONSTANT (TYPE_MIN_VALUE (t)))
- goto fail;
- if (TYPE_MAX_VALUE (t) == NULL || !TREE_CONSTANT (TYPE_MAX_VALUE (t)))
- goto fail;
- break;
+ return access;
+}
- case COMPLEX_TYPE:
- break;
+/* Return the first group representative for DECL or NULL if none exists. */
- default:
- goto fail;
- }
+static struct access *
+get_first_repr_for_decl (tree base)
+{
+ VEC (access_p, heap) *access_vec;
- bitmap_set_bit (sra_type_decomp_cache, cache+0);
- return true;
+ access_vec = get_base_access_vector (base);
+ if (!access_vec)
+ return NULL;
- fail:
- bitmap_set_bit (sra_type_decomp_cache, cache+1);
- return false;
+ return VEC_index (access_p, access_vec, 0);
}
-/* Returns true if the TYPE is one of the available va_list types.
- Otherwise it returns false.
- Note, that for multiple calling conventions there can be more
- than just one va_list type present. */
+/* Find an access representative for the variable BASE and given OFFSET and
+ SIZE. Requires that access trees have already been built. Return NULL if
+ it cannot be found. */
-static bool
-is_va_list_type (tree type)
+static struct access *
+get_var_base_offset_size_access (tree base, HOST_WIDE_INT offset,
+ HOST_WIDE_INT size)
{
- tree h;
+ struct access *access;
- if (type == NULL_TREE)
- return false;
- h = targetm.canonical_va_list_type (type);
- if (h == NULL_TREE)
- return false;
- if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (h))
- return true;
- return false;
-}
+ access = get_first_repr_for_decl (base);
+ while (access && (access->offset + access->size <= offset))
+ access = access->next_grp;
+ if (!access)
+ return NULL;
-/* Return true if DECL can be decomposed into a set of independent
- (though not necessarily scalar) variables. */
+ return find_access_in_subtree (access, offset, size);
+}
-static bool
-decl_can_be_decomposed_p (tree var)
+/* Add LINK to the linked list of assign links of RACC. */
+static void
+add_link_to_rhs (struct access *racc, struct assign_link *link)
{
- /* Early out for scalars. */
- if (is_sra_scalar_type (TREE_TYPE (var)))
- return false;
+ gcc_assert (link->racc == racc);
- /* The variable must not be aliased. */
- if (!is_gimple_non_addressable (var))
+ if (!racc->first_link)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Cannot scalarize variable ");
- print_generic_expr (dump_file, var, dump_flags);
- fprintf (dump_file, " because it must live in memory\n");
- }
- return false;
+ gcc_assert (!racc->last_link);
+ racc->first_link = link;
}
+ else
+ racc->last_link->next = link;
+
+ racc->last_link = link;
+ link->next = NULL;
+}
- /* The variable must not be volatile. */
- if (TREE_THIS_VOLATILE (var))
+/* Move all link structures in their linked list in OLD_RACC to the linked list
+ in NEW_RACC. */
+static void
+relink_to_new_repr (struct access *new_racc, struct access *old_racc)
+{
+ if (!old_racc->first_link)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Cannot scalarize variable ");
- print_generic_expr (dump_file, var, dump_flags);
- fprintf (dump_file, " because it is declared volatile\n");
- }
- return false;
+ gcc_assert (!old_racc->last_link);
+ return;
}
- /* We must be able to decompose the variable's type. */
- if (!sra_type_can_be_decomposed_p (TREE_TYPE (var)))
+ if (new_racc->first_link)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- {
- fprintf (dump_file, "Cannot scalarize variable ");
- print_generic_expr (dump_file, var, dump_flags);
- fprintf (dump_file, " because its type cannot be decomposed\n");
- }
- return false;
- }
+ gcc_assert (!new_racc->last_link->next);
+ gcc_assert (!old_racc->last_link || !old_racc->last_link->next);
- /* HACK: if we decompose a va_list_type_node before inlining, then we'll
- confuse tree-stdarg.c, and we won't be able to figure out which and
- how many arguments are accessed. This really should be improved in
- tree-stdarg.c, as the decomposition is truly a win. This could also
- be fixed if the stdarg pass ran early, but this can't be done until
- we've aliasing information early too. See PR 30791. */
- if (early_sra && is_va_list_type (TREE_TYPE (var)))
- return false;
+ new_racc->last_link->next = old_racc->first_link;
+ new_racc->last_link = old_racc->last_link;
+ }
+ else
+ {
+ gcc_assert (!new_racc->last_link);
- return true;
+ new_racc->first_link = old_racc->first_link;
+ new_racc->last_link = old_racc->last_link;
+ }
+ old_racc->first_link = old_racc->last_link = NULL;
}
-/* Return true if TYPE can be *completely* decomposed into scalars. */
+/* Add ACCESS to the work queue (which is actually a stack). */
-static bool
-type_can_instantiate_all_elements (tree type)
+static void
+add_access_to_work_queue (struct access *access)
{
- if (is_sra_scalar_type (type))
- return true;
- if (!sra_type_can_be_decomposed_p (type))
- return false;
-
- switch (TREE_CODE (type))
+ if (!access->grp_queued)
{
- case RECORD_TYPE:
- {
- unsigned int cache = TYPE_UID (TYPE_MAIN_VARIANT (type)) * 2;
- tree f;
+ gcc_assert (!access->next_queued);
+ access->next_queued = work_queue_head;
+ access->grp_queued = 1;
+ work_queue_head = access;
+ }
+}
- if (bitmap_bit_p (sra_type_inst_cache, cache+0))
- return true;
- if (bitmap_bit_p (sra_type_inst_cache, cache+1))
- return false;
+/* Pop an access from the work queue, and return it, assuming there is one. */
- for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
- if (TREE_CODE (f) == FIELD_DECL)
- {
- if (!type_can_instantiate_all_elements (TREE_TYPE (f)))
- {
- bitmap_set_bit (sra_type_inst_cache, cache+1);
- return false;
- }
- }
+static struct access *
+pop_access_from_work_queue (void)
+{
+ struct access *access = work_queue_head;
- bitmap_set_bit (sra_type_inst_cache, cache+0);
- return true;
- }
+ work_queue_head = access->next_queued;
+ access->next_queued = NULL;
+ access->grp_queued = 0;
+ return access;
+}
- case ARRAY_TYPE:
- return type_can_instantiate_all_elements (TREE_TYPE (type));
- case COMPLEX_TYPE:
- return true;
+/* Allocate necessary structures. */
- default:
- gcc_unreachable ();
- }
+static void
+sra_initialize (void)
+{
+ candidate_bitmap = BITMAP_ALLOC (NULL);
+ gcc_obstack_init (&name_obstack);
+ access_pool = create_alloc_pool ("SRA accesses", sizeof (struct access), 16);
+ link_pool = create_alloc_pool ("SRA links", sizeof (struct assign_link), 16);
+ base_access_vec = pointer_map_create ();
}
-/* Test whether ELT or some sub-element cannot be scalarized. */
+/* Hook fed to pointer_map_traverse, deallocate stored vectors. */
static bool
-can_completely_scalarize_p (struct sra_elt *elt)
+delete_base_accesses (const void *key ATTRIBUTE_UNUSED, void **value,
+ void *data ATTRIBUTE_UNUSED)
{
- struct sra_elt *c;
-
- if (elt->cannot_scalarize)
- return false;
-
- for (c = elt->children; c; c = c->sibling)
- if (!can_completely_scalarize_p (c))
- return false;
-
- for (c = elt->groups; c; c = c->sibling)
- if (!can_completely_scalarize_p (c))
- return false;
+ VEC (access_p, heap) *access_vec;
+ access_vec = (VEC (access_p, heap) *) *value;
+ VEC_free (access_p, heap, access_vec);
return true;
}
-
-/* A simplified tree hashing algorithm that only handles the types of
- trees we expect to find in sra_elt->element. */
+/* Deallocate all general structures. */
-static hashval_t
-sra_hash_tree (tree t)
+static void
+sra_deinitialize (void)
{
- hashval_t h;
-
- switch (TREE_CODE (t))
- {
- case VAR_DECL:
- case PARM_DECL:
- case RESULT_DECL:
- h = DECL_UID (t);
- break;
-
- case INTEGER_CST:
- h = TREE_INT_CST_LOW (t) ^ TREE_INT_CST_HIGH (t);
- break;
-
- case RANGE_EXPR:
- h = iterative_hash_expr (TREE_OPERAND (t, 0), 0);
- h = iterative_hash_expr (TREE_OPERAND (t, 1), h);
- break;
+ BITMAP_FREE (candidate_bitmap);
+ free_alloc_pool (access_pool);
+ free_alloc_pool (link_pool);
+ obstack_free (&name_obstack, NULL);
- case FIELD_DECL:
- /* We can have types that are compatible, but have different member
- lists, so we can't hash fields by ID. Use offsets instead. */
- h = iterative_hash_expr (DECL_FIELD_OFFSET (t), 0);
- h = iterative_hash_expr (DECL_FIELD_BIT_OFFSET (t), h);
- break;
+ pointer_map_traverse (base_access_vec, delete_base_accesses, NULL);
+ pointer_map_destroy (base_access_vec);
+}
- case BIT_FIELD_REF:
- /* Don't take operand 0 into account, that's our parent. */
- h = iterative_hash_expr (TREE_OPERAND (t, 1), 0);
- h = iterative_hash_expr (TREE_OPERAND (t, 2), h);
- break;
+/* Remove DECL from candidates for SRA and write REASON to the dump file if
+ there is one. */
+static void
+disqualify_candidate (tree decl, const char *reason)
+{
+ bitmap_clear_bit (candidate_bitmap, DECL_UID (decl));
- default:
- gcc_unreachable ();
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "! Disqualifying ");
+ print_generic_expr (dump_file, decl, 0);
+ fprintf (dump_file, " - %s\n", reason);
}
-
- return h;
}
-/* Hash function for type SRA_PAIR. */
+/* Return true iff the type contains a field or an element which does not allow
+ scalarization. */
-static hashval_t
-sra_elt_hash (const void *x)
+static bool
+type_internals_preclude_sra_p (tree type)
{
- const struct sra_elt *const e = (const struct sra_elt *) x;
- const struct sra_elt *p;
- hashval_t h;
-
- h = sra_hash_tree (e->element);
-
- /* Take into account everything except bitfield blocks back up the
- chain. Given that chain lengths are rarely very long, this
- should be acceptable. If we truly identify this as a performance
- problem, it should work to hash the pointer value
- "e->parent". */
- for (p = e->parent; p ; p = p->parent)
- if (!p->in_bitfld_block)
- h = (h * 65521) ^ sra_hash_tree (p->element);
-
- return h;
-}
+ tree fld;
+ tree et;
-/* Equality function for type SRA_PAIR. */
-
-static int
-sra_elt_eq (const void *x, const void *y)
-{
- const struct sra_elt *const a = (const struct sra_elt *) x;
- const struct sra_elt *const b = (const struct sra_elt *) y;
- tree ae, be;
- const struct sra_elt *ap = a->parent;
- const struct sra_elt *bp = b->parent;
-
- if (ap)
- while (ap->in_bitfld_block)
- ap = ap->parent;
- if (bp)
- while (bp->in_bitfld_block)
- bp = bp->parent;
-
- if (ap != bp)
- return false;
+ switch (TREE_CODE (type))
+ {
+ case RECORD_TYPE:
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
+ if (TREE_CODE (fld) == FIELD_DECL)
+ {
+ tree ft = TREE_TYPE (fld);
- ae = a->element;
- be = b->element;
+ if (TREE_THIS_VOLATILE (fld)
+ || !DECL_FIELD_OFFSET (fld) || !DECL_SIZE (fld)
+ || !host_integerp (DECL_FIELD_OFFSET (fld), 1)
+ || !host_integerp (DECL_SIZE (fld), 1))
+ return true;
- if (ae == be)
- return true;
- if (TREE_CODE (ae) != TREE_CODE (be))
- return false;
+ if (AGGREGATE_TYPE_P (ft)
+ && type_internals_preclude_sra_p (ft))
+ return true;
+ }
- switch (TREE_CODE (ae))
- {
- case VAR_DECL:
- case PARM_DECL:
- case RESULT_DECL:
- /* These are all pointer unique. */
return false;
- case INTEGER_CST:
- /* Integers are not pointer unique, so compare their values. */
- return tree_int_cst_equal (ae, be);
-
- case RANGE_EXPR:
- return
- tree_int_cst_equal (TREE_OPERAND (ae, 0), TREE_OPERAND (be, 0))
- && tree_int_cst_equal (TREE_OPERAND (ae, 1), TREE_OPERAND (be, 1));
+ case ARRAY_TYPE:
+ et = TREE_TYPE (type);
- case FIELD_DECL:
- /* Fields are unique within a record, but not between
- compatible records. */
- if (DECL_FIELD_CONTEXT (ae) == DECL_FIELD_CONTEXT (be))
+ if (AGGREGATE_TYPE_P (et))
+ return type_internals_preclude_sra_p (et);
+ else
return false;
- return fields_compatible_p (ae, be);
-
- case BIT_FIELD_REF:
- return
- tree_int_cst_equal (TREE_OPERAND (ae, 1), TREE_OPERAND (be, 1))
- && tree_int_cst_equal (TREE_OPERAND (ae, 2), TREE_OPERAND (be, 2));
default:
- gcc_unreachable ();
+ return false;
}
}
-/* Create or return the SRA_ELT structure for CHILD in PARENT. PARENT
- may be null, in which case CHILD must be a DECL. */
+/* Create and insert access for EXPR. Return created access, or NULL if it is
+ not possible. */
-static struct sra_elt *
-lookup_element (struct sra_elt *parent, tree child, tree type,
- enum insert_option insert)
+static struct access *
+create_access (tree expr, bool write)
{
- struct sra_elt dummy;
- struct sra_elt **slot;
- struct sra_elt *elt;
+ struct access *access;
+ void **slot;
+ VEC (access_p,heap) *vec;
+ HOST_WIDE_INT offset, size, max_size;
+ tree base = expr;
+ bool unscalarizable_region = false;
- if (parent)
- dummy.parent = parent->is_group ? parent->parent : parent;
- else
- dummy.parent = NULL;
- dummy.element = child;
+ base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
- slot = (struct sra_elt **) htab_find_slot (sra_map, &dummy, insert);
- if (!slot && insert == NO_INSERT)
+ if (!DECL_P (base) || !bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
return NULL;
- elt = *slot;
- if (!elt && insert == INSERT)
+ if (size != max_size)
{
- *slot = elt = XOBNEW (&sra_obstack, struct sra_elt);
- memset (elt, 0, sizeof (*elt));
-
- elt->parent = parent;
- elt->element = child;
- elt->type = type;
- elt->is_scalar = is_sra_scalar_type (type);
-
- if (parent)
- {
- if (IS_ELEMENT_FOR_GROUP (elt->element))
- {
- elt->is_group = true;
- elt->sibling = parent->groups;
- parent->groups = elt;
- }
- else
- {
- elt->sibling = parent->children;
- parent->children = elt;
- }
- }
-
- /* If this is a parameter, then if we want to scalarize, we have
- one copy from the true function parameter. Count it now. */
- if (TREE_CODE (child) == PARM_DECL)
- {
- elt->n_copies = 1;
- bitmap_set_bit (needs_copy_in, DECL_UID (child));
- }
+ size = max_size;
+ unscalarizable_region = true;
}
- return elt;
-}
-
-/* Create or return the SRA_ELT structure for EXPR if the expression
- refers to a scalarizable variable. */
-
-static struct sra_elt *
-maybe_lookup_element_for_expr (tree expr)
-{
- struct sra_elt *elt;
- tree child;
-
- switch (TREE_CODE (expr))
+ if (size < 0)
{
- case VAR_DECL:
- case PARM_DECL:
- case RESULT_DECL:
- if (is_sra_candidate_decl (expr))
- return lookup_element (NULL, expr, TREE_TYPE (expr), INSERT);
- return NULL;
-
- case ARRAY_REF:
- /* We can't scalarize variable array indices. */
- if (in_array_bounds_p (expr))
- child = TREE_OPERAND (expr, 1);
- else
- return NULL;
- break;
-
- case ARRAY_RANGE_REF:
- /* We can't scalarize variable array indices. */
- if (range_in_array_bounds_p (expr))
- {
- tree domain = TYPE_DOMAIN (TREE_TYPE (expr));
- child = build2 (RANGE_EXPR, integer_type_node,
- TYPE_MIN_VALUE (domain), TYPE_MAX_VALUE (domain));
- }
- else
- return NULL;
- break;
-
- case COMPONENT_REF:
- {
- tree type = TREE_TYPE (TREE_OPERAND (expr, 0));
- /* Don't look through unions. */
- if (TREE_CODE (type) != RECORD_TYPE)
- return NULL;
- /* Neither through variable-sized records. */
- if (TYPE_SIZE (type) == NULL_TREE
- || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
- return NULL;
- child = TREE_OPERAND (expr, 1);
- }
- break;
-
- case REALPART_EXPR:
- child = integer_zero_node;
- break;
- case IMAGPART_EXPR:
- child = integer_one_node;
- break;
-
- default:
+ disqualify_candidate (base, "Encountered an unconstrained access.");
return NULL;
}
- elt = maybe_lookup_element_for_expr (TREE_OPERAND (expr, 0));
- if (elt)
- return lookup_element (elt, child, TREE_TYPE (expr), INSERT);
- return NULL;
-}
+ access = (struct access *) pool_alloc (access_pool);
+ memset (access, 0, sizeof (struct access));
-
-/* Functions to walk just enough of the tree to see all scalarizable
- references, and categorize them. */
+ access->base = base;
+ access->offset = offset;
+ access->size = size;
+ access->expr = expr;
+ access->type = TREE_TYPE (expr);
+ access->write = write;
+ access->grp_unscalarizable_region = unscalarizable_region;
-/* A set of callbacks for phases 2 and 4. They'll be invoked for the
- various kinds of references seen. In all cases, *GSI is an iterator
- pointing to the statement being processed. */
-struct sra_walk_fns
-{
- /* Invoked when ELT is required as a unit. Note that ELT might refer to
- a leaf node, in which case this is a simple scalar reference. *EXPR_P
- points to the location of the expression. IS_OUTPUT is true if this
- is a left-hand-side reference. USE_ALL is true if we saw something we
- couldn't quite identify and had to force the use of the entire object. */
- void (*use) (struct sra_elt *elt, tree *expr_p,
- gimple_stmt_iterator *gsi, bool is_output, bool use_all);
-
- /* Invoked when we have a copy between two scalarizable references. */
- void (*copy) (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt,
- gimple_stmt_iterator *gsi);
-
- /* Invoked when ELT is initialized from a constant. VALUE may be NULL,
- in which case it should be treated as an empty CONSTRUCTOR. */
- void (*init) (struct sra_elt *elt, tree value, gimple_stmt_iterator *gsi);
-
- /* Invoked when we have a copy between one scalarizable reference ELT
- and one non-scalarizable reference OTHER without side-effects.
- IS_OUTPUT is true if ELT is on the left-hand side. */
- void (*ldst) (struct sra_elt *elt, tree other,
- gimple_stmt_iterator *gsi, bool is_output);
-
- /* True during phase 2, false during phase 4. */
- /* ??? This is a hack. */
- bool initial_scan;
-};
-
-#ifdef ENABLE_CHECKING
-/* Invoked via walk_tree, if *TP contains a candidate decl, return it. */
+ slot = pointer_map_contains (base_access_vec, base);
+ if (slot)
+ vec = (VEC (access_p, heap) *) *slot;
+ else
+ vec = VEC_alloc (access_p, heap, 32);
-static tree
-sra_find_candidate_decl (tree *tp, int *walk_subtrees,
- void *data ATTRIBUTE_UNUSED)
-{
- tree t = *tp;
- enum tree_code code = TREE_CODE (t);
+ VEC_safe_push (access_p, heap, vec, access);
- if (code == VAR_DECL || code == PARM_DECL || code == RESULT_DECL)
- {
- *walk_subtrees = 0;
- if (is_sra_candidate_decl (t))
- return t;
- }
- else if (TYPE_P (t))
- *walk_subtrees = 0;
+ *((struct VEC (access_p,heap) **)
+ pointer_map_insert (base_access_vec, base)) = vec;
- return NULL;
+ return access;
}
-#endif
-
-/* Walk most expressions looking for a scalarizable aggregate.
- If we find one, invoke FNS->USE. */
-
-static void
-sra_walk_expr (tree *expr_p, gimple_stmt_iterator *gsi, bool is_output,
- const struct sra_walk_fns *fns)
-{
- tree expr = *expr_p;
- tree inner = expr;
- bool disable_scalarization = false;
- bool use_all_p = false;
-
- /* We're looking to collect a reference expression between EXPR and INNER,
- such that INNER is a scalarizable decl and all other nodes through EXPR
- are references that we can scalarize. If we come across something that
- we can't scalarize, we reset EXPR. This has the effect of making it
- appear that we're referring to the larger expression as a whole. */
-
- while (1)
- switch (TREE_CODE (inner))
- {
- case VAR_DECL:
- case PARM_DECL:
- case RESULT_DECL:
- /* If there is a scalarizable decl at the bottom, then process it. */
- if (is_sra_candidate_decl (inner))
- {
- struct sra_elt *elt = maybe_lookup_element_for_expr (expr);
- if (disable_scalarization)
- elt->cannot_scalarize = true;
- else
- fns->use (elt, expr_p, gsi, is_output, use_all_p);
- }
- return;
-
- case ARRAY_REF:
- /* Non-constant index means any member may be accessed. Prevent the
- expression from being scalarized. If we were to treat this as a
- reference to the whole array, we can wind up with a single dynamic
- index reference inside a loop being overridden by several constant
- index references during loop setup. It's possible that this could
- be avoided by using dynamic usage counts based on BB trip counts
- (based on loop analysis or profiling), but that hardly seems worth
- the effort. */
- /* ??? Hack. Figure out how to push this into the scan routines
- without duplicating too much code. */
- if (!in_array_bounds_p (inner))
- {
- disable_scalarization = true;
- goto use_all;
- }
- /* ??? Are we assured that non-constant bounds and stride will have
- the same value everywhere? I don't think Fortran will... */
- if (TREE_OPERAND (inner, 2) || TREE_OPERAND (inner, 3))
- goto use_all;
- inner = TREE_OPERAND (inner, 0);
- break;
-
- case ARRAY_RANGE_REF:
- if (!range_in_array_bounds_p (inner))
- {
- disable_scalarization = true;
- goto use_all;
- }
- /* ??? See above non-constant bounds and stride . */
- if (TREE_OPERAND (inner, 2) || TREE_OPERAND (inner, 3))
- goto use_all;
- inner = TREE_OPERAND (inner, 0);
- break;
- case COMPONENT_REF:
- {
- tree type = TREE_TYPE (TREE_OPERAND (inner, 0));
- /* Don't look through unions. */
- if (TREE_CODE (type) != RECORD_TYPE)
- goto use_all;
- /* Neither through variable-sized records. */
- if (TYPE_SIZE (type) == NULL_TREE
- || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
- goto use_all;
- inner = TREE_OPERAND (inner, 0);
- }
- break;
- case REALPART_EXPR:
- case IMAGPART_EXPR:
- inner = TREE_OPERAND (inner, 0);
- break;
-
- case BIT_FIELD_REF:
- /* A bit field reference to a specific vector is scalarized but for
- ones for inputs need to be marked as used on the left hand size so
- when we scalarize it, we can mark that variable as non renamable. */
- if (is_output
- && TREE_CODE (TREE_TYPE (TREE_OPERAND (inner, 0))) == VECTOR_TYPE)
- {
- struct sra_elt *elt
- = maybe_lookup_element_for_expr (TREE_OPERAND (inner, 0));
- if (elt)
- elt->is_vector_lhs = true;
- }
-
- /* A bit field reference (access to *multiple* fields simultaneously)
- is not currently scalarized. Consider this an access to the full
- outer element, to which walk_tree will bring us next. */
- goto use_all;
-
- CASE_CONVERT:
- /* Similarly, a nop explicitly wants to look at an object in a
- type other than the one we've scalarized. */
- goto use_all;
-
- case VIEW_CONVERT_EXPR:
- /* Likewise for a view conversion, but with an additional twist:
- it can be on the LHS and, in this case, an access to the full
- outer element would mean a killing def. So we need to punt
- if we haven't already a full access to the current element,
- because we cannot pretend to have a killing def if we only
- have a partial access at some level. */
- if (is_output && !use_all_p && inner != expr)
- disable_scalarization = true;
- goto use_all;
-
- case WITH_SIZE_EXPR:
- /* This is a transparent wrapper. The entire inner expression really
- is being used. */
- goto use_all;
-
- use_all:
- expr_p = &TREE_OPERAND (inner, 0);
- inner = expr = *expr_p;
- use_all_p = true;
- break;
-
- default:
-#ifdef ENABLE_CHECKING
- /* Validate that we're not missing any references. */
- gcc_assert (!walk_tree (&inner, sra_find_candidate_decl, NULL, NULL));
-#endif
- return;
- }
-}
-
-/* Walk the arguments of a GIMPLE_CALL looking for scalarizable aggregates.
- If we find one, invoke FNS->USE. */
+/* Search the given tree for a declaration by skipping handled components and
+ exclude it from the candidates. */
static void
-sra_walk_gimple_call (gimple stmt, gimple_stmt_iterator *gsi,
- const struct sra_walk_fns *fns)
+disqualify_base_of_expr (tree t, const char *reason)
{
- int i;
- int nargs = gimple_call_num_args (stmt);
+ while (handled_component_p (t))
+ t = TREE_OPERAND (t, 0);
- for (i = 0; i < nargs; i++)
- sra_walk_expr (gimple_call_arg_ptr (stmt, i), gsi, false, fns);
-
- if (gimple_call_lhs (stmt))
- sra_walk_expr (gimple_call_lhs_ptr (stmt), gsi, true, fns);
-}
-
-/* Walk the inputs and outputs of a GIMPLE_ASM looking for scalarizable
- aggregates. If we find one, invoke FNS->USE. */
-
-static void
-sra_walk_gimple_asm (gimple stmt, gimple_stmt_iterator *gsi,
- const struct sra_walk_fns *fns)
-{
- size_t i;
- for (i = 0; i < gimple_asm_ninputs (stmt); i++)
- sra_walk_expr (&TREE_VALUE (gimple_asm_input_op (stmt, i)), gsi, false, fns);
- for (i = 0; i < gimple_asm_noutputs (stmt); i++)
- sra_walk_expr (&TREE_VALUE (gimple_asm_output_op (stmt, i)), gsi, true, fns);
+ if (DECL_P (t))
+ disqualify_candidate (t, reason);
}
-/* Walk a GIMPLE_ASSIGN and categorize the assignment appropriately. */
+/* Scan expression EXPR and create access structures for all accesses to
+ candidates for scalarization. Return the created access or NULL if none is
+ created. */
-static void
-sra_walk_gimple_assign (gimple stmt, gimple_stmt_iterator *gsi,
- const struct sra_walk_fns *fns)
+static struct access *
+build_access_from_expr_1 (tree *expr_ptr, bool write)
{
- struct sra_elt *lhs_elt = NULL, *rhs_elt = NULL;
- tree lhs, rhs;
+ struct access *ret = NULL;
+ tree expr = *expr_ptr;
+ bool partial_ref;
- /* If there is more than 1 element on the RHS, only walk the lhs. */
- if (!gimple_assign_single_p (stmt))
+ if (TREE_CODE (expr) == BIT_FIELD_REF
+ || TREE_CODE (expr) == IMAGPART_EXPR
+ || TREE_CODE (expr) == REALPART_EXPR)
{
- sra_walk_expr (gimple_assign_lhs_ptr (stmt), gsi, true, fns);
- return;
+ expr = TREE_OPERAND (expr, 0);
+ partial_ref = true;
}
+ else
+ partial_ref = false;
- lhs = gimple_assign_lhs (stmt);
- rhs = gimple_assign_rhs1 (stmt);
- lhs_elt = maybe_lookup_element_for_expr (lhs);
- rhs_elt = maybe_lookup_element_for_expr (rhs);
+ /* We need to dive through V_C_Es in order to get the size of its parameter
+ and not the result type. Ada produces such statements. We are also
+ capable of handling the topmost V_C_E but not any of those buried in other
+ handled components. */
+ if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
+ expr = TREE_OPERAND (expr, 0);
- /* If both sides are scalarizable, this is a COPY operation. */
- if (lhs_elt && rhs_elt)
+ if (contains_view_convert_expr_p (expr))
{
- fns->copy (lhs_elt, rhs_elt, gsi);
- return;
+ disqualify_base_of_expr (expr, "V_C_E under a different handled "
+ "component.");
+ return NULL;
}
- /* If the RHS is scalarizable, handle it. There are only two cases. */
- if (rhs_elt)
+ switch (TREE_CODE (expr))
{
- if (!rhs_elt->is_scalar && !TREE_SIDE_EFFECTS (lhs))
- fns->ldst (rhs_elt, lhs, gsi, false);
- else
- fns->use (rhs_elt, gimple_assign_rhs1_ptr (stmt), gsi, false, false);
- }
-
- /* If it isn't scalarizable, there may be scalarizable variables within, so
- check for a call or else walk the RHS to see if we need to do any
- copy-in operations. We need to do it before the LHS is scalarized so
- that the statements get inserted in the proper place, before any
- copy-out operations. */
- else
- sra_walk_expr (gimple_assign_rhs1_ptr (stmt), gsi, false, fns);
+ case VAR_DECL:
+ case PARM_DECL:
+ case RESULT_DECL:
+ case COMPONENT_REF:
+ case ARRAY_REF:
+ case ARRAY_RANGE_REF:
+ ret = create_access (expr, write);
+ break;
- /* Likewise, handle the LHS being scalarizable. We have cases similar
- to those above, but also want to handle RHS being constant. */
- if (lhs_elt)
- {
- /* If this is an assignment from a constant, or constructor, then
- we have access to all of the elements individually. Invoke INIT. */
- if (TREE_CODE (rhs) == COMPLEX_EXPR
- || TREE_CODE (rhs) == COMPLEX_CST
- || TREE_CODE (rhs) == CONSTRUCTOR)
- fns->init (lhs_elt, rhs, gsi);
-
- /* If this is an assignment from read-only memory, treat this as if
- we'd been passed the constructor directly. Invoke INIT. */
- else if (TREE_CODE (rhs) == VAR_DECL
- && TREE_STATIC (rhs)
- && !DECL_EXTERNAL (rhs)
- && TREE_READONLY (rhs)
- && targetm.binds_local_p (rhs))
- fns->init (lhs_elt, DECL_INITIAL (rhs), gsi);
-
- /* If this is a copy from a non-scalarizable lvalue, invoke LDST.
- The lvalue requirement prevents us from trying to directly scalarize
- the result of a function call. Which would result in trying to call
- the function multiple times, and other evil things. */
- else if (!lhs_elt->is_scalar
- && !TREE_SIDE_EFFECTS (rhs) && is_gimple_addressable (rhs))
- fns->ldst (lhs_elt, rhs, gsi, true);
-
- /* Otherwise we're being used in some context that requires the
- aggregate to be seen as a whole. Invoke USE. */
- else
- fns->use (lhs_elt, gimple_assign_lhs_ptr (stmt), gsi, true, false);
+ default:
+ break;
}
- /* Similarly to above, LHS_ELT being null only means that the LHS as a
- whole is not a scalarizable reference. There may be occurrences of
- scalarizable variables within, which implies a USE. */
- else
- sra_walk_expr (gimple_assign_lhs_ptr (stmt), gsi, true, fns);
+ if (write && partial_ref && ret)
+ ret->grp_partial_lhs = 1;
+
+ return ret;
}
-/* Entry point to the walk functions. Search the entire function,
- invoking the callbacks in FNS on each of the references to
- scalarizable variables. */
+/* Callback of scan_function. Scan expression EXPR and create access
+ structures for all accesses to candidates for scalarization. Return true if
+ any access has been inserted. */
-static void
-sra_walk_function (const struct sra_walk_fns *fns)
+static bool
+build_access_from_expr (tree *expr_ptr,
+ gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED, bool write,
+ void *data ATTRIBUTE_UNUSED)
{
- basic_block bb;
- gimple_stmt_iterator si, ni;
-
- /* ??? Phase 4 could derive some benefit to walking the function in
- dominator tree order. */
-
- FOR_EACH_BB (bb)
- for (si = gsi_start_bb (bb); !gsi_end_p (si); si = ni)
- {
- gimple stmt;
-
- stmt = gsi_stmt (si);
-
- ni = si;
- gsi_next (&ni);
-
- /* If the statement does not reference memory, then it doesn't
- make any structure references that we care about. */
- if (!gimple_references_memory_p (stmt))
- continue;
-
- switch (gimple_code (stmt))
- {
- case GIMPLE_RETURN:
- /* If we have "return <retval>" then the return value is
- already exposed for our pleasure. Walk it as a USE to
- force all the components back in place for the return.
- */
- if (gimple_return_retval (stmt) == NULL_TREE)
- ;
- else
- sra_walk_expr (gimple_return_retval_ptr (stmt), &si, false,
- fns);
- break;
-
- case GIMPLE_ASSIGN:
- sra_walk_gimple_assign (stmt, &si, fns);
- break;
- case GIMPLE_CALL:
- sra_walk_gimple_call (stmt, &si, fns);
- break;
- case GIMPLE_ASM:
- sra_walk_gimple_asm (stmt, &si, fns);
- break;
-
- default:
- break;
- }
- }
+ return build_access_from_expr_1 (expr_ptr, write) != NULL;
}
-
-/* Phase One: Scan all referenced variables in the program looking for
- structures that could be decomposed. */
+/* Disqualify LHS and RHS for scalarization if STMT must end its basic block in
+ modes in which it matters, return true iff they have been disqualified. RHS
+ may be NULL, in that case ignore it. If we scalarize an aggregate in
+ intra-SRA we may need to add statements after each statement. This is not
+ possible if a statement unconditionally has to end the basic block. */
static bool
-find_candidates_for_sra (void)
+disqualify_ops_if_throwing_stmt (gimple stmt, tree lhs, tree rhs)
{
- bool any_set = false;
- tree var;
- referenced_var_iterator rvi;
-
- FOR_EACH_REFERENCED_VAR (var, rvi)
+ if (stmt_can_throw_internal (stmt) || stmt_ends_bb_p (stmt))
{
- if (decl_can_be_decomposed_p (var))
- {
- bitmap_set_bit (sra_candidates, DECL_UID (var));
- any_set = true;
- }
+ disqualify_base_of_expr (lhs, "LHS of a throwing stmt.");
+ if (rhs)
+ disqualify_base_of_expr (rhs, "RHS of a throwing stmt.");
+ return true;
}
-
- return any_set;
+ return false;
}
-
-/* Phase Two: Scan all references to scalarizable variables. Count the
- number of times they are used or copied respectively. */
-/* Callbacks to fill in SRA_WALK_FNS. Everything but USE is
- considered a copy, because we can decompose the reference such that
- the sub-elements needn't be contiguous. */
+/* Result code for scan_assign callback for scan_function. */
+enum scan_assign_result { SRA_SA_NONE, /* nothing done for the stmt */
+ SRA_SA_PROCESSED, /* stmt analyzed/changed */
+ SRA_SA_REMOVED }; /* stmt redundant and eliminated */
-static void
-scan_use (struct sra_elt *elt, tree *expr_p ATTRIBUTE_UNUSED,
- gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
- bool is_output ATTRIBUTE_UNUSED, bool use_all ATTRIBUTE_UNUSED)
-{
- elt->n_uses += 1;
-}
-static void
-scan_copy (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt,
- gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED)
-{
- lhs_elt->n_copies += 1;
- rhs_elt->n_copies += 1;
-}
-
-static void
-scan_init (struct sra_elt *lhs_elt, tree rhs ATTRIBUTE_UNUSED,
- gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED)
-{
- lhs_elt->n_copies += 1;
-}
+/* Callback of scan_function. Scan expressions occuring in the statement
+ pointed to by STMT_EXPR, create access structures for all accesses to
+ candidates for scalarization and remove those candidates which occur in
+ statements or expressions that prevent them from being split apart. Return
+ true if any access has been inserted. */
-static void
-scan_ldst (struct sra_elt *elt, tree other ATTRIBUTE_UNUSED,
- gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
- bool is_output ATTRIBUTE_UNUSED)
+static enum scan_assign_result
+build_accesses_from_assign (gimple *stmt_ptr,
+ gimple_stmt_iterator *gsi ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
{
- elt->n_copies += 1;
-}
+ gimple stmt = *stmt_ptr;
+ tree *lhs_ptr, *rhs_ptr;
+ struct access *lacc, *racc;
-/* Dump the values we collected during the scanning phase. */
-
-static void
-scan_dump (struct sra_elt *elt)
-{
- struct sra_elt *c;
-
- dump_sra_elt_name (dump_file, elt);
- fprintf (dump_file, ": n_uses=%u n_copies=%u\n", elt->n_uses, elt->n_copies);
-
- for (c = elt->children; c ; c = c->sibling)
- scan_dump (c);
-
- for (c = elt->groups; c ; c = c->sibling)
- scan_dump (c);
-}
+ if (!gimple_assign_single_p (stmt))
+ return SRA_SA_NONE;
-/* Entry point to phase 2. Scan the entire function, building up
- scalarization data structures, recording copies and uses. */
+ lhs_ptr = gimple_assign_lhs_ptr (stmt);
+ rhs_ptr = gimple_assign_rhs1_ptr (stmt);
-static void
-scan_function (void)
-{
- static const struct sra_walk_fns fns = {
- scan_use, scan_copy, scan_init, scan_ldst, true
- };
- bitmap_iterator bi;
+ if (disqualify_ops_if_throwing_stmt (stmt, *lhs_ptr, *rhs_ptr))
+ return SRA_SA_NONE;
- sra_walk_function (&fns);
+ racc = build_access_from_expr_1 (rhs_ptr, false);
+ lacc = build_access_from_expr_1 (lhs_ptr, true);
- if (dump_file && (dump_flags & TDF_DETAILS))
+ if (lacc && racc
+ && !lacc->grp_unscalarizable_region
+ && !racc->grp_unscalarizable_region
+ && AGGREGATE_TYPE_P (TREE_TYPE (*lhs_ptr))
+ /* FIXME: Turn the following line into an assert after PR 40058 is
+ fixed. */
+ && lacc->size == racc->size
+ && useless_type_conversion_p (lacc->type, racc->type))
{
- unsigned i;
+ struct assign_link *link;
- fputs ("\nScan results:\n", dump_file);
- EXECUTE_IF_SET_IN_BITMAP (sra_candidates, 0, i, bi)
- {
- tree var = referenced_var (i);
- struct sra_elt *elt = lookup_element (NULL, var, NULL, NO_INSERT);
- if (elt)
- scan_dump (elt);
- }
- fputc ('\n', dump_file);
- }
-}
-
-/* Phase Three: Make decisions about which variables to scalarize, if any.
- All elements to be scalarized have replacement variables made for them. */
+ link = (struct assign_link *) pool_alloc (link_pool);
+ memset (link, 0, sizeof (struct assign_link));
-/* A subroutine of build_element_name. Recursively build the element
- name on the obstack. */
+ link->lacc = lacc;
+ link->racc = racc;
-static void
-build_element_name_1 (struct sra_elt *elt)
-{
- tree t;
- char buffer[32];
-
- if (elt->parent)
- {
- build_element_name_1 (elt->parent);
- obstack_1grow (&sra_obstack, '$');
-
- if (TREE_CODE (elt->parent->type) == COMPLEX_TYPE)
- {
- if (elt->element == integer_zero_node)
- obstack_grow (&sra_obstack, "real", 4);
- else
- obstack_grow (&sra_obstack, "imag", 4);
- return;
- }
+ add_link_to_rhs (racc, link);
}
- t = elt->element;
- if (TREE_CODE (t) == INTEGER_CST)
- {
- /* ??? Eh. Don't bother doing double-wide printing. */
- sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (t));
- obstack_grow (&sra_obstack, buffer, strlen (buffer));
- }
- else if (TREE_CODE (t) == BIT_FIELD_REF)
- {
- sprintf (buffer, "B" HOST_WIDE_INT_PRINT_DEC,
- tree_low_cst (TREE_OPERAND (t, 2), 1));
- obstack_grow (&sra_obstack, buffer, strlen (buffer));
- sprintf (buffer, "F" HOST_WIDE_INT_PRINT_DEC,
- tree_low_cst (TREE_OPERAND (t, 1), 1));
- obstack_grow (&sra_obstack, buffer, strlen (buffer));
- }
- else
- {
- tree name = DECL_NAME (t);
- if (name)
- obstack_grow (&sra_obstack, IDENTIFIER_POINTER (name),
- IDENTIFIER_LENGTH (name));
- else
- {
- sprintf (buffer, "D%u", DECL_UID (t));
- obstack_grow (&sra_obstack, buffer, strlen (buffer));
- }
- }
+ return (lacc || racc) ? SRA_SA_PROCESSED : SRA_SA_NONE;
}
-/* Construct a pretty variable name for an element's replacement variable.
- The name is built on the obstack. */
+/* Callback of walk_stmt_load_store_addr_ops visit_addr used to determine
+ GIMPLE_ASM operands with memory constrains which cannot be scalarized. */
-static char *
-build_element_name (struct sra_elt *elt)
+static bool
+asm_visit_addr (gimple stmt ATTRIBUTE_UNUSED, tree op,
+ void *data ATTRIBUTE_UNUSED)
{
- build_element_name_1 (elt);
- obstack_1grow (&sra_obstack, '\0');
- return XOBFINISH (&sra_obstack, char *);
+ if (DECL_P (op))
+ disqualify_candidate (op, "Non-scalarizable GIMPLE_ASM operand.");
+
+ return false;
}
-/* Insert a gimple_seq SEQ on all the outgoing edges out of BB. Note that
- if BB has more than one edge, STMT will be replicated for each edge.
- Also, abnormal edges will be ignored. */
-static void
-insert_edge_copies_seq (gimple_seq seq, basic_block bb)
-{
- edge e;
- edge_iterator ei;
- unsigned n_copies = -1;
+/* Scan function and look for interesting statements. Return true if any has
+ been found or processed, as indicated by callbacks. SCAN_EXPR is a callback
+ called on all expressions within statements except assign statements and
+ those deemed entirely unsuitable for some reason (all operands in such
+ statements and expression are removed from candidate_bitmap). SCAN_ASSIGN
+ is a callback called on all assign statements, HANDLE_SSA_DEFS is a callback
+ called on assign statements and those call statements which have a lhs and
+ it is the only callback which can be NULL. ANALYSIS_STAGE is true when
+ running in the analysis stage of a pass and thus no statement is being
+ modified. DATA is a pointer passed to all callbacks. If any single
+ callback returns true, this function also returns true, otherwise it returns
+ false. */
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (!(e->flags & EDGE_ABNORMAL))
- n_copies++;
+static bool
+scan_function (bool (*scan_expr) (tree *, gimple_stmt_iterator *, bool, void *),
+ enum scan_assign_result (*scan_assign) (gimple *,
+ gimple_stmt_iterator *,
+ void *),
+ bool (*handle_ssa_defs)(gimple, void *),
+ bool analysis_stage, void *data)
+{
+ gimple_stmt_iterator gsi;
+ basic_block bb;
+ unsigned i;
+ tree *t;
+ bool ret = false;
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (!(e->flags & EDGE_ABNORMAL))
- gsi_insert_seq_on_edge (e, n_copies-- > 0 ? gimple_seq_copy (seq) : seq);
-}
+ FOR_EACH_BB (bb)
+ {
+ bool bb_changed = false;
-/* Instantiate an element as an independent variable. */
+ gsi = gsi_start_bb (bb);
+ while (!gsi_end_p (gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ enum scan_assign_result assign_result;
+ bool any = false, deleted = false;
-static void
-instantiate_element (struct sra_elt *elt)
-{
- struct sra_elt *base_elt;
- tree var, base;
- bool nowarn = TREE_NO_WARNING (elt->element);
+ switch (gimple_code (stmt))
+ {
+ case GIMPLE_RETURN:
+ t = gimple_return_retval_ptr (stmt);
+ if (*t != NULL_TREE)
+ any |= scan_expr (t, &gsi, false, data);
+ break;
- for (base_elt = elt; base_elt->parent; base_elt = base_elt->parent)
- if (!nowarn)
- nowarn = TREE_NO_WARNING (base_elt->parent->element);
- base = base_elt->element;
+ case GIMPLE_ASSIGN:
+ assign_result = scan_assign (&stmt, &gsi, data);
+ any |= assign_result == SRA_SA_PROCESSED;
+ deleted = assign_result == SRA_SA_REMOVED;
+ if (handle_ssa_defs && assign_result != SRA_SA_REMOVED)
+ any |= handle_ssa_defs (stmt, data);
+ break;
- elt->replacement = var = make_rename_temp (elt->type, "SR");
+ case GIMPLE_CALL:
+ /* Operands must be processed before the lhs. */
+ for (i = 0; i < gimple_call_num_args (stmt); i++)
+ {
+ tree *argp = gimple_call_arg_ptr (stmt, i);
+ any |= scan_expr (argp, &gsi, false, data);
+ }
- if (DECL_P (elt->element)
- && !tree_int_cst_equal (DECL_SIZE (var), DECL_SIZE (elt->element)))
- {
- DECL_SIZE (var) = DECL_SIZE (elt->element);
- DECL_SIZE_UNIT (var) = DECL_SIZE_UNIT (elt->element);
-
- elt->in_bitfld_block = 1;
- elt->replacement = fold_build3 (BIT_FIELD_REF, elt->type, var,
- DECL_SIZE (var),
- BYTES_BIG_ENDIAN
- ? size_binop (MINUS_EXPR,
- TYPE_SIZE (elt->type),
- DECL_SIZE (var))
- : bitsize_int (0));
- }
+ if (gimple_call_lhs (stmt))
+ {
+ tree *lhs_ptr = gimple_call_lhs_ptr (stmt);
+ if (!analysis_stage
+ || !disqualify_ops_if_throwing_stmt (stmt,
+ *lhs_ptr, NULL))
+ {
+ any |= scan_expr (lhs_ptr, &gsi, true, data);
+ if (handle_ssa_defs)
+ any |= handle_ssa_defs (stmt, data);
+ }
+ }
+ break;
- /* For vectors, if used on the left hand side with BIT_FIELD_REF,
- they are not a gimple register. */
- if (TREE_CODE (TREE_TYPE (var)) == VECTOR_TYPE && elt->is_vector_lhs)
- DECL_GIMPLE_REG_P (var) = 0;
+ case GIMPLE_ASM:
- DECL_SOURCE_LOCATION (var) = DECL_SOURCE_LOCATION (base);
- DECL_ARTIFICIAL (var) = 1;
+ if (analysis_stage)
+ walk_stmt_load_store_addr_ops (stmt, NULL, NULL, NULL,
+ asm_visit_addr);
+ for (i = 0; i < gimple_asm_ninputs (stmt); i++)
+ {
+ tree *op = &TREE_VALUE (gimple_asm_input_op (stmt, i));
+ any |= scan_expr (op, &gsi, false, data);
+ }
+ for (i = 0; i < gimple_asm_noutputs (stmt); i++)
+ {
+ tree *op = &TREE_VALUE (gimple_asm_output_op (stmt, i));
+ any |= scan_expr (op, &gsi, true, data);
+ }
- if (TREE_THIS_VOLATILE (elt->type))
- {
- TREE_THIS_VOLATILE (var) = 1;
- TREE_SIDE_EFFECTS (var) = 1;
- }
+ default:
+ break;
+ }
- if (DECL_NAME (base) && !DECL_IGNORED_P (base))
- {
- char *pretty_name = build_element_name (elt);
- DECL_NAME (var) = get_identifier (pretty_name);
- obstack_free (&sra_obstack, pretty_name);
-
- SET_DECL_DEBUG_EXPR (var, generate_element_ref (elt));
- DECL_DEBUG_EXPR_IS_FROM (var) = 1;
-
- DECL_IGNORED_P (var) = 0;
- TREE_NO_WARNING (var) = nowarn;
- }
- else
- {
- DECL_IGNORED_P (var) = 1;
- /* ??? We can't generate any warning that would be meaningful. */
- TREE_NO_WARNING (var) = 1;
- }
+ if (any)
+ {
+ ret = true;
+ bb_changed = true;
- /* Zero-initialize bit-field scalarization variables, to avoid
- triggering undefined behavior. */
- if (TREE_CODE (elt->element) == BIT_FIELD_REF
- || (var != elt->replacement
- && TREE_CODE (elt->replacement) == BIT_FIELD_REF))
- {
- gimple_seq init = sra_build_assignment (var,
- fold_convert (TREE_TYPE (var),
- integer_zero_node)
- );
- insert_edge_copies_seq (init, ENTRY_BLOCK_PTR);
- mark_all_v_defs_seq (init);
+ if (!analysis_stage)
+ {
+ update_stmt (stmt);
+ if (!stmt_could_throw_p (stmt))
+ remove_stmt_from_eh_region (stmt);
+ }
+ }
+ if (deleted)
+ bb_changed = true;
+ else
+ {
+ gsi_next (&gsi);
+ ret = true;
+ }
+ }
+ if (!analysis_stage && bb_changed)
+ gimple_purge_dead_eh_edges (bb);
}
- if (dump_file)
- {
- fputs (" ", dump_file);
- dump_sra_elt_name (dump_file, elt);
- fputs (" -> ", dump_file);
- print_generic_expr (dump_file, var, dump_flags);
- fputc ('\n', dump_file);
- }
+ return ret;
}
-/* Make one pass across an element tree deciding whether or not it's
- profitable to instantiate individual leaf scalars.
+/* Helper of QSORT function. There are pointers to accesses in the array. An
+ access is considered smaller than another if it has smaller offset or if the
+ offsets are the same but is size is bigger. */
- PARENT_USES and PARENT_COPIES are the sum of the N_USES and N_COPIES
- fields all the way up the tree. */
+static int
+compare_access_positions (const void *a, const void *b)
+{
+ const access_p *fp1 = (const access_p *) a;
+ const access_p *fp2 = (const access_p *) b;
+ const access_p f1 = *fp1;
+ const access_p f2 = *fp2;
+
+ if (f1->offset != f2->offset)
+ return f1->offset < f2->offset ? -1 : 1;
+
+ if (f1->size == f2->size)
+ {
+ /* Put any non-aggregate type before any aggregate type. */
+ if (!is_gimple_reg_type (f1->type)
+ && is_gimple_reg_type (f2->type))
+ return 1;
+ else if (is_gimple_reg_type (f1->type)
+ && !is_gimple_reg_type (f2->type))
+ return -1;
+ /* Put the integral type with the bigger precision first. */
+ else if (INTEGRAL_TYPE_P (f1->type)
+ && INTEGRAL_TYPE_P (f2->type))
+ return TYPE_PRECISION (f1->type) > TYPE_PRECISION (f2->type) ? -1 : 1;
+ /* Put any integral type with non-full precision last. */
+ else if (INTEGRAL_TYPE_P (f1->type)
+ && (TREE_INT_CST_LOW (TYPE_SIZE (f1->type))
+ != TYPE_PRECISION (f1->type)))
+ return 1;
+ else if (INTEGRAL_TYPE_P (f2->type)
+ && (TREE_INT_CST_LOW (TYPE_SIZE (f2->type))
+ != TYPE_PRECISION (f2->type)))
+ return -1;
+ /* Stabilize the sort. */
+ return TYPE_UID (f1->type) - TYPE_UID (f2->type);
+ }
+
+ /* We want the bigger accesses first, thus the opposite operator in the next
+ line: */
+ return f1->size > f2->size ? -1 : 1;
+}
+
+
+/* Append a name of the declaration to the name obstack. A helper function for
+ make_fancy_name. */
static void
-decide_instantiation_1 (struct sra_elt *elt, unsigned int parent_uses,
- unsigned int parent_copies)
+make_fancy_decl_name (tree decl)
{
- if (dump_file && !elt->parent)
- {
- fputs ("Initial instantiation for ", dump_file);
- dump_sra_elt_name (dump_file, elt);
- fputc ('\n', dump_file);
- }
-
- if (elt->cannot_scalarize)
- return;
+ char buffer[32];
- if (elt->is_scalar)
- {
- /* The decision is simple: instantiate if we're used more frequently
- than the parent needs to be seen as a complete unit. */
- if (elt->n_uses + elt->n_copies + parent_copies > parent_uses)
- instantiate_element (elt);
- }
+ tree name = DECL_NAME (decl);
+ if (name)
+ obstack_grow (&name_obstack, IDENTIFIER_POINTER (name),
+ IDENTIFIER_LENGTH (name));
else
{
- struct sra_elt *c, *group;
- unsigned int this_uses = elt->n_uses + parent_uses;
- unsigned int this_copies = elt->n_copies + parent_copies;
-
- /* Consider groups of sub-elements as weighing in favour of
- instantiation whatever their size. */
- for (group = elt->groups; group ; group = group->sibling)
- FOR_EACH_ACTUAL_CHILD (c, group)
- {
- c->n_uses += group->n_uses;
- c->n_copies += group->n_copies;
- }
-
- for (c = elt->children; c ; c = c->sibling)
- decide_instantiation_1 (c, this_uses, this_copies);
+ sprintf (buffer, "D%u", DECL_UID (decl));
+ obstack_grow (&name_obstack, buffer, strlen (buffer));
}
}
-/* Compute the size and number of all instantiated elements below ELT.
- We will only care about this if the size of the complete structure
- fits in a HOST_WIDE_INT, so we don't have to worry about overflow. */
+/* Helper for make_fancy_name. */
-static unsigned int
-sum_instantiated_sizes (struct sra_elt *elt, unsigned HOST_WIDE_INT *sizep)
+static void
+make_fancy_name_1 (tree expr)
{
- if (elt->replacement)
+ char buffer[32];
+ tree index;
+
+ if (DECL_P (expr))
{
- *sizep += TREE_INT_CST_LOW (TYPE_SIZE_UNIT (elt->type));
- return 1;
+ make_fancy_decl_name (expr);
+ return;
}
- else
- {
- struct sra_elt *c;
- unsigned int count = 0;
-
- for (c = elt->children; c ; c = c->sibling)
- count += sum_instantiated_sizes (c, sizep);
- return count;
- }
-}
+ switch (TREE_CODE (expr))
+ {
+ case COMPONENT_REF:
+ make_fancy_name_1 (TREE_OPERAND (expr, 0));
+ obstack_1grow (&name_obstack, '$');
+ make_fancy_decl_name (TREE_OPERAND (expr, 1));
+ break;
-/* Instantiate fields in ELT->TYPE that are not currently present as
- children of ELT. */
+ case ARRAY_REF:
+ make_fancy_name_1 (TREE_OPERAND (expr, 0));
+ obstack_1grow (&name_obstack, '$');
+ /* Arrays with only one element may not have a constant as their
+ index. */
+ index = TREE_OPERAND (expr, 1);
+ if (TREE_CODE (index) != INTEGER_CST)
+ break;
+ sprintf (buffer, HOST_WIDE_INT_PRINT_DEC, TREE_INT_CST_LOW (index));
+ obstack_grow (&name_obstack, buffer, strlen (buffer));
-static void instantiate_missing_elements (struct sra_elt *elt);
+ break;
-static struct sra_elt *
-instantiate_missing_elements_1 (struct sra_elt *elt, tree child, tree type)
-{
- struct sra_elt *sub = lookup_element (elt, child, type, INSERT);
- if (sub->is_scalar)
- {
- if (sub->replacement == NULL)
- instantiate_element (sub);
+ case BIT_FIELD_REF:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ gcc_unreachable (); /* we treat these as scalars. */
+ break;
+ default:
+ break;
}
- else
- instantiate_missing_elements (sub);
- return sub;
}
-/* Obtain the canonical type for field F of ELEMENT. */
+/* Create a human readable name for replacement variable of ACCESS. */
-static tree
-canon_type_for_field (tree f, tree element)
+static char *
+make_fancy_name (tree expr)
{
- tree field_type = TREE_TYPE (f);
-
- /* canonicalize_component_ref() unwidens some bit-field types (not
- marked as DECL_BIT_FIELD in C++), so we must do the same, lest we
- may introduce type mismatches. */
- if (INTEGRAL_TYPE_P (field_type)
- && DECL_MODE (f) != TYPE_MODE (field_type))
- field_type = TREE_TYPE (get_unwidened (build3 (COMPONENT_REF,
- field_type,
- element,
- f, NULL_TREE),
- NULL_TREE));
-
- return field_type;
+ make_fancy_name_1 (expr);
+ obstack_1grow (&name_obstack, '\0');
+ return XOBFINISH (&name_obstack, char *);
}
-/* Look for adjacent fields of ELT starting at F that we'd like to
- scalarize as a single variable. Return the last field of the
- group. */
+/* Helper function for build_ref_for_offset. */
-static tree
-try_instantiate_multiple_fields (struct sra_elt *elt, tree f)
+static bool
+build_ref_for_offset_1 (tree *res, tree type, HOST_WIDE_INT offset,
+ tree exp_type)
{
- int count;
- unsigned HOST_WIDE_INT align, bit, size, alchk;
- enum machine_mode mode;
- tree first = f, prev;
- tree type, var;
- struct sra_elt *block;
-
- /* Point fields are typically best handled as standalone entities. */
- if (POINTER_TYPE_P (TREE_TYPE (f)))
- return f;
-
- if (!is_sra_scalar_type (TREE_TYPE (f))
- || !host_integerp (DECL_FIELD_OFFSET (f), 1)
- || !host_integerp (DECL_FIELD_BIT_OFFSET (f), 1)
- || !host_integerp (DECL_SIZE (f), 1)
- || lookup_element (elt, f, NULL, NO_INSERT))
- return f;
-
- block = elt;
-
- /* For complex and array objects, there are going to be integer
- literals as child elements. In this case, we can't just take the
- alignment and mode of the decl, so we instead rely on the element
- type.
-
- ??? We could try to infer additional alignment from the full
- object declaration and the location of the sub-elements we're
- accessing. */
- for (count = 0; !DECL_P (block->element); count++)
- block = block->parent;
-
- align = DECL_ALIGN (block->element);
- alchk = GET_MODE_BITSIZE (DECL_MODE (block->element));
-
- if (count)
- {
- type = TREE_TYPE (block->element);
- while (count--)
- type = TREE_TYPE (type);
-
- align = TYPE_ALIGN (type);
- alchk = GET_MODE_BITSIZE (TYPE_MODE (type));
- }
-
- if (align < alchk)
- align = alchk;
-
- /* Coalescing wider fields is probably pointless and
- inefficient. */
- if (align > BITS_PER_WORD)
- align = BITS_PER_WORD;
-
- bit = tree_low_cst (DECL_FIELD_OFFSET (f), 1) * BITS_PER_UNIT
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (f), 1);
- size = tree_low_cst (DECL_SIZE (f), 1);
-
- alchk = align - 1;
- alchk = ~alchk;
-
- if ((bit & alchk) != ((bit + size - 1) & alchk))
- return f;
-
- /* Find adjacent fields in the same alignment word. */
-
- for (prev = f, f = TREE_CHAIN (f);
- f && TREE_CODE (f) == FIELD_DECL
- && is_sra_scalar_type (TREE_TYPE (f))
- && host_integerp (DECL_FIELD_OFFSET (f), 1)
- && host_integerp (DECL_FIELD_BIT_OFFSET (f), 1)
- && host_integerp (DECL_SIZE (f), 1)
- && !lookup_element (elt, f, NULL, NO_INSERT);
- prev = f, f = TREE_CHAIN (f))
+ while (1)
{
- unsigned HOST_WIDE_INT nbit, nsize;
-
- nbit = tree_low_cst (DECL_FIELD_OFFSET (f), 1) * BITS_PER_UNIT
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (f), 1);
- nsize = tree_low_cst (DECL_SIZE (f), 1);
-
- if (bit + size == nbit)
- {
- if ((bit & alchk) != ((nbit + nsize - 1) & alchk))
- {
- /* If we're at an alignment boundary, don't bother
- growing alignment such that we can include this next
- field. */
- if ((nbit & alchk)
- || GET_MODE_BITSIZE (DECL_MODE (f)) <= align)
- break;
-
- align = GET_MODE_BITSIZE (DECL_MODE (f));
- alchk = align - 1;
- alchk = ~alchk;
-
- if ((bit & alchk) != ((nbit + nsize - 1) & alchk))
- break;
- }
- size += nsize;
- }
- else if (nbit + nsize == bit)
- {
- if ((nbit & alchk) != ((bit + size - 1) & alchk))
- {
- if ((bit & alchk)
- || GET_MODE_BITSIZE (DECL_MODE (f)) <= align)
- break;
+ tree fld;
+ tree tr_size, index;
+ HOST_WIDE_INT el_size;
- align = GET_MODE_BITSIZE (DECL_MODE (f));
- alchk = align - 1;
- alchk = ~alchk;
-
- if ((nbit & alchk) != ((bit + size - 1) & alchk))
- break;
- }
- bit = nbit;
- size += nsize;
- }
- else
- break;
- }
-
- f = prev;
-
- if (f == first)
- return f;
-
- gcc_assert ((bit & alchk) == ((bit + size - 1) & alchk));
-
- /* Try to widen the bit range so as to cover padding bits as well. */
-
- if ((bit & ~alchk) || size != align)
- {
- unsigned HOST_WIDE_INT mbit = bit & alchk;
- unsigned HOST_WIDE_INT msize = align;
+ if (offset == 0 && exp_type
+ && useless_type_conversion_p (exp_type, type))
+ return true;
- for (f = TYPE_FIELDS (elt->type);
- f; f = TREE_CHAIN (f))
+ switch (TREE_CODE (type))
{
- unsigned HOST_WIDE_INT fbit, fsize;
-
- /* Skip the fields from first to prev. */
- if (f == first)
- {
- f = prev;
- continue;
- }
-
- if (!(TREE_CODE (f) == FIELD_DECL
- && host_integerp (DECL_FIELD_OFFSET (f), 1)
- && host_integerp (DECL_FIELD_BIT_OFFSET (f), 1)))
- continue;
-
- fbit = tree_low_cst (DECL_FIELD_OFFSET (f), 1) * BITS_PER_UNIT
- + tree_low_cst (DECL_FIELD_BIT_OFFSET (f), 1);
-
- /* If we're past the selected word, we're fine. */
- if ((bit & alchk) < (fbit & alchk))
- continue;
-
- if (host_integerp (DECL_SIZE (f), 1))
- fsize = tree_low_cst (DECL_SIZE (f), 1);
- else
- /* Assume a variable-sized field takes up all space till
- the end of the word. ??? Endianness issues? */
- fsize = align - (fbit & alchk);
-
- if ((fbit & alchk) < (bit & alchk))
+ case UNION_TYPE:
+ case QUAL_UNION_TYPE:
+ case RECORD_TYPE:
+ /* Some ADA records are half-unions, treat all of them the same. */
+ for (fld = TYPE_FIELDS (type); fld; fld = TREE_CHAIN (fld))
{
- /* A large field might start at a previous word and
- extend into the selected word. Exclude those
- bits. ??? Endianness issues? */
- HOST_WIDE_INT diff = fbit + fsize - mbit;
+ HOST_WIDE_INT pos, size;
+ tree expr, *expr_ptr;
- if (diff <= 0)
+ if (TREE_CODE (fld) != FIELD_DECL)
continue;
- mbit += diff;
- msize -= diff;
- }
- else
- {
- /* Non-overlapping, great. */
- if (fbit + fsize <= mbit
- || mbit + msize <= fbit)
+ pos = int_bit_position (fld);
+ gcc_assert (TREE_CODE (type) == RECORD_TYPE || pos == 0);
+ size = tree_low_cst (DECL_SIZE (fld), 1);
+ if (pos > offset || (pos + size) <= offset)
continue;
- if (fbit <= mbit)
+ if (res)
{
- unsigned HOST_WIDE_INT diff = fbit + fsize - mbit;
- mbit += diff;
- msize -= diff;
+ expr = build3 (COMPONENT_REF, TREE_TYPE (fld), *res, fld,
+ NULL_TREE);
+ expr_ptr = &expr;
}
- else if (fbit > mbit)
- msize -= (mbit + msize - fbit);
else
- gcc_unreachable ();
+ expr_ptr = NULL;
+ if (build_ref_for_offset_1 (expr_ptr, TREE_TYPE (fld),
+ offset - pos, exp_type))
+ {
+ if (res)
+ *res = expr;
+ return true;
+ }
}
- }
-
- bit = mbit;
- size = msize;
- }
+ return false;
- /* Now we know the bit range we're interested in. Find the smallest
- machine mode we can use to access it. */
+ case ARRAY_TYPE:
+ tr_size = TYPE_SIZE (TREE_TYPE (type));
+ if (!tr_size || !host_integerp (tr_size, 1))
+ return false;
+ el_size = tree_low_cst (tr_size, 1);
- for (mode = smallest_mode_for_size (size, MODE_INT);
- ;
- mode = GET_MODE_WIDER_MODE (mode))
- {
- gcc_assert (mode != VOIDmode);
+ if (res)
+ {
+ index = build_int_cst (TYPE_DOMAIN (type), offset / el_size);
+ if (!integer_zerop (TYPE_MIN_VALUE (TYPE_DOMAIN (type))))
+ index = int_const_binop (PLUS_EXPR, index,
+ TYPE_MIN_VALUE (TYPE_DOMAIN (type)),
+ 0);
+ *res = build4 (ARRAY_REF, TREE_TYPE (type), *res, index,
+ NULL_TREE, NULL_TREE);
+ }
+ offset = offset % el_size;
+ type = TREE_TYPE (type);
+ break;
- alchk = GET_MODE_PRECISION (mode) - 1;
- alchk = ~alchk;
+ default:
+ if (offset != 0)
+ return false;
- if ((bit & alchk) == ((bit + size - 1) & alchk))
- break;
+ if (exp_type)
+ return false;
+ else
+ return true;
+ }
}
+}
- gcc_assert (~alchk < align);
-
- /* Create the field group as a single variable. */
-
- /* We used to create a type for the mode above, but size turns
- to be out not of mode-size. As we need a matching type
- to build a BIT_FIELD_REF, use a nonstandard integer type as
- fallback. */
- type = lang_hooks.types.type_for_size (size, 1);
- if (!type || TYPE_PRECISION (type) != size)
- type = build_nonstandard_integer_type (size, 1);
- gcc_assert (type);
- var = build3 (BIT_FIELD_REF, type, NULL_TREE,
- bitsize_int (size), bitsize_int (bit));
-
- block = instantiate_missing_elements_1 (elt, var, type);
- gcc_assert (block && block->is_scalar);
-
- var = block->replacement;
- block->in_bitfld_block = 2;
-
- /* Add the member fields to the group, such that they access
- portions of the group variable. */
-
- for (f = first; f != TREE_CHAIN (prev); f = TREE_CHAIN (f))
- {
- tree field_type = canon_type_for_field (f, elt->element);
- struct sra_elt *fld = lookup_element (block, f, field_type, INSERT);
-
- gcc_assert (fld && fld->is_scalar && !fld->replacement);
-
- fld->replacement = fold_build3 (BIT_FIELD_REF, field_type, var,
- bitsize_int (TYPE_PRECISION (field_type)),
- bitsize_int
- ((TREE_INT_CST_LOW (DECL_FIELD_OFFSET (f))
- * BITS_PER_UNIT
- + (TREE_INT_CST_LOW
- (DECL_FIELD_BIT_OFFSET (f)))
- - (TREE_INT_CST_LOW
- (TREE_OPERAND (block->element, 2))))
- & ~alchk));
- fld->in_bitfld_block = 1;
- }
+/* Construct an expression that would reference a part of aggregate *EXPR of
+ type TYPE at the given OFFSET of the type EXP_TYPE. If EXPR is NULL, the
+ function only determines whether it can build such a reference without
+ actually doing it.
- return prev;
-}
+ FIXME: Eventually this should be replaced with
+ maybe_fold_offset_to_reference() from tree-ssa-ccp.c but that requires a
+ minor rewrite of fold_stmt.
+ */
-static void
-instantiate_missing_elements (struct sra_elt *elt)
+static bool
+build_ref_for_offset (tree *expr, tree type, HOST_WIDE_INT offset,
+ tree exp_type, bool allow_ptr)
{
- tree type = elt->type;
-
- switch (TREE_CODE (type))
+ if (allow_ptr && POINTER_TYPE_P (type))
{
- case RECORD_TYPE:
- {
- tree f;
- for (f = TYPE_FIELDS (type); f ; f = TREE_CHAIN (f))
- if (TREE_CODE (f) == FIELD_DECL)
- {
- tree last = try_instantiate_multiple_fields (elt, f);
-
- if (last != f)
- {
- f = last;
- continue;
- }
-
- instantiate_missing_elements_1 (elt, f,
- canon_type_for_field
- (f, elt->element));
- }
- break;
- }
-
- case ARRAY_TYPE:
- {
- tree i, max, subtype;
-
- i = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
- max = TYPE_MAX_VALUE (TYPE_DOMAIN (type));
- subtype = TREE_TYPE (type);
-
- while (1)
- {
- instantiate_missing_elements_1 (elt, i, subtype);
- if (tree_int_cst_equal (i, max))
- break;
- i = int_const_binop (PLUS_EXPR, i, integer_one_node, true);
- }
-
- break;
- }
-
- case COMPLEX_TYPE:
type = TREE_TYPE (type);
- instantiate_missing_elements_1 (elt, integer_zero_node, type);
- instantiate_missing_elements_1 (elt, integer_one_node, type);
- break;
-
- default:
- gcc_unreachable ();
+ if (expr)
+ *expr = fold_build1 (INDIRECT_REF, type, *expr);
}
-}
-/* Return true if there is only one non aggregate field in the record, TYPE.
- Return false otherwise. */
-
-static bool
-single_scalar_field_in_record_p (tree type)
-{
- int num_fields = 0;
- tree field;
- if (TREE_CODE (type) != RECORD_TYPE)
- return false;
-
- for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (TREE_CODE (field) == FIELD_DECL)
- {
- num_fields++;
-
- if (num_fields == 2)
- return false;
-
- if (AGGREGATE_TYPE_P (TREE_TYPE (field)))
- return false;
- }
-
- return true;
+ return build_ref_for_offset_1 (expr, type, offset, exp_type);
}
-/* Make one pass across an element tree deciding whether to perform block
- or element copies. If we decide on element copies, instantiate all
- elements. Return true if there are any instantiated sub-elements. */
+/* The very first phase of intraprocedural SRA. It marks in candidate_bitmap
+ those with type which is suitable for scalarization. */
static bool
-decide_block_copy (struct sra_elt *elt)
+find_var_candidates (void)
{
- struct sra_elt *c;
- bool any_inst;
-
- /* We shouldn't be invoked on groups of sub-elements as they must
- behave like their parent as far as block copy is concerned. */
- gcc_assert (!elt->is_group);
+ tree var, type;
+ referenced_var_iterator rvi;
+ bool ret = false;
- /* If scalarization is disabled, respect it. */
- if (elt->cannot_scalarize)
+ FOR_EACH_REFERENCED_VAR (var, rvi)
{
- elt->use_block_copy = 1;
+ if (TREE_CODE (var) != VAR_DECL && TREE_CODE (var) != PARM_DECL)
+ continue;
+ type = TREE_TYPE (var);
+
+ if (!AGGREGATE_TYPE_P (type)
+ || needs_to_live_in_memory (var)
+ || TREE_THIS_VOLATILE (var)
+ || !COMPLETE_TYPE_P (type)
+ || !host_integerp (TYPE_SIZE (type), 1)
+ || tree_low_cst (TYPE_SIZE (type), 1) == 0
+ || type_internals_preclude_sra_p (type))
+ continue;
- if (dump_file)
- {
- fputs ("Scalarization disabled for ", dump_file);
- dump_sra_elt_name (dump_file, elt);
- fputc ('\n', dump_file);
- }
+ bitmap_set_bit (candidate_bitmap, DECL_UID (var));
- /* Disable scalarization of sub-elements */
- for (c = elt->children; c; c = c->sibling)
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- c->cannot_scalarize = 1;
- decide_block_copy (c);
+ fprintf (dump_file, "Candidate (%d): ", DECL_UID (var));
+ print_generic_expr (dump_file, var, 0);
+ fprintf (dump_file, "\n");
}
+ ret = true;
+ }
- /* Groups behave like their parent. */
- for (c = elt->groups; c; c = c->sibling)
- {
- c->cannot_scalarize = 1;
- c->use_block_copy = 1;
- }
+ return ret;
+}
- return false;
- }
+/* Sort all accesses for the given variable, check for partial overlaps and
+ return NULL if there are any. If there are none, pick a representative for
+ each combination of offset and size and create a linked list out of them.
+ Return the pointer to the first representative and make sure it is the first
+ one in the vector of accesses. */
- /* Don't decide if we've no uses and no groups. */
- if (elt->n_uses == 0 && elt->n_copies == 0 && elt->groups == NULL)
- ;
+static struct access *
+sort_and_splice_var_accesses (tree var)
+{
+ int i, j, access_count;
+ struct access *res, **prev_acc_ptr = &res;
+ VEC (access_p, heap) *access_vec;
+ bool first = true;
+ HOST_WIDE_INT low = -1, high = 0;
- else if (!elt->is_scalar)
- {
- tree size_tree = TYPE_SIZE_UNIT (elt->type);
- bool use_block_copy = true;
-
- /* Tradeoffs for COMPLEX types pretty much always make it better
- to go ahead and split the components. */
- if (TREE_CODE (elt->type) == COMPLEX_TYPE)
- use_block_copy = false;
-
- /* Don't bother trying to figure out the rest if the structure is
- so large we can't do easy arithmetic. This also forces block
- copies for variable sized structures. */
- else if (host_integerp (size_tree, 1))
- {
- unsigned HOST_WIDE_INT full_size, inst_size = 0;
- unsigned int max_size, max_count, inst_count, full_count;
-
- /* If the sra-max-structure-size parameter is 0, then the
- user has not overridden the parameter and we can choose a
- sensible default. */
- max_size = SRA_MAX_STRUCTURE_SIZE
- ? SRA_MAX_STRUCTURE_SIZE
- : MOVE_RATIO (optimize_function_for_speed_p (cfun)) * UNITS_PER_WORD;
- max_count = SRA_MAX_STRUCTURE_COUNT
- ? SRA_MAX_STRUCTURE_COUNT
- : MOVE_RATIO (optimize_function_for_speed_p (cfun));
-
- full_size = tree_low_cst (size_tree, 1);
- full_count = count_type_elements (elt->type, false);
- inst_count = sum_instantiated_sizes (elt, &inst_size);
-
- /* If there is only one scalar field in the record, don't block copy. */
- if (single_scalar_field_in_record_p (elt->type))
- use_block_copy = false;
-
- /* ??? What to do here. If there are two fields, and we've only
- instantiated one, then instantiating the other is clearly a win.
- If there are a large number of fields then the size of the copy
- is much more of a factor. */
-
- /* If the structure is small, and we've made copies, go ahead
- and instantiate, hoping that the copies will go away. */
- if (full_size <= max_size
- && (full_count - inst_count) <= max_count
- && elt->n_copies > elt->n_uses)
- use_block_copy = false;
- else if (inst_count * 100 >= full_count * SRA_FIELD_STRUCTURE_RATIO
- && inst_size * 100 >= full_size * SRA_FIELD_STRUCTURE_RATIO)
- use_block_copy = false;
-
- /* In order to avoid block copy, we have to be able to instantiate
- all elements of the type. See if this is possible. */
- if (!use_block_copy
- && (!can_completely_scalarize_p (elt)
- || !type_can_instantiate_all_elements (elt->type)))
- use_block_copy = true;
- }
+ access_vec = get_base_access_vector (var);
+ if (!access_vec)
+ return NULL;
+ access_count = VEC_length (access_p, access_vec);
- elt->use_block_copy = use_block_copy;
+ /* Sort by <OFFSET, SIZE>. */
+ qsort (VEC_address (access_p, access_vec), access_count, sizeof (access_p),
+ compare_access_positions);
- /* Groups behave like their parent. */
- for (c = elt->groups; c; c = c->sibling)
- c->use_block_copy = use_block_copy;
+ i = 0;
+ while (i < access_count)
+ {
+ struct access *access = VEC_index (access_p, access_vec, i);
+ bool modification = access->write;
+ bool grp_read = !access->write;
+ bool grp_partial_lhs = access->grp_partial_lhs;
+ bool first_scalar = is_gimple_reg_type (access->type);
+ bool unscalarizable_region = access->grp_unscalarizable_region;
- if (dump_file)
+ if (first || access->offset >= high)
{
- fprintf (dump_file, "Using %s for ",
- use_block_copy ? "block-copy" : "element-copy");
- dump_sra_elt_name (dump_file, elt);
- fputc ('\n', dump_file);
+ first = false;
+ low = access->offset;
+ high = access->offset + access->size;
}
+ else if (access->offset > low && access->offset + access->size > high)
+ return NULL;
+ else
+ gcc_assert (access->offset >= low
+ && access->offset + access->size <= high);
- if (!use_block_copy)
+ j = i + 1;
+ while (j < access_count)
{
- instantiate_missing_elements (elt);
- return true;
+ struct access *ac2 = VEC_index (access_p, access_vec, j);
+ if (ac2->offset != access->offset || ac2->size != access->size)
+ break;
+ modification |= ac2->write;
+ grp_read |= !ac2->write;
+ grp_partial_lhs |= ac2->grp_partial_lhs;
+ unscalarizable_region |= ac2->grp_unscalarizable_region;
+ relink_to_new_repr (access, ac2);
+
+ /* If there are both aggregate-type and scalar-type accesses with
+ this combination of size and offset, the comparison function
+ should have put the scalars first. */
+ gcc_assert (first_scalar || !is_gimple_reg_type (ac2->type));
+ ac2->group_representative = access;
+ j++;
}
- }
- any_inst = elt->replacement != NULL;
+ i = j;
+
+ access->group_representative = access;
+ access->grp_write = modification;
+ access->grp_read = grp_read;
+ access->grp_partial_lhs = grp_partial_lhs;
+ access->grp_unscalarizable_region = unscalarizable_region;
+ if (access->first_link)
+ add_access_to_work_queue (access);
- for (c = elt->children; c ; c = c->sibling)
- any_inst |= decide_block_copy (c);
+ *prev_acc_ptr = access;
+ prev_acc_ptr = &access->next_grp;
+ }
- return any_inst;
+ gcc_assert (res == VEC_index (access_p, access_vec, 0));
+ return res;
}
-/* Entry point to phase 3. Instantiate scalar replacement variables. */
+/* Create a variable for the given ACCESS which determines the type, name and a
+ few other properties. Return the variable declaration and store it also to
+ ACCESS->replacement. */
-static void
-decide_instantiations (void)
+static tree
+create_access_replacement (struct access *access)
{
- unsigned int i;
- bool cleared_any;
- bitmap_head done_head;
- bitmap_iterator bi;
+ tree repl;
+
+ repl = create_tmp_var (access->type, "SR");
+ get_var_ann (repl);
+ add_referenced_var (repl);
+ mark_sym_for_renaming (repl);
- /* We cannot clear bits from a bitmap we're iterating over,
- so save up all the bits to clear until the end. */
- bitmap_initialize (&done_head, &bitmap_default_obstack);
- cleared_any = false;
+ if (!access->grp_partial_lhs
+ && (TREE_CODE (access->type) == COMPLEX_TYPE
+ || TREE_CODE (access->type) == VECTOR_TYPE))
+ DECL_GIMPLE_REG_P (repl) = 1;
- EXECUTE_IF_SET_IN_BITMAP (sra_candidates, 0, i, bi)
+ DECL_SOURCE_LOCATION (repl) = DECL_SOURCE_LOCATION (access->base);
+ DECL_ARTIFICIAL (repl) = 1;
+
+ if (DECL_NAME (access->base)
+ && !DECL_IGNORED_P (access->base)
+ && !DECL_ARTIFICIAL (access->base))
{
- tree var = referenced_var (i);
- struct sra_elt *elt = lookup_element (NULL, var, NULL, NO_INSERT);
- if (elt)
- {
- decide_instantiation_1 (elt, 0, 0);
- if (!decide_block_copy (elt))
- elt = NULL;
- }
- if (!elt)
- {
- bitmap_set_bit (&done_head, i);
- cleared_any = true;
- }
+ char *pretty_name = make_fancy_name (access->expr);
+
+ DECL_NAME (repl) = get_identifier (pretty_name);
+ obstack_free (&name_obstack, pretty_name);
+
+ SET_DECL_DEBUG_EXPR (repl, access->expr);
+ DECL_DEBUG_EXPR_IS_FROM (repl) = 1;
+ DECL_IGNORED_P (repl) = 0;
}
- if (cleared_any)
+ DECL_IGNORED_P (repl) = DECL_IGNORED_P (access->base);
+ TREE_NO_WARNING (repl) = TREE_NO_WARNING (access->base);
+
+ if (dump_file)
{
- bitmap_and_compl_into (sra_candidates, &done_head);
- bitmap_and_compl_into (needs_copy_in, &done_head);
+ fprintf (dump_file, "Created a replacement for ");
+ print_generic_expr (dump_file, access->base, 0);
+ fprintf (dump_file, " offset: %u, size: %u: ",
+ (unsigned) access->offset, (unsigned) access->size);
+ print_generic_expr (dump_file, repl, 0);
+ fprintf (dump_file, "\n");
}
- bitmap_clear (&done_head);
-
- mark_set_for_renaming (sra_candidates);
- if (dump_file)
- fputc ('\n', dump_file);
+ return repl;
}
-
-/* Phase Four: Update the function to match the replacements created. */
+/* Return ACCESS scalar replacement, create it if it does not exist yet. */
-/* Mark all the variables in virtual operands in all the statements in
- LIST for renaming. */
-
-static void
-mark_all_v_defs_seq (gimple_seq seq)
+static inline tree
+get_access_replacement (struct access *access)
{
- gimple_stmt_iterator gsi;
+ gcc_assert (access->grp_to_be_replaced);
+
+ if (access->replacement_decl)
+ return access->replacement_decl;
- for (gsi = gsi_start (seq); !gsi_end_p (gsi); gsi_next (&gsi))
- update_stmt_if_modified (gsi_stmt (gsi));
+ access->replacement_decl = create_access_replacement (access);
+ return access->replacement_decl;
}
-/* Mark every replacement under ELT with TREE_NO_WARNING. */
+/* Build a subtree of accesses rooted in *ACCESS, and move the pointer in the
+ linked list along the way. Stop when *ACCESS is NULL or the access pointed
+ to it is not "within" the root. */
static void
-mark_no_warning (struct sra_elt *elt)
+build_access_subtree (struct access **access)
{
- if (!elt->all_no_warning)
+ struct access *root = *access, *last_child = NULL;
+ HOST_WIDE_INT limit = root->offset + root->size;
+
+ *access = (*access)->next_grp;
+ while (*access && (*access)->offset + (*access)->size <= limit)
{
- if (elt->replacement)
- TREE_NO_WARNING (elt->replacement) = 1;
+ if (!last_child)
+ root->first_child = *access;
else
- {
- struct sra_elt *c;
- FOR_EACH_ACTUAL_CHILD (c, elt)
- mark_no_warning (c);
- }
- elt->all_no_warning = true;
+ last_child->next_sibling = *access;
+ last_child = *access;
+
+ build_access_subtree (access);
}
}
-/* Build a single level component reference to ELT rooted at BASE. */
+/* Build a tree of access representatives, ACCESS is the pointer to the first
+ one, others are linked in a list by the next_grp field. Decide about scalar
+ replacements on the way, return true iff any are to be created. */
-static tree
-generate_one_element_ref (struct sra_elt *elt, tree base)
+static void
+build_access_trees (struct access *access)
{
- switch (TREE_CODE (TREE_TYPE (base)))
+ while (access)
{
- case RECORD_TYPE:
- {
- tree field = elt->element;
-
- /* We can't test elt->in_bitfld_block here because, when this is
- called from instantiate_element, we haven't set this field
- yet. */
- if (TREE_CODE (field) == BIT_FIELD_REF)
- {
- tree ret = unshare_expr (field);
- TREE_OPERAND (ret, 0) = base;
- return ret;
- }
-
- /* Watch out for compatible records with differing field lists. */
- if (DECL_FIELD_CONTEXT (field) != TYPE_MAIN_VARIANT (TREE_TYPE (base)))
- field = find_compatible_field (TREE_TYPE (base), field);
+ struct access *root = access;
- return build3 (COMPONENT_REF, elt->type, base, field, NULL);
- }
-
- case ARRAY_TYPE:
- if (TREE_CODE (elt->element) == RANGE_EXPR)
- return build4 (ARRAY_RANGE_REF, elt->type, base,
- TREE_OPERAND (elt->element, 0), NULL, NULL);
- else
- return build4 (ARRAY_REF, elt->type, base, elt->element, NULL, NULL);
-
- case COMPLEX_TYPE:
- if (elt->element == integer_zero_node)
- return build1 (REALPART_EXPR, elt->type, base);
- else
- return build1 (IMAGPART_EXPR, elt->type, base);
-
- default:
- gcc_unreachable ();
+ build_access_subtree (&access);
+ root->next_grp = access;
}
}
-/* Build a full component reference to ELT rooted at its native variable. */
+/* Analyze the subtree of accesses rooted in ROOT, scheduling replacements when
+ both seeming beneficial and when ALLOW_REPLACEMENTS allows it. Also set
+ all sorts of access flags appropriately along the way, notably always ser
+ grp_read when MARK_READ is true and grp_write when MARK_WRITE is true. */
-static tree
-generate_element_ref (struct sra_elt *elt)
+static bool
+analyze_access_subtree (struct access *root, bool allow_replacements,
+ bool mark_read, bool mark_write)
{
- if (elt->parent)
- return generate_one_element_ref (elt, generate_element_ref (elt->parent));
- else
- return elt->element;
-}
+ struct access *child;
+ HOST_WIDE_INT limit = root->offset + root->size;
+ HOST_WIDE_INT covered_to = root->offset;
+ bool scalar = is_gimple_reg_type (root->type);
+ bool hole = false, sth_created = false;
-/* Return true if BF is a bit-field that we can handle like a scalar. */
+ if (mark_read)
+ root->grp_read = true;
+ else if (root->grp_read)
+ mark_read = true;
-static bool
-scalar_bitfield_p (tree bf)
-{
- return (TREE_CODE (bf) == BIT_FIELD_REF
- && (is_gimple_reg (TREE_OPERAND (bf, 0))
- || (TYPE_MODE (TREE_TYPE (TREE_OPERAND (bf, 0))) != BLKmode
- && (!TREE_SIDE_EFFECTS (TREE_OPERAND (bf, 0))
- || (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE
- (TREE_OPERAND (bf, 0))))
- <= BITS_PER_WORD)))));
-}
+ if (mark_write)
+ root->grp_write = true;
+ else if (root->grp_write)
+ mark_write = true;
-/* Create an assignment statement from SRC to DST. */
+ if (root->grp_unscalarizable_region)
+ allow_replacements = false;
-static gimple_seq
-sra_build_assignment (tree dst, tree src)
-{
- gimple stmt;
- gimple_seq seq = NULL, seq2 = NULL;
- /* Turning BIT_FIELD_REFs into bit operations enables other passes
- to do a much better job at optimizing the code.
- From dst = BIT_FIELD_REF <var, sz, off> we produce
-
- SR.1 = (scalar type) var;
- SR.2 = SR.1 >> off;
- SR.3 = SR.2 & ((1 << sz) - 1);
- ... possible sign extension of SR.3 ...
- dst = (destination type) SR.3;
- */
- if (scalar_bitfield_p (src))
+ for (child = root->first_child; child; child = child->next_sibling)
{
- tree var, shift, width;
- tree utype, stype;
- bool unsignedp = (INTEGRAL_TYPE_P (TREE_TYPE (src))
- ? TYPE_UNSIGNED (TREE_TYPE (src)) : true);
- struct gimplify_ctx gctx;
-
- var = TREE_OPERAND (src, 0);
- width = TREE_OPERAND (src, 1);
- /* The offset needs to be adjusted to a right shift quantity
- depending on the endianness. */
- if (BYTES_BIG_ENDIAN)
- {
- tree tmp = size_binop (PLUS_EXPR, width, TREE_OPERAND (src, 2));
- shift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), tmp);
- }
+ if (!hole && child->offset < covered_to)
+ hole = true;
else
- shift = TREE_OPERAND (src, 2);
-
- /* In weird cases we have non-integral types for the source or
- destination object.
- ??? For unknown reasons we also want an unsigned scalar type. */
- stype = TREE_TYPE (var);
- if (!INTEGRAL_TYPE_P (stype))
- stype = lang_hooks.types.type_for_size (TREE_INT_CST_LOW
- (TYPE_SIZE (stype)), 1);
- else if (!TYPE_UNSIGNED (stype))
- stype = unsigned_type_for (stype);
-
- utype = TREE_TYPE (dst);
- if (!INTEGRAL_TYPE_P (utype))
- utype = lang_hooks.types.type_for_size (TREE_INT_CST_LOW
- (TYPE_SIZE (utype)), 1);
- else if (!TYPE_UNSIGNED (utype))
- utype = unsigned_type_for (utype);
-
- /* Convert the base var of the BIT_FIELD_REF to the scalar type
- we use for computation if we cannot use it directly. */
- if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
- var = fold_convert (stype, var);
- else
- var = fold_build1 (VIEW_CONVERT_EXPR, stype, var);
-
- if (!integer_zerop (shift))
- var = fold_build2 (RSHIFT_EXPR, stype, var, shift);
+ covered_to += child->size;
- /* If we need a masking operation, produce one. */
- if (TREE_INT_CST_LOW (width) == TYPE_PRECISION (stype))
- unsignedp = true;
- else
- {
- tree one = build_int_cst_wide (stype, 1, 0);
- tree mask = int_const_binop (LSHIFT_EXPR, one, width, 0);
- mask = int_const_binop (MINUS_EXPR, mask, one, 0);
- var = fold_build2 (BIT_AND_EXPR, stype, var, mask);
- }
+ sth_created |= analyze_access_subtree (child, allow_replacements,
+ mark_read, mark_write);
- /* After shifting and masking, convert to the target type. */
- var = fold_convert (utype, var);
+ root->grp_unscalarized_data |= child->grp_unscalarized_data;
+ hole |= !child->grp_covered;
+ }
- /* Perform sign extension, if required.
- ??? This should never be necessary. */
- if (!unsignedp)
+ if (allow_replacements && scalar && !root->first_child)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
{
- tree signbit = int_const_binop (LSHIFT_EXPR,
- build_int_cst_wide (utype, 1, 0),
- size_binop (MINUS_EXPR, width,
- bitsize_int (1)), 0);
-
- var = fold_build2 (BIT_XOR_EXPR, utype, var, signbit);
- var = fold_build2 (MINUS_EXPR, utype, var, signbit);
+ fprintf (dump_file, "Marking ");
+ print_generic_expr (dump_file, root->base, 0);
+ fprintf (dump_file, " offset: %u, size: %u: ",
+ (unsigned) root->offset, (unsigned) root->size);
+ fprintf (dump_file, " to be replaced.\n");
}
- /* fold_build3 (BIT_FIELD_REF, ...) sometimes returns a cast. */
- STRIP_NOPS (dst);
-
- /* Finally, move and convert to the destination. */
- if (INTEGRAL_TYPE_P (TREE_TYPE (dst)))
- var = fold_convert (TREE_TYPE (dst), var);
- else
- var = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (dst), var);
-
- push_gimplify_context (&gctx);
- gctx.allow_rhs_cond_expr = true;
-
- gimplify_assign (dst, var, &seq);
-
- if (gimple_referenced_vars (cfun))
- for (var = gctx.temps; var; var = TREE_CHAIN (var))
- {
- add_referenced_var (var);
- mark_sym_for_renaming (var);
- }
- pop_gimplify_context (NULL);
-
- return seq;
+ root->grp_to_be_replaced = 1;
+ sth_created = true;
+ hole = false;
}
+ else if (covered_to < limit)
+ hole = true;
- /* fold_build3 (BIT_FIELD_REF, ...) sometimes returns a cast. */
- if (CONVERT_EXPR_P (dst))
+ if (sth_created && !hole)
{
- STRIP_NOPS (dst);
- src = fold_convert (TREE_TYPE (dst), src);
+ root->grp_covered = 1;
+ return true;
}
- /* It was hoped that we could perform some type sanity checking
- here, but since front-ends can emit accesses of fields in types
- different from their nominal types and copy structures containing
- them as a whole, we'd have to handle such differences here.
- Since such accesses under different types require compatibility
- anyway, there's little point in making tests and/or adding
- conversions to ensure the types of src and dst are the same.
- So we just assume type differences at this point are ok.
- The only exception we make here are pointer types, which can be different
- in e.g. structurally equal, but non-identical RECORD_TYPEs. */
- else if (POINTER_TYPE_P (TREE_TYPE (dst))
- && !useless_type_conversion_p (TREE_TYPE (dst), TREE_TYPE (src)))
- src = fold_convert (TREE_TYPE (dst), src);
-
- /* ??? Only call the gimplifier if we need to. Otherwise we may
- end up substituting with DECL_VALUE_EXPR - see PR37380. */
- if (!handled_component_p (src)
- && !SSA_VAR_P (src))
+ if (root->grp_write || TREE_CODE (root->base) == PARM_DECL)
+ root->grp_unscalarized_data = 1; /* not covered and written to */
+ if (sth_created)
+ return true;
+ return false;
+}
+
+/* Analyze all access trees linked by next_grp by the means of
+ analyze_access_subtree. */
+static bool
+analyze_access_trees (struct access *access)
+{
+ bool ret = false;
+
+ while (access)
{
- src = force_gimple_operand (src, &seq2, false, NULL_TREE);
- gimple_seq_add_seq (&seq, seq2);
+ if (analyze_access_subtree (access, true, false, false))
+ ret = true;
+ access = access->next_grp;
}
- stmt = gimple_build_assign (dst, src);
- gimple_seq_add_stmt (&seq, stmt);
- return seq;
-}
-/* BIT_FIELD_REFs must not be shared. sra_build_elt_assignment()
- takes care of assignments, but we must create copies for uses. */
-#define REPLDUP(t) (TREE_CODE (t) != BIT_FIELD_REF ? (t) : unshare_expr (t))
+ return ret;
+}
-/* Emit an assignment from SRC to DST, but if DST is a scalarizable
- BIT_FIELD_REF, turn it into bit operations. */
+/* Return true iff a potential new child of LACC at offset OFFSET and with size
+ SIZE would conflict with an already existing one. If exactly such a child
+ already exists in LACC, store a pointer to it in EXACT_MATCH. */
-static gimple_seq
-sra_build_bf_assignment (tree dst, tree src)
+static bool
+child_would_conflict_in_lacc (struct access *lacc, HOST_WIDE_INT norm_offset,
+ HOST_WIDE_INT size, struct access **exact_match)
{
- tree var, type, utype, tmp, tmp2, tmp3;
- gimple_seq seq;
- gimple stmt;
- tree cst, cst2, mask;
- tree minshift, maxshift;
+ struct access *child;
- if (TREE_CODE (dst) != BIT_FIELD_REF)
- return sra_build_assignment (dst, src);
+ for (child = lacc->first_child; child; child = child->next_sibling)
+ {
+ if (child->offset == norm_offset && child->size == size)
+ {
+ *exact_match = child;
+ return true;
+ }
- var = TREE_OPERAND (dst, 0);
+ if (child->offset < norm_offset + size
+ && child->offset + child->size > norm_offset)
+ return true;
+ }
- if (!scalar_bitfield_p (dst))
- return sra_build_assignment (REPLDUP (dst), src);
+ return false;
+}
- seq = NULL;
+/* Set the expr of TARGET to one just like MODEL but with is own base at the
+ bottom of the handled components. */
- cst = fold_convert (bitsizetype, TREE_OPERAND (dst, 2));
- cst2 = size_binop (PLUS_EXPR,
- fold_convert (bitsizetype, TREE_OPERAND (dst, 1)),
- cst);
+static void
+duplicate_expr_for_different_base (struct access *target,
+ struct access *model)
+{
+ tree t, expr = unshare_expr (model->expr);
- if (BYTES_BIG_ENDIAN)
- {
- maxshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst);
- minshift = size_binop (MINUS_EXPR, TYPE_SIZE (TREE_TYPE (var)), cst2);
- }
- else
- {
- maxshift = cst2;
- minshift = cst;
- }
+ gcc_assert (handled_component_p (expr));
+ t = expr;
+ while (handled_component_p (TREE_OPERAND (t, 0)))
+ t = TREE_OPERAND (t, 0);
+ gcc_assert (TREE_OPERAND (t, 0) == model->base);
+ TREE_OPERAND (t, 0) = target->base;
- type = TREE_TYPE (var);
- if (!INTEGRAL_TYPE_P (type))
- type = lang_hooks.types.type_for_size
- (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (var))), 1);
- if (TYPE_UNSIGNED (type))
- utype = type;
- else
- utype = unsigned_type_for (type);
+ target->expr = expr;
+}
- mask = build_int_cst_wide (utype, 1, 0);
- if (TREE_INT_CST_LOW (maxshift) == TYPE_PRECISION (utype))
- cst = build_int_cst_wide (utype, 0, 0);
- else
- cst = int_const_binop (LSHIFT_EXPR, mask, maxshift, true);
- if (integer_zerop (minshift))
- cst2 = mask;
- else
- cst2 = int_const_binop (LSHIFT_EXPR, mask, minshift, true);
- mask = int_const_binop (MINUS_EXPR, cst, cst2, true);
- mask = fold_build1 (BIT_NOT_EXPR, utype, mask);
- if (TYPE_MAIN_VARIANT (utype) != TYPE_MAIN_VARIANT (TREE_TYPE (var))
- && !integer_zerop (mask))
- {
- tmp = var;
- if (!is_gimple_variable (tmp))
- tmp = unshare_expr (var);
- else
- TREE_NO_WARNING (var) = true;
+/* Create a new child access of PARENT, with all properties just like MODEL
+ except for its offset and with its grp_write false and grp_read true.
+ Return the new access. Note that this access is created long after all
+ splicing and sorting, it's not located in any access vector and is
+ automatically a representative of its group. */
- tmp2 = make_rename_temp (utype, "SR");
+static struct access *
+create_artificial_child_access (struct access *parent, struct access *model,
+ HOST_WIDE_INT new_offset)
+{
+ struct access *access;
+ struct access **child;
- if (INTEGRAL_TYPE_P (TREE_TYPE (var)))
- tmp = fold_convert (utype, tmp);
- else
- tmp = fold_build1 (VIEW_CONVERT_EXPR, utype, tmp);
+ gcc_assert (!model->grp_unscalarizable_region);
- stmt = gimple_build_assign (tmp2, tmp);
- gimple_seq_add_stmt (&seq, stmt);
- }
- else
- tmp2 = var;
+ access = (struct access *) pool_alloc (access_pool);
+ memset (access, 0, sizeof (struct access));
+ access->base = parent->base;
+ access->offset = new_offset;
+ access->size = model->size;
+ duplicate_expr_for_different_base (access, model);
+ access->type = model->type;
+ access->grp_write = true;
+ access->grp_read = false;
- if (!integer_zerop (mask))
- {
- tmp = make_rename_temp (utype, "SR");
- stmt = gimple_build_assign (tmp, fold_build2 (BIT_AND_EXPR, utype,
- tmp2, mask));
- gimple_seq_add_stmt (&seq, stmt);
- }
- else
- tmp = mask;
+ child = &parent->first_child;
+ while (*child && (*child)->offset < new_offset)
+ child = &(*child)->next_sibling;
- if (is_gimple_reg (src) && INTEGRAL_TYPE_P (TREE_TYPE (src)))
- tmp2 = src;
- else if (INTEGRAL_TYPE_P (TREE_TYPE (src)))
- {
- gimple_seq tmp_seq;
- tmp2 = make_rename_temp (TREE_TYPE (src), "SR");
- tmp_seq = sra_build_assignment (tmp2, src);
- gimple_seq_add_seq (&seq, tmp_seq);
- }
- else
- {
- gimple_seq tmp_seq;
- tmp2 = make_rename_temp
- (lang_hooks.types.type_for_size
- (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (src))),
- 1), "SR");
- tmp_seq = sra_build_assignment (tmp2, fold_build1 (VIEW_CONVERT_EXPR,
- TREE_TYPE (tmp2), src));
- gimple_seq_add_seq (&seq, tmp_seq);
- }
+ access->next_sibling = *child;
+ *child = access;
- if (!TYPE_UNSIGNED (TREE_TYPE (tmp2)))
- {
- gimple_seq tmp_seq;
- tree ut = unsigned_type_for (TREE_TYPE (tmp2));
- tmp3 = make_rename_temp (ut, "SR");
- tmp2 = fold_convert (ut, tmp2);
- tmp_seq = sra_build_assignment (tmp3, tmp2);
- gimple_seq_add_seq (&seq, tmp_seq);
-
- tmp2 = fold_build1 (BIT_NOT_EXPR, utype, mask);
- tmp2 = int_const_binop (RSHIFT_EXPR, tmp2, minshift, true);
- tmp2 = fold_convert (ut, tmp2);
- tmp2 = fold_build2 (BIT_AND_EXPR, ut, tmp3, tmp2);
-
- if (tmp3 != tmp2)
- {
- tmp3 = make_rename_temp (ut, "SR");
- tmp_seq = sra_build_assignment (tmp3, tmp2);
- gimple_seq_add_seq (&seq, tmp_seq);
- }
+ return access;
+}
- tmp2 = tmp3;
- }
- if (TYPE_MAIN_VARIANT (TREE_TYPE (tmp2)) != TYPE_MAIN_VARIANT (utype))
- {
- gimple_seq tmp_seq;
- tmp3 = make_rename_temp (utype, "SR");
- tmp2 = fold_convert (utype, tmp2);
- tmp_seq = sra_build_assignment (tmp3, tmp2);
- gimple_seq_add_seq (&seq, tmp_seq);
- tmp2 = tmp3;
- }
+/* Propagate all subaccesses of RACC across an assignment link to LACC. Return
+ true if any new subaccess was created. Additionally, if RACC is a scalar
+ access but LACC is not, change the type of the latter. */
- if (!integer_zerop (minshift))
- {
- tmp3 = make_rename_temp (utype, "SR");
- stmt = gimple_build_assign (tmp3, fold_build2 (LSHIFT_EXPR, utype,
- tmp2, minshift));
- gimple_seq_add_stmt (&seq, stmt);
- tmp2 = tmp3;
- }
+static bool
+propagate_subacesses_accross_link (struct access *lacc, struct access *racc)
+{
+ struct access *rchild;
+ HOST_WIDE_INT norm_delta = lacc->offset - racc->offset;
- if (utype != TREE_TYPE (var))
- tmp3 = make_rename_temp (utype, "SR");
- else
- tmp3 = var;
- stmt = gimple_build_assign (tmp3, fold_build2 (BIT_IOR_EXPR, utype,
- tmp, tmp2));
- gimple_seq_add_stmt (&seq, stmt);
+ bool ret = false;
+
+ if (is_gimple_reg_type (lacc->type)
+ || lacc->grp_unscalarizable_region
+ || racc->grp_unscalarizable_region)
+ return false;
- if (tmp3 != var)
+ if (!lacc->first_child && !racc->first_child
+ && is_gimple_reg_type (racc->type))
{
- if (TREE_TYPE (var) == type)
- stmt = gimple_build_assign (var, fold_convert (type, tmp3));
- else
- stmt = gimple_build_assign (var, fold_build1 (VIEW_CONVERT_EXPR,
- TREE_TYPE (var), tmp3));
- gimple_seq_add_stmt (&seq, stmt);
+ duplicate_expr_for_different_base (lacc, racc);
+ lacc->type = racc->type;
+ return false;
}
- return seq;
-}
-
-/* Expand an assignment of SRC to the scalarized representation of
- ELT. If it is a field group, try to widen the assignment to cover
- the full variable. */
-
-static gimple_seq
-sra_build_elt_assignment (struct sra_elt *elt, tree src)
-{
- tree dst = elt->replacement;
- tree var, tmp, cst, cst2;
- gimple stmt;
- gimple_seq seq;
-
- if (TREE_CODE (dst) != BIT_FIELD_REF
- || !elt->in_bitfld_block)
- return sra_build_assignment (REPLDUP (dst), src);
-
- var = TREE_OPERAND (dst, 0);
-
- /* Try to widen the assignment to the entire variable.
- We need the source to be a BIT_FIELD_REF as well, such that, for
- BIT_FIELD_REF<d,sz,dp> = BIT_FIELD_REF<s,sz,sp>,
- by design, conditions are met such that we can turn it into
- d = BIT_FIELD_REF<s,dw,sp-dp>. */
- if (elt->in_bitfld_block == 2
- && TREE_CODE (src) == BIT_FIELD_REF)
+ for (rchild = racc->first_child; rchild; rchild = rchild->next_sibling)
{
- tmp = src;
- cst = TYPE_SIZE (TREE_TYPE (var));
- cst2 = size_binop (MINUS_EXPR, TREE_OPERAND (src, 2),
- TREE_OPERAND (dst, 2));
+ struct access *new_acc = NULL;
+ HOST_WIDE_INT norm_offset = rchild->offset + norm_delta;
- src = TREE_OPERAND (src, 0);
+ if (rchild->grp_unscalarizable_region)
+ continue;
- /* Avoid full-width bit-fields. */
- if (integer_zerop (cst2)
- && tree_int_cst_equal (cst, TYPE_SIZE (TREE_TYPE (src))))
+ if (child_would_conflict_in_lacc (lacc, norm_offset, rchild->size,
+ &new_acc))
{
- if (INTEGRAL_TYPE_P (TREE_TYPE (src))
- && !TYPE_UNSIGNED (TREE_TYPE (src)))
- src = fold_convert (unsigned_type_for (TREE_TYPE (src)), src);
-
- /* If a single conversion won't do, we'll need a statement
- list. */
- if (TYPE_MAIN_VARIANT (TREE_TYPE (var))
- != TYPE_MAIN_VARIANT (TREE_TYPE (src)))
- {
- gimple_seq tmp_seq;
- seq = NULL;
-
- if (!INTEGRAL_TYPE_P (TREE_TYPE (src)))
- src = fold_build1 (VIEW_CONVERT_EXPR,
- lang_hooks.types.type_for_size
- (TREE_INT_CST_LOW
- (TYPE_SIZE (TREE_TYPE (src))),
- 1), src);
- gcc_assert (TYPE_UNSIGNED (TREE_TYPE (src)));
-
- tmp = make_rename_temp (TREE_TYPE (src), "SR");
- stmt = gimple_build_assign (tmp, src);
- gimple_seq_add_stmt (&seq, stmt);
-
- tmp_seq = sra_build_assignment (var,
- fold_convert (TREE_TYPE (var),
- tmp));
- gimple_seq_add_seq (&seq, tmp_seq);
-
- return seq;
- }
-
- src = fold_convert (TREE_TYPE (var), src);
- }
- else
- {
- src = fold_convert (TREE_TYPE (var), tmp);
+ if (new_acc && rchild->first_child)
+ ret |= propagate_subacesses_accross_link (new_acc, rchild);
+ continue;
}
- return sra_build_assignment (var, src);
+ new_acc = create_artificial_child_access (lacc, rchild, norm_offset);
+ if (racc->first_child)
+ propagate_subacesses_accross_link (new_acc, rchild);
+
+ ret = true;
}
- return sra_build_bf_assignment (dst, src);
+ return ret;
}
-/* Generate a set of assignment statements in *LIST_P to copy all
- instantiated elements under ELT to or from the equivalent structure
- rooted at EXPR. COPY_OUT controls the direction of the copy, with
- true meaning to copy out of EXPR into ELT. */
+/* Propagate all subaccesses across assignment links. */
static void
-generate_copy_inout (struct sra_elt *elt, bool copy_out, tree expr,
- gimple_seq *seq_p)
+propagate_all_subaccesses (void)
{
- struct sra_elt *c;
- gimple_seq tmp_seq;
- tree t;
-
- if (!copy_out && TREE_CODE (expr) == SSA_NAME
- && TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
+ while (work_queue_head)
{
- tree r, i;
+ struct access *racc = pop_access_from_work_queue ();
+ struct assign_link *link;
- c = lookup_element (elt, integer_zero_node, NULL, NO_INSERT);
- r = c->replacement;
- c = lookup_element (elt, integer_one_node, NULL, NO_INSERT);
- i = c->replacement;
+ gcc_assert (racc->first_link);
- t = build2 (COMPLEX_EXPR, elt->type, r, i);
- tmp_seq = sra_build_bf_assignment (expr, t);
- SSA_NAME_DEF_STMT (expr) = gimple_seq_last_stmt (tmp_seq);
- gimple_seq_add_seq (seq_p, tmp_seq);
- }
- else if (elt->replacement)
- {
- if (copy_out)
- tmp_seq = sra_build_elt_assignment (elt, expr);
- else
- tmp_seq = sra_build_bf_assignment (expr, REPLDUP (elt->replacement));
- gimple_seq_add_seq (seq_p, tmp_seq);
- }
- else
- {
- FOR_EACH_ACTUAL_CHILD (c, elt)
+ for (link = racc->first_link; link; link = link->next)
{
- t = generate_one_element_ref (c, unshare_expr (expr));
- generate_copy_inout (c, copy_out, t, seq_p);
+ struct access *lacc = link->lacc;
+
+ if (!bitmap_bit_p (candidate_bitmap, DECL_UID (lacc->base)))
+ continue;
+ lacc = lacc->group_representative;
+ if (propagate_subacesses_accross_link (lacc, racc)
+ && lacc->first_link)
+ add_access_to_work_queue (lacc);
}
}
}
-/* Generate a set of assignment statements in *LIST_P to copy all instantiated
- elements under SRC to their counterparts under DST. There must be a 1-1
- correspondence of instantiated elements. */
+/* Go through all accesses collected throughout the (intraprocedural) analysis
+ stage, exclude overlapping ones, identify representatives and build trees
+ out of them, making decisions about scalarization on the way. Return true
+ iff there are any to-be-scalarized variables after this stage. */
-static void
-generate_element_copy (struct sra_elt *dst, struct sra_elt *src, gimple_seq *seq_p)
+static bool
+analyze_all_variable_accesses (void)
{
- struct sra_elt *dc, *sc;
-
- FOR_EACH_ACTUAL_CHILD (dc, dst)
- {
- sc = lookup_element (src, dc->element, NULL, NO_INSERT);
- if (!sc && dc->in_bitfld_block == 2)
- {
- struct sra_elt *dcs;
-
- FOR_EACH_ACTUAL_CHILD (dcs, dc)
- {
- sc = lookup_element (src, dcs->element, NULL, NO_INSERT);
- gcc_assert (sc);
- generate_element_copy (dcs, sc, seq_p);
- }
+ tree var;
+ referenced_var_iterator rvi;
+ bool res = false;
- continue;
- }
+ FOR_EACH_REFERENCED_VAR (var, rvi)
+ if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
+ {
+ struct access *access;
- /* If DST and SRC are structs with the same elements, but do not have
- the same TYPE_MAIN_VARIANT, then lookup of DST FIELD_DECL in SRC
- will fail. Try harder by finding the corresponding FIELD_DECL
- in SRC. */
- if (!sc)
- {
- tree f;
-
- gcc_assert (useless_type_conversion_p (dst->type, src->type));
- gcc_assert (TREE_CODE (dc->element) == FIELD_DECL);
- for (f = TYPE_FIELDS (src->type); f ; f = TREE_CHAIN (f))
- if (simple_cst_equal (DECL_FIELD_OFFSET (f),
- DECL_FIELD_OFFSET (dc->element)) > 0
- && simple_cst_equal (DECL_FIELD_BIT_OFFSET (f),
- DECL_FIELD_BIT_OFFSET (dc->element)) > 0
- && simple_cst_equal (DECL_SIZE (f),
- DECL_SIZE (dc->element)) > 0
- && (useless_type_conversion_p (TREE_TYPE (dc->element),
- TREE_TYPE (f))
- || (POINTER_TYPE_P (TREE_TYPE (dc->element))
- && POINTER_TYPE_P (TREE_TYPE (f)))))
- break;
- gcc_assert (f != NULL_TREE);
- sc = lookup_element (src, f, NULL, NO_INSERT);
- }
+ access = sort_and_splice_var_accesses (var);
+ if (access)
+ build_access_trees (access);
+ else
+ disqualify_candidate (var,
+ "No or inhibitingly overlapping accesses.");
+ }
- generate_element_copy (dc, sc, seq_p);
- }
+ propagate_all_subaccesses ();
- if (dst->replacement)
- {
- gimple_seq tmp_seq;
+ FOR_EACH_REFERENCED_VAR (var, rvi)
+ if (bitmap_bit_p (candidate_bitmap, DECL_UID (var)))
+ {
+ struct access *access = get_first_repr_for_decl (var);
- gcc_assert (src->replacement);
+ if (analyze_access_trees (access))
+ {
+ res = true;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\nAccess trees for ");
+ print_generic_expr (dump_file, var, 0);
+ fprintf (dump_file, " (UID: %u): \n", DECL_UID (var));
+ dump_access_tree (dump_file, access);
+ fprintf (dump_file, "\n");
+ }
+ }
+ else
+ disqualify_candidate (var, "No scalar replacements to be created.");
+ }
- tmp_seq = sra_build_elt_assignment (dst, REPLDUP (src->replacement));
- gimple_seq_add_seq (seq_p, tmp_seq);
- }
+ return res;
}
-/* Generate a set of assignment statements in *LIST_P to zero all instantiated
- elements under ELT. In addition, do not assign to elements that have been
- marked VISITED but do reset the visited flag; this allows easy coordination
- with generate_element_init. */
+/* Return true iff a reference statement into aggregate AGG can be built for
+ every single to-be-replaced accesses that is a child of ACCESS, its sibling
+ or a child of its sibling. TOP_OFFSET is the offset from the processed
+ access subtree that has to be subtracted from offset of each access. */
-static void
-generate_element_zero (struct sra_elt *elt, gimple_seq *seq_p)
+static bool
+ref_expr_for_all_replacements_p (struct access *access, tree agg,
+ HOST_WIDE_INT top_offset)
{
- struct sra_elt *c;
-
- if (elt->visited)
- {
- elt->visited = false;
- return;
- }
-
- if (!elt->in_bitfld_block)
- FOR_EACH_ACTUAL_CHILD (c, elt)
- generate_element_zero (c, seq_p);
-
- if (elt->replacement)
+ do
{
- tree t;
- gimple_seq tmp_seq;
+ if (access->grp_to_be_replaced
+ && !build_ref_for_offset (NULL, TREE_TYPE (agg),
+ access->offset - top_offset,
+ access->type, false))
+ return false;
- gcc_assert (elt->is_scalar);
- t = fold_convert (elt->type, integer_zero_node);
+ if (access->first_child
+ && !ref_expr_for_all_replacements_p (access->first_child, agg,
+ top_offset))
+ return false;
- tmp_seq = sra_build_elt_assignment (elt, t);
- gimple_seq_add_seq (seq_p, tmp_seq);
+ access = access->next_sibling;
}
+ while (access);
+
+ return true;
}
-/* Generate an assignment VAR = INIT, where INIT may need gimplification.
- Add the result to *LIST_P. */
+/* Generate statements copying scalar replacements of accesses within a subtree
+ into or out of AGG. ACCESS is the first child of the root of the subtree to
+ be processed. AGG is an aggregate type expression (can be a declaration but
+ does not have to be, it can for example also be an indirect_ref).
+ TOP_OFFSET is the offset of the processed subtree which has to be subtracted
+ from offsets of individual accesses to get corresponding offsets for AGG.
+ If CHUNK_SIZE is non-null, copy only replacements in the interval
+ <start_offset, start_offset + chunk_size>, otherwise copy all. GSI is a
+ statement iterator used to place the new statements. WRITE should be true
+ when the statements should write from AGG to the replacement and false if
+ vice versa. if INSERT_AFTER is true, new statements will be added after the
+ current statement in GSI, they will be added before the statement
+ otherwise. */
static void
-generate_one_element_init (struct sra_elt *elt, tree init, gimple_seq *seq_p)
+generate_subtree_copies (struct access *access, tree agg,
+ HOST_WIDE_INT top_offset,
+ HOST_WIDE_INT start_offset, HOST_WIDE_INT chunk_size,
+ gimple_stmt_iterator *gsi, bool write,
+ bool insert_after)
{
- gimple_seq tmp_seq = sra_build_elt_assignment (elt, init);
- gimple_seq_add_seq (seq_p, tmp_seq);
-}
+ do
+ {
+ tree expr = unshare_expr (agg);
-/* Generate a set of assignment statements in *LIST_P to set all instantiated
- elements under ELT with the contents of the initializer INIT. In addition,
- mark all assigned elements VISITED; this allows easy coordination with
- generate_element_zero. Return false if we found a case we couldn't
- handle. */
+ if (chunk_size && access->offset >= start_offset + chunk_size)
+ return;
-static bool
-generate_element_init_1 (struct sra_elt *elt, tree init, gimple_seq *seq_p)
-{
- bool result = true;
- enum tree_code init_code;
- struct sra_elt *sub;
- tree t;
- unsigned HOST_WIDE_INT idx;
- tree value, purpose;
-
- /* We can be passed DECL_INITIAL of a static variable. It might have a
- conversion, which we strip off here. */
- STRIP_USELESS_TYPE_CONVERSION (init);
- init_code = TREE_CODE (init);
-
- if (elt->is_scalar)
- {
- if (elt->replacement)
+ if (access->grp_to_be_replaced
+ && (chunk_size == 0
+ || access->offset + access->size > start_offset))
{
- generate_one_element_init (elt, init, seq_p);
- elt->visited = true;
- }
- return result;
- }
+ tree repl = get_access_replacement (access);
+ bool ref_found;
+ gimple stmt;
- switch (init_code)
- {
- case COMPLEX_CST:
- case COMPLEX_EXPR:
- FOR_EACH_ACTUAL_CHILD (sub, elt)
- {
- if (sub->element == integer_zero_node)
- t = (init_code == COMPLEX_EXPR
- ? TREE_OPERAND (init, 0) : TREE_REALPART (init));
- else
- t = (init_code == COMPLEX_EXPR
- ? TREE_OPERAND (init, 1) : TREE_IMAGPART (init));
- result &= generate_element_init_1 (sub, t, seq_p);
- }
- break;
+ ref_found = build_ref_for_offset (&expr, TREE_TYPE (agg),
+ access->offset - top_offset,
+ access->type, false);
+ gcc_assert (ref_found);
- case CONSTRUCTOR:
- FOR_EACH_CONSTRUCTOR_ELT (CONSTRUCTOR_ELTS (init), idx, purpose, value)
- {
- /* Array constructors are routinely created with NULL indices. */
- if (purpose == NULL_TREE)
- {
- result = false;
- break;
- }
- if (TREE_CODE (purpose) == RANGE_EXPR)
+ if (write)
{
- tree lower = TREE_OPERAND (purpose, 0);
- tree upper = TREE_OPERAND (purpose, 1);
-
- while (1)
- {
- sub = lookup_element (elt, lower, NULL, NO_INSERT);
- if (sub != NULL)
- result &= generate_element_init_1 (sub, value, seq_p);
- if (tree_int_cst_equal (lower, upper))
- break;
- lower = int_const_binop (PLUS_EXPR, lower,
- integer_one_node, true);
- }
+ if (access->grp_partial_lhs)
+ expr = force_gimple_operand_gsi (gsi, expr, true, NULL_TREE,
+ !insert_after,
+ insert_after ? GSI_NEW_STMT
+ : GSI_SAME_STMT);
+ stmt = gimple_build_assign (repl, expr);
}
else
{
- sub = lookup_element (elt, purpose, NULL, NO_INSERT);
- if (sub != NULL)
- result &= generate_element_init_1 (sub, value, seq_p);
+ TREE_NO_WARNING (repl) = 1;
+ if (access->grp_partial_lhs)
+ repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
+ !insert_after,
+ insert_after ? GSI_NEW_STMT
+ : GSI_SAME_STMT);
+ stmt = gimple_build_assign (expr, repl);
}
+
+ if (insert_after)
+ gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
+ else
+ gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
+ update_stmt (stmt);
}
- break;
- default:
- elt->visited = true;
- result = false;
- }
+ if (access->first_child)
+ generate_subtree_copies (access->first_child, agg, top_offset,
+ start_offset, chunk_size, gsi,
+ write, insert_after);
- return result;
+ access = access->next_sibling;
+ }
+ while (access);
}
-/* A wrapper function for generate_element_init_1 that handles cleanup after
- gimplification. */
+/* Assign zero to all scalar replacements in an access subtree. ACCESS is the
+ the root of the subtree to be processed. GSI is the statement iterator used
+ for inserting statements which are added after the current statement if
+ INSERT_AFTER is true or before it otherwise. */
-static bool
-generate_element_init (struct sra_elt *elt, tree init, gimple_seq *seq_p)
-{
- bool ret;
- struct gimplify_ctx gctx;
+static void
+init_subtree_with_zero (struct access *access, gimple_stmt_iterator *gsi,
+ bool insert_after)
- push_gimplify_context (&gctx);
- ret = generate_element_init_1 (elt, init, seq_p);
- pop_gimplify_context (NULL);
+{
+ struct access *child;
- /* The replacement can expose previously unreferenced variables. */
- if (ret && *seq_p)
+ if (access->grp_to_be_replaced)
{
- gimple_stmt_iterator i;
+ gimple stmt;
- for (i = gsi_start (*seq_p); !gsi_end_p (i); gsi_next (&i))
- find_new_referenced_vars (gsi_stmt (i));
+ stmt = gimple_build_assign (get_access_replacement (access),
+ fold_convert (access->type,
+ integer_zero_node));
+ if (insert_after)
+ gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
+ else
+ gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
+ update_stmt (stmt);
}
- return ret;
-}
-
-/* Helper function to insert LIST before GSI, and set up line number info. */
-
-static void
-sra_insert_before (gimple_stmt_iterator *gsi, gimple_seq seq)
-{
- gimple stmt = gsi_stmt (*gsi);
-
- if (gimple_has_location (stmt))
- annotate_all_with_location (seq, gimple_location (stmt));
- gsi_insert_seq_before (gsi, seq, GSI_SAME_STMT);
+ for (child = access->first_child; child; child = child->next_sibling)
+ init_subtree_with_zero (child, gsi, insert_after);
}
-/* Similarly, but insert after GSI. Handles insertion onto edges as well. */
+/* Search for an access representative for the given expression EXPR and
+ return it or NULL if it cannot be found. */
-static void
-sra_insert_after (gimple_stmt_iterator *gsi, gimple_seq seq)
+static struct access *
+get_access_for_expr (tree expr)
{
- gimple stmt = gsi_stmt (*gsi);
+ HOST_WIDE_INT offset, size, max_size;
+ tree base;
- if (gimple_has_location (stmt))
- annotate_all_with_location (seq, gimple_location (stmt));
+ /* FIXME: This should not be necessary but Ada produces V_C_Es with a type of
+ a different size than the size of its argument and we need the latter
+ one. */
+ if (TREE_CODE (expr) == VIEW_CONVERT_EXPR)
+ expr = TREE_OPERAND (expr, 0);
- if (stmt_ends_bb_p (stmt))
- insert_edge_copies_seq (seq, gsi_bb (*gsi));
- else
- gsi_insert_seq_after (gsi, seq, GSI_SAME_STMT);
-}
+ base = get_ref_base_and_extent (expr, &offset, &size, &max_size);
+ if (max_size == -1 || !DECL_P (base))
+ return NULL;
-/* Similarly, but replace the statement at GSI. */
+ if (!bitmap_bit_p (candidate_bitmap, DECL_UID (base)))
+ return NULL;
-static void
-sra_replace (gimple_stmt_iterator *gsi, gimple_seq seq)
-{
- sra_insert_before (gsi, seq);
- unlink_stmt_vdef (gsi_stmt (*gsi));
- gsi_remove (gsi, false);
- if (gsi_end_p (*gsi))
- *gsi = gsi_last (gsi_seq (*gsi));
- else
- gsi_prev (gsi);
+ return get_var_base_offset_size_access (base, offset, max_size);
}
-/* Data structure that bitfield_overlaps_p fills in with information
- about the element passed in and how much of it overlaps with the
- bit-range passed it to. */
-
-struct bitfield_overlap_info
-{
- /* The bit-length of an element. */
- tree field_len;
-
- /* The bit-position of the element in its parent. */
- tree field_pos;
-
- /* The number of bits of the element that overlap with the incoming
- bit range. */
- tree overlap_len;
-
- /* The first bit of the element that overlaps with the incoming bit
- range. */
- tree overlap_pos;
-};
-
-/* Return true if a BIT_FIELD_REF<(FLD->parent), BLEN, BPOS>
- expression (referenced as BF below) accesses any of the bits in FLD,
- false if it doesn't. If DATA is non-null, its field_len and
- field_pos are filled in such that BIT_FIELD_REF<(FLD->parent),
- field_len, field_pos> (referenced as BFLD below) represents the
- entire field FLD->element, and BIT_FIELD_REF<BFLD, overlap_len,
- overlap_pos> represents the portion of the entire field that
- overlaps with BF. */
+/* Callback for scan_function. Replace the expression EXPR with a scalar
+ replacement if there is one and generate other statements to do type
+ conversion or subtree copying if necessary. GSI is used to place newly
+ created statements, WRITE is true if the expression is being written to (it
+ is on a LHS of a statement or output in an assembly statement). */
static bool
-bitfield_overlaps_p (tree blen, tree bpos, struct sra_elt *fld,
- struct bitfield_overlap_info *data)
+sra_modify_expr (tree *expr, gimple_stmt_iterator *gsi, bool write,
+ void *data ATTRIBUTE_UNUSED)
{
- tree flen, fpos;
- bool ret;
+ struct access *access;
+ tree type, bfr;
- if (TREE_CODE (fld->element) == FIELD_DECL)
- {
- flen = fold_convert (bitsizetype, DECL_SIZE (fld->element));
- fpos = fold_convert (bitsizetype, DECL_FIELD_OFFSET (fld->element));
- fpos = size_binop (MULT_EXPR, fpos, bitsize_int (BITS_PER_UNIT));
- fpos = size_binop (PLUS_EXPR, fpos, DECL_FIELD_BIT_OFFSET (fld->element));
- }
- else if (TREE_CODE (fld->element) == BIT_FIELD_REF)
+ if (TREE_CODE (*expr) == BIT_FIELD_REF)
{
- flen = fold_convert (bitsizetype, TREE_OPERAND (fld->element, 1));
- fpos = fold_convert (bitsizetype, TREE_OPERAND (fld->element, 2));
- }
- else if (TREE_CODE (fld->element) == INTEGER_CST)
- {
- tree domain_type = TYPE_DOMAIN (TREE_TYPE (fld->parent->element));
- flen = fold_convert (bitsizetype, TYPE_SIZE (fld->type));
- fpos = fold_convert (bitsizetype, fld->element);
- if (domain_type && TYPE_MIN_VALUE (domain_type))
- fpos = size_binop (MINUS_EXPR, fpos,
- fold_convert (bitsizetype,
- TYPE_MIN_VALUE (domain_type)));
- fpos = size_binop (MULT_EXPR, flen, fpos);
+ bfr = *expr;
+ expr = &TREE_OPERAND (*expr, 0);
}
else
- gcc_unreachable ();
-
- gcc_assert (host_integerp (blen, 1)
- && host_integerp (bpos, 1)
- && host_integerp (flen, 1)
- && host_integerp (fpos, 1));
-
- ret = ((!tree_int_cst_lt (fpos, bpos)
- && tree_int_cst_lt (size_binop (MINUS_EXPR, fpos, bpos),
- blen))
- || (!tree_int_cst_lt (bpos, fpos)
- && tree_int_cst_lt (size_binop (MINUS_EXPR, bpos, fpos),
- flen)));
+ bfr = NULL_TREE;
- if (!ret)
- return ret;
-
- if (data)
- {
- tree bend, fend;
-
- data->field_len = flen;
- data->field_pos = fpos;
-
- fend = size_binop (PLUS_EXPR, fpos, flen);
- bend = size_binop (PLUS_EXPR, bpos, blen);
-
- if (tree_int_cst_lt (bend, fend))
- data->overlap_len = size_binop (MINUS_EXPR, bend, fpos);
- else
- data->overlap_len = NULL;
-
- if (tree_int_cst_lt (fpos, bpos))
- {
- data->overlap_pos = size_binop (MINUS_EXPR, bpos, fpos);
- data->overlap_len = size_binop (MINUS_EXPR,
- data->overlap_len
- ? data->overlap_len
- : data->field_len,
- data->overlap_pos);
- }
- else
- data->overlap_pos = NULL;
- }
-
- return ret;
-}
-
-/* Add to LISTP a sequence of statements that copies BLEN bits between
- VAR and the scalarized elements of ELT, starting a bit VPOS of VAR
- and at bit BPOS of ELT. The direction of the copy is given by
- TO_VAR. */
-
-static void
-sra_explode_bitfield_assignment (tree var, tree vpos, bool to_var,
- gimple_seq *seq_p, tree blen, tree bpos,
- struct sra_elt *elt)
-{
- struct sra_elt *fld;
- struct bitfield_overlap_info flp;
+ if (TREE_CODE (*expr) == REALPART_EXPR || TREE_CODE (*expr) == IMAGPART_EXPR)
+ expr = &TREE_OPERAND (*expr, 0);
+ access = get_access_for_expr (*expr);
+ if (!access)
+ return false;
+ type = TREE_TYPE (*expr);
- FOR_EACH_ACTUAL_CHILD (fld, elt)
+ if (access->grp_to_be_replaced)
{
- tree flen, fpos;
-
- if (!bitfield_overlaps_p (blen, bpos, fld, &flp))
- continue;
-
- flen = flp.overlap_len ? flp.overlap_len : flp.field_len;
- fpos = flp.overlap_pos ? flp.overlap_pos : bitsize_int (0);
-
- if (fld->replacement)
+ tree repl = get_access_replacement (access);
+ /* If we replace a non-register typed access simply use the original
+ access expression to extract the scalar component afterwards.
+ This happens if scalarizing a function return value or parameter
+ like in gcc.c-torture/execute/20041124-1.c, 20050316-1.c and
+ gcc.c-torture/compile/20011217-1.c. */
+ if (!is_gimple_reg_type (type))
{
- tree infld, invar, type;
- gimple_seq st;
-
- infld = fld->replacement;
-
- type = unsigned_type_for (TREE_TYPE (infld));
- if (TYPE_PRECISION (type) != TREE_INT_CST_LOW (flen))
- type = build_nonstandard_integer_type (TREE_INT_CST_LOW (flen), 1);
-
- if (TREE_CODE (infld) == BIT_FIELD_REF)
+ gimple stmt;
+ if (write)
{
- fpos = size_binop (PLUS_EXPR, fpos, TREE_OPERAND (infld, 2));
- infld = TREE_OPERAND (infld, 0);
+ tree ref = unshare_expr (access->expr);
+ if (access->grp_partial_lhs)
+ ref = force_gimple_operand_gsi (gsi, ref, true, NULL_TREE,
+ false, GSI_NEW_STMT);
+ stmt = gimple_build_assign (repl, ref);
+ gsi_insert_after (gsi, stmt, GSI_NEW_STMT);
}
- else if (BYTES_BIG_ENDIAN && DECL_P (fld->element)
- && !tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (infld)),
- DECL_SIZE (fld->element)))
+ else
{
- fpos = size_binop (PLUS_EXPR, fpos,
- TYPE_SIZE (TREE_TYPE (infld)));
- fpos = size_binop (MINUS_EXPR, fpos,
- DECL_SIZE (fld->element));
+ if (access->grp_partial_lhs)
+ repl = force_gimple_operand_gsi (gsi, repl, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+ stmt = gimple_build_assign (unshare_expr (access->expr), repl);
+ gsi_insert_before (gsi, stmt, GSI_SAME_STMT);
}
-
- infld = fold_build3 (BIT_FIELD_REF, type, infld, flen, fpos);
-
- invar = size_binop (MINUS_EXPR, flp.field_pos, bpos);
- if (flp.overlap_pos)
- invar = size_binop (PLUS_EXPR, invar, flp.overlap_pos);
- invar = size_binop (PLUS_EXPR, invar, vpos);
-
- invar = fold_build3 (BIT_FIELD_REF, type, var, flen, invar);
-
- if (to_var)
- st = sra_build_bf_assignment (invar, infld);
- else
- st = sra_build_bf_assignment (infld, invar);
-
- gimple_seq_add_seq (seq_p, st);
}
else
{
- tree sub = size_binop (MINUS_EXPR, flp.field_pos, bpos);
- sub = size_binop (PLUS_EXPR, vpos, sub);
- if (flp.overlap_pos)
- sub = size_binop (PLUS_EXPR, sub, flp.overlap_pos);
+ gcc_assert (useless_type_conversion_p (type, access->type));
+ *expr = repl;
+ }
+ }
- sra_explode_bitfield_assignment (var, sub, to_var, seq_p,
- flen, fpos, fld);
+ if (access->first_child)
+ {
+ HOST_WIDE_INT start_offset, chunk_size;
+ if (bfr
+ && host_integerp (TREE_OPERAND (bfr, 1), 1)
+ && host_integerp (TREE_OPERAND (bfr, 2), 1))
+ {
+ start_offset = tree_low_cst (TREE_OPERAND (bfr, 1), 1);
+ chunk_size = tree_low_cst (TREE_OPERAND (bfr, 2), 1);
}
+ else
+ start_offset = chunk_size = 0;
+
+ generate_subtree_copies (access->first_child, access->base, 0,
+ start_offset, chunk_size, gsi, write, write);
}
+ return true;
}
-/* Add to LISTBEFOREP statements that copy scalarized members of ELT
- that overlap with BIT_FIELD_REF<(ELT->element), BLEN, BPOS> back
- into the full variable, and to LISTAFTERP, if non-NULL, statements
- that copy the (presumably modified) overlapping portions of the
- full variable back to the scalarized variables. */
+/* Store all replacements in the access tree rooted in TOP_RACC either to their
+ base aggregate if there are unscalarized data or directly to LHS
+ otherwise. */
static void
-sra_sync_for_bitfield_assignment (gimple_seq *seq_before_p,
- gimple_seq *seq_after_p,
- tree blen, tree bpos,
- struct sra_elt *elt)
+handle_unscalarized_data_in_subtree (struct access *top_racc, tree lhs,
+ gimple_stmt_iterator *gsi)
{
- struct sra_elt *fld;
- struct bitfield_overlap_info flp;
-
- FOR_EACH_ACTUAL_CHILD (fld, elt)
- if (bitfield_overlaps_p (blen, bpos, fld, &flp))
- {
- if (fld->replacement || (!flp.overlap_len && !flp.overlap_pos))
- {
- generate_copy_inout (fld, false, generate_element_ref (fld),
- seq_before_p);
- mark_no_warning (fld);
- if (seq_after_p)
- generate_copy_inout (fld, true, generate_element_ref (fld),
- seq_after_p);
- }
- else
- {
- tree flen = flp.overlap_len ? flp.overlap_len : flp.field_len;
- tree fpos = flp.overlap_pos ? flp.overlap_pos : bitsize_int (0);
-
- sra_sync_for_bitfield_assignment (seq_before_p, seq_after_p,
- flen, fpos, fld);
- }
- }
+ if (top_racc->grp_unscalarized_data)
+ generate_subtree_copies (top_racc->first_child, top_racc->base, 0, 0, 0,
+ gsi, false, false);
+ else
+ generate_subtree_copies (top_racc->first_child, lhs, top_racc->offset,
+ 0, 0, gsi, false, false);
}
-/* Scalarize a USE. To recap, this is either a simple reference to ELT,
- if elt is scalar, or some occurrence of ELT that requires a complete
- aggregate. IS_OUTPUT is true if ELT is being modified. */
+
+/* Try to generate statements to load all sub-replacements in an access
+ (sub)tree (LACC is the first child) from scalar replacements in the TOP_RACC
+ (sub)tree. If that is not possible, refresh the TOP_RACC base aggregate and
+ load the accesses from it. LEFT_OFFSET is the offset of the left whole
+ subtree being copied, RIGHT_OFFSET is the same thing for the right subtree.
+ GSI is stmt iterator used for statement insertions. *REFRESHED is true iff
+ the rhs top aggregate has already been refreshed by contents of its scalar
+ reductions and is set to true if this function has to do it. */
static void
-scalarize_use (struct sra_elt *elt, tree *expr_p, gimple_stmt_iterator *gsi,
- bool is_output, bool use_all)
+load_assign_lhs_subreplacements (struct access *lacc, struct access *top_racc,
+ HOST_WIDE_INT left_offset,
+ HOST_WIDE_INT right_offset,
+ gimple_stmt_iterator *old_gsi,
+ gimple_stmt_iterator *new_gsi,
+ bool *refreshed, tree lhs)
{
- gimple stmt = gsi_stmt (*gsi);
- tree bfexpr;
-
- if (elt->replacement)
- {
- tree replacement = elt->replacement;
-
- /* If we have a replacement, then updating the reference is as
- simple as modifying the existing statement in place. */
- if (is_output
- && TREE_CODE (elt->replacement) == BIT_FIELD_REF
- && is_gimple_reg (TREE_OPERAND (elt->replacement, 0))
- && is_gimple_assign (stmt)
- && gimple_assign_lhs_ptr (stmt) == expr_p)
- {
- gimple_seq newseq;
- /* RHS must be a single operand. */
- gcc_assert (gimple_assign_single_p (stmt));
- newseq = sra_build_elt_assignment (elt, gimple_assign_rhs1 (stmt));
- sra_replace (gsi, newseq);
- return;
- }
- else if (!is_output
- && TREE_CODE (elt->replacement) == BIT_FIELD_REF
- && is_gimple_assign (stmt)
- && gimple_assign_rhs1_ptr (stmt) == expr_p)
- {
- tree tmp = make_rename_temp
- (TREE_TYPE (gimple_assign_lhs (stmt)), "SR");
- gimple_seq newseq = sra_build_assignment (tmp, REPLDUP (elt->replacement));
-
- sra_insert_before (gsi, newseq);
- replacement = tmp;
- }
- if (is_output)
- update_stmt_if_modified (stmt);
- *expr_p = REPLDUP (replacement);
- update_stmt (stmt);
- }
- else if (use_all && is_output
- && is_gimple_assign (stmt)
- && TREE_CODE (bfexpr
- = gimple_assign_lhs (stmt)) == BIT_FIELD_REF
- && &TREE_OPERAND (bfexpr, 0) == expr_p
- && INTEGRAL_TYPE_P (TREE_TYPE (bfexpr))
- && TREE_CODE (TREE_TYPE (*expr_p)) == RECORD_TYPE)
+ do
{
- gimple_seq seq_before = NULL;
- gimple_seq seq_after = NULL;
- tree blen = fold_convert (bitsizetype, TREE_OPERAND (bfexpr, 1));
- tree bpos = fold_convert (bitsizetype, TREE_OPERAND (bfexpr, 2));
- bool update = false;
-
- if (!elt->use_block_copy)
+ if (lacc->grp_to_be_replaced)
{
- tree type = TREE_TYPE (bfexpr);
- tree var = make_rename_temp (type, "SR"), tmp, vpos;
- gimple st;
+ struct access *racc;
+ HOST_WIDE_INT offset = lacc->offset - left_offset + right_offset;
+ gimple stmt;
+ tree rhs;
- gimple_assign_set_lhs (stmt, var);
- update = true;
-
- if (!TYPE_UNSIGNED (type))
+ racc = find_access_in_subtree (top_racc, offset, lacc->size);
+ if (racc && racc->grp_to_be_replaced)
{
- type = unsigned_type_for (type);
- tmp = make_rename_temp (type, "SR");
- st = gimple_build_assign (tmp, fold_convert (type, var));
- gimple_seq_add_stmt (&seq_after, st);
- var = tmp;
+ rhs = get_access_replacement (racc);
+ if (!useless_type_conversion_p (lacc->type, racc->type))
+ rhs = fold_build1 (VIEW_CONVERT_EXPR, lacc->type, rhs);
}
-
- /* If VAR is wider than BLEN bits, it is padded at the
- most-significant end. We want to set VPOS such that
- <BIT_FIELD_REF VAR BLEN VPOS> would refer to the
- least-significant BLEN bits of VAR. */
- if (BYTES_BIG_ENDIAN)
- vpos = size_binop (MINUS_EXPR, TYPE_SIZE (type), blen);
else
- vpos = bitsize_int (0);
- sra_explode_bitfield_assignment
- (var, vpos, false, &seq_after, blen, bpos, elt);
- }
- else
- sra_sync_for_bitfield_assignment
- (&seq_before, &seq_after, blen, bpos, elt);
-
- if (seq_before)
- {
- mark_all_v_defs_seq (seq_before);
- sra_insert_before (gsi, seq_before);
- }
- if (seq_after)
- {
- mark_all_v_defs_seq (seq_after);
- sra_insert_after (gsi, seq_after);
- }
-
- if (update)
- update_stmt (stmt);
- }
- else if (use_all && !is_output
- && is_gimple_assign (stmt)
- && TREE_CODE (bfexpr
- = gimple_assign_rhs1 (stmt)) == BIT_FIELD_REF
- && &TREE_OPERAND (gimple_assign_rhs1 (stmt), 0) == expr_p
- && INTEGRAL_TYPE_P (TREE_TYPE (bfexpr))
- && TREE_CODE (TREE_TYPE (*expr_p)) == RECORD_TYPE)
- {
- gimple_seq seq = NULL;
- tree blen = fold_convert (bitsizetype, TREE_OPERAND (bfexpr, 1));
- tree bpos = fold_convert (bitsizetype, TREE_OPERAND (bfexpr, 2));
- bool update = false;
-
- if (!elt->use_block_copy)
- {
- tree type = TREE_TYPE (bfexpr);
- tree var = make_rename_temp (type, "SR"), tmp, vpos;
- gimple st = NULL;
-
- gimple_assign_set_rhs1 (stmt, var);
- update = true;
-
- if (!TYPE_UNSIGNED (type))
{
- type = unsigned_type_for (type);
- tmp = make_rename_temp (type, "SR");
- st = gimple_build_assign (var,
- fold_convert (TREE_TYPE (var), tmp));
- var = tmp;
- }
+ bool repl_found;
- gimple_seq_add_stmt (&seq,
- gimple_build_assign
- (var, build_int_cst_wide (type, 0, 0)));
+ /* No suitable access on the right hand side, need to load from
+ the aggregate. See if we have to update it first... */
+ if (!*refreshed)
+ {
+ gcc_assert (top_racc->first_child);
+ handle_unscalarized_data_in_subtree (top_racc, lhs, old_gsi);
+ *refreshed = true;
+ }
- /* If VAR is wider than BLEN bits, it is padded at the
- most-significant end. We want to set VPOS such that
- <BIT_FIELD_REF VAR BLEN VPOS> would refer to the
- least-significant BLEN bits of VAR. */
- if (BYTES_BIG_ENDIAN)
- vpos = size_binop (MINUS_EXPR, TYPE_SIZE (type), blen);
- else
- vpos = bitsize_int (0);
- sra_explode_bitfield_assignment
- (var, vpos, true, &seq, blen, bpos, elt);
+ rhs = unshare_expr (top_racc->base);
+ repl_found = build_ref_for_offset (&rhs,
+ TREE_TYPE (top_racc->base),
+ lacc->offset - left_offset,
+ lacc->type, false);
+ gcc_assert (repl_found);
+ }
- if (st)
- gimple_seq_add_stmt (&seq, st);
+ stmt = gimple_build_assign (get_access_replacement (lacc), rhs);
+ gsi_insert_after (new_gsi, stmt, GSI_NEW_STMT);
+ update_stmt (stmt);
}
- else
- sra_sync_for_bitfield_assignment
- (&seq, NULL, blen, bpos, elt);
-
- if (seq)
+ else if (lacc->grp_read && !lacc->grp_covered && !*refreshed)
{
- mark_all_v_defs_seq (seq);
- sra_insert_before (gsi, seq);
+ handle_unscalarized_data_in_subtree (top_racc, lhs, old_gsi);
+ *refreshed = true;
}
- if (update)
- update_stmt (stmt);
- }
- else
- {
- gimple_seq seq = NULL;
-
- /* Otherwise we need some copies. If ELT is being read, then we
- want to store all (modified) sub-elements back into the
- structure before the reference takes place. If ELT is being
- written, then we want to load the changed values back into
- our shadow variables. */
- /* ??? We don't check modified for reads, we just always write all of
- the values. We should be able to record the SSA number of the VOP
- for which the values were last read. If that number matches the
- SSA number of the VOP in the current statement, then we needn't
- emit an assignment. This would also eliminate double writes when
- a structure is passed as more than one argument to a function call.
- This optimization would be most effective if sra_walk_function
- processed the blocks in dominator order. */
-
- generate_copy_inout (elt, is_output, generate_element_ref (elt), &seq);
- if (seq == NULL)
- return;
- mark_all_v_defs_seq (seq);
- if (is_output)
- sra_insert_after (gsi, seq);
- else
- {
- sra_insert_before (gsi, seq);
- if (use_all)
- mark_no_warning (elt);
- }
+ if (lacc->first_child)
+ load_assign_lhs_subreplacements (lacc->first_child, top_racc,
+ left_offset, right_offset,
+ old_gsi, new_gsi, refreshed, lhs);
+ lacc = lacc->next_sibling;
}
+ while (lacc);
}
-/* Scalarize a COPY. To recap, this is an assignment statement between
- two scalarizable references, LHS_ELT and RHS_ELT. */
+/* Modify assignments with a CONSTRUCTOR on their RHS. STMT contains a pointer
+ to the assignment and GSI is the statement iterator pointing at it. Returns
+ the same values as sra_modify_assign. */
-static void
-scalarize_copy (struct sra_elt *lhs_elt, struct sra_elt *rhs_elt,
- gimple_stmt_iterator *gsi)
+static enum scan_assign_result
+sra_modify_constructor_assign (gimple *stmt, gimple_stmt_iterator *gsi)
{
- gimple_seq seq;
- gimple stmt;
-
- if (lhs_elt->replacement && rhs_elt->replacement)
- {
- /* If we have two scalar operands, modify the existing statement. */
- stmt = gsi_stmt (*gsi);
+ tree lhs = gimple_assign_lhs (*stmt);
+ struct access *acc;
- /* See the commentary in sra_walk_function concerning
- RETURN_EXPR, and why we should never see one here. */
- gcc_assert (is_gimple_assign (stmt));
- gcc_assert (gimple_assign_copy_p (stmt));
+ acc = get_access_for_expr (lhs);
+ if (!acc)
+ return SRA_SA_NONE;
-
- gimple_assign_set_lhs (stmt, lhs_elt->replacement);
- gimple_assign_set_rhs1 (stmt, REPLDUP (rhs_elt->replacement));
- update_stmt (stmt);
- }
- else if (lhs_elt->use_block_copy || rhs_elt->use_block_copy)
+ if (VEC_length (constructor_elt,
+ CONSTRUCTOR_ELTS (gimple_assign_rhs1 (*stmt))) > 0)
{
- /* If either side requires a block copy, then sync the RHS back
- to the original structure, leave the original assignment
- statement (which will perform the block copy), then load the
- LHS values out of its now-updated original structure. */
- /* ??? Could perform a modified pair-wise element copy. That
- would at least allow those elements that are instantiated in
- both structures to be optimized well. */
-
- seq = NULL;
- generate_copy_inout (rhs_elt, false,
- generate_element_ref (rhs_elt), &seq);
- if (seq)
- {
- mark_all_v_defs_seq (seq);
- sra_insert_before (gsi, seq);
- }
+ /* I have never seen this code path trigger but if it can happen the
+ following should handle it gracefully. */
+ if (access_has_children_p (acc))
+ generate_subtree_copies (acc->first_child, acc->base, 0, 0, 0, gsi,
+ true, true);
+ return SRA_SA_PROCESSED;
+ }
- seq = NULL;
- generate_copy_inout (lhs_elt, true,
- generate_element_ref (lhs_elt), &seq);
- if (seq)
- {
- mark_all_v_defs_seq (seq);
- sra_insert_after (gsi, seq);
- }
+ if (acc->grp_covered)
+ {
+ init_subtree_with_zero (acc, gsi, false);
+ unlink_stmt_vdef (*stmt);
+ gsi_remove (gsi, true);
+ return SRA_SA_REMOVED;
}
else
{
- /* Otherwise both sides must be fully instantiated. In which
- case perform pair-wise element assignments and replace the
- original block copy statement. */
-
- stmt = gsi_stmt (*gsi);
- update_stmt_if_modified (stmt);
-
- seq = NULL;
- generate_element_copy (lhs_elt, rhs_elt, &seq);
- gcc_assert (seq);
- mark_all_v_defs_seq (seq);
- sra_replace (gsi, seq);
+ init_subtree_with_zero (acc, gsi, true);
+ return SRA_SA_PROCESSED;
}
}
-/* Scalarize an INIT. To recap, this is an assignment to a scalarizable
- reference from some form of constructor: CONSTRUCTOR, COMPLEX_CST or
- COMPLEX_EXPR. If RHS is NULL, it should be treated as an empty
- CONSTRUCTOR. */
-static void
-scalarize_init (struct sra_elt *lhs_elt, tree rhs, gimple_stmt_iterator *gsi)
+/* Callback of scan_function to process assign statements. It examines both
+ sides of the statement, replaces them with a scalare replacement if there is
+ one and generating copying of replacements if scalarized aggregates have been
+ used in the assignment. STMT is a pointer to the assign statement, GSI is
+ used to hold generated statements for type conversions and subtree
+ copying. */
+
+static enum scan_assign_result
+sra_modify_assign (gimple *stmt, gimple_stmt_iterator *gsi,
+ void *data ATTRIBUTE_UNUSED)
{
- bool result = true;
- gimple_seq seq = NULL, init_seq = NULL;
+ struct access *lacc, *racc;
+ tree lhs, rhs;
+ bool modify_this_stmt = false;
+ bool force_gimple_rhs = false;
- /* Generate initialization statements for all members extant in the RHS. */
- if (rhs)
+ if (!gimple_assign_single_p (*stmt))
+ return SRA_SA_NONE;
+ lhs = gimple_assign_lhs (*stmt);
+ rhs = gimple_assign_rhs1 (*stmt);
+
+ if (TREE_CODE (rhs) == CONSTRUCTOR)
+ return sra_modify_constructor_assign (stmt, gsi);
+
+ if (TREE_CODE (rhs) == REALPART_EXPR || TREE_CODE (lhs) == REALPART_EXPR
+ || TREE_CODE (rhs) == IMAGPART_EXPR || TREE_CODE (lhs) == IMAGPART_EXPR
+ || TREE_CODE (rhs) == BIT_FIELD_REF || TREE_CODE (lhs) == BIT_FIELD_REF)
{
- /* Unshare the expression just in case this is from a decl's initial. */
- rhs = unshare_expr (rhs);
- result = generate_element_init (lhs_elt, rhs, &init_seq);
+ modify_this_stmt = sra_modify_expr (gimple_assign_rhs1_ptr (*stmt),
+ gsi, false, data);
+ modify_this_stmt |= sra_modify_expr (gimple_assign_lhs_ptr (*stmt),
+ gsi, true, data);
+ return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
}
- if (!result)
+ lacc = get_access_for_expr (lhs);
+ racc = get_access_for_expr (rhs);
+ if (!lacc && !racc)
+ return SRA_SA_NONE;
+
+ if (lacc && lacc->grp_to_be_replaced)
{
- /* If we failed to convert the entire initializer, then we must
- leave the structure assignment in place and must load values
- from the structure into the slots for which we did not find
- constants. The easiest way to do this is to generate a complete
- copy-out, and then follow that with the constant assignments
- that we were able to build. DCE will clean things up. */
- gimple_seq seq0 = NULL;
- generate_copy_inout (lhs_elt, true, generate_element_ref (lhs_elt),
- &seq0);
- gimple_seq_add_seq (&seq0, seq);
- seq = seq0;
+ lhs = get_access_replacement (lacc);
+ gimple_assign_set_lhs (*stmt, lhs);
+ modify_this_stmt = true;
+ if (lacc->grp_partial_lhs)
+ force_gimple_rhs = true;
}
- else
+
+ if (racc && racc->grp_to_be_replaced)
{
- /* CONSTRUCTOR is defined such that any member not mentioned is assigned
- a zero value. Initialize the rest of the instantiated elements. */
- generate_element_zero (lhs_elt, &seq);
- gimple_seq_add_seq (&seq, init_seq);
+ rhs = get_access_replacement (racc);
+ modify_this_stmt = true;
+ if (racc->grp_partial_lhs)
+ force_gimple_rhs = true;
}
- if (lhs_elt->use_block_copy || !result)
+ if (modify_this_stmt)
{
- /* Since LHS is not fully instantiated, we must leave the structure
- assignment in place. Treating this case differently from a USE
- exposes constants to later optimizations. */
- if (seq)
+ if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
{
- mark_all_v_defs_seq (seq);
- sra_insert_after (gsi, seq);
+ /* If we can avoid creating a VIEW_CONVERT_EXPR do so.
+ ??? This should move to fold_stmt which we simply should
+ call after building a VIEW_CONVERT_EXPR here. */
+ if (AGGREGATE_TYPE_P (TREE_TYPE (lhs))
+ && !access_has_children_p (lacc))
+ {
+ tree expr = unshare_expr (lhs);
+ if (build_ref_for_offset (&expr, TREE_TYPE (lhs), racc->offset,
+ TREE_TYPE (rhs), false))
+ {
+ lhs = expr;
+ gimple_assign_set_lhs (*stmt, expr);
+ }
+ }
+ else if (AGGREGATE_TYPE_P (TREE_TYPE (rhs))
+ && !access_has_children_p (racc))
+ {
+ tree expr = unshare_expr (rhs);
+ if (build_ref_for_offset (&expr, TREE_TYPE (rhs), lacc->offset,
+ TREE_TYPE (lhs), false))
+ rhs = expr;
+ }
+ if (!useless_type_conversion_p (TREE_TYPE (lhs), TREE_TYPE (rhs)))
+ rhs = fold_build1 (VIEW_CONVERT_EXPR, TREE_TYPE (lhs), rhs);
}
- }
- else
- {
- /* The LHS is fully instantiated. The list of initializations
- replaces the original structure assignment. */
- gcc_assert (seq);
- update_stmt_if_modified (gsi_stmt (*gsi));
- mark_all_v_defs_seq (seq);
- sra_replace (gsi, seq);
- }
-}
-/* A subroutine of scalarize_ldst called via walk_tree. Set TREE_NO_TRAP
- on all INDIRECT_REFs. */
-
-static tree
-mark_notrap (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
-{
- tree t = *tp;
-
- if (TREE_CODE (t) == INDIRECT_REF)
- {
- TREE_THIS_NOTRAP (t) = 1;
- *walk_subtrees = 0;
+ if (force_gimple_rhs)
+ rhs = force_gimple_operand_gsi (gsi, rhs, true, NULL_TREE,
+ true, GSI_SAME_STMT);
+ if (gimple_assign_rhs1 (*stmt) != rhs)
+ {
+ gimple_assign_set_rhs_from_tree (gsi, rhs);
+ gcc_assert (*stmt == gsi_stmt (*gsi));
+ }
}
- else if (IS_TYPE_OR_DECL_P (t))
- *walk_subtrees = 0;
-
- return NULL;
-}
-
-/* Scalarize a LDST. To recap, this is an assignment between one scalarizable
- reference ELT and one non-scalarizable reference OTHER. IS_OUTPUT is true
- if ELT is on the left-hand side. */
-
-static void
-scalarize_ldst (struct sra_elt *elt, tree other,
- gimple_stmt_iterator *gsi, bool is_output)
-{
- /* Shouldn't have gotten called for a scalar. */
- gcc_assert (!elt->replacement);
- if (elt->use_block_copy)
- {
- /* Since ELT is not fully instantiated, we have to leave the
- block copy in place. Treat this as a USE. */
- scalarize_use (elt, NULL, gsi, is_output, false);
+ /* From this point on, the function deals with assignments in between
+ aggregates when at least one has scalar reductions of some of its
+ components. There are three possible scenarios: Both the LHS and RHS have
+ to-be-scalarized components, 2) only the RHS has or 3) only the LHS has.
+
+ In the first case, we would like to load the LHS components from RHS
+ components whenever possible. If that is not possible, we would like to
+ read it directly from the RHS (after updating it by storing in it its own
+ components). If there are some necessary unscalarized data in the LHS,
+ those will be loaded by the original assignment too. If neither of these
+ cases happen, the original statement can be removed. Most of this is done
+ by load_assign_lhs_subreplacements.
+
+ In the second case, we would like to store all RHS scalarized components
+ directly into LHS and if they cover the aggregate completely, remove the
+ statement too. In the third case, we want the LHS components to be loaded
+ directly from the RHS (DSE will remove the original statement if it
+ becomes redundant).
+
+ This is a bit complex but manageable when types match and when unions do
+ not cause confusion in a way that we cannot really load a component of LHS
+ from the RHS or vice versa (the access representing this level can have
+ subaccesses that are accessible only through a different union field at a
+ higher level - different from the one used in the examined expression).
+ Unions are fun.
+
+ Therefore, I specially handle a fourth case, happening when there is a
+ specific type cast or it is impossible to locate a scalarized subaccess on
+ the other side of the expression. If that happens, I simply "refresh" the
+ RHS by storing in it is scalarized components leave the original statement
+ there to do the copying and then load the scalar replacements of the LHS.
+ This is what the first branch does. */
+
+ if (contains_view_convert_expr_p (rhs) || contains_view_convert_expr_p (lhs)
+ || (access_has_children_p (racc)
+ && !ref_expr_for_all_replacements_p (racc, lhs, racc->offset))
+ || (access_has_children_p (lacc)
+ && !ref_expr_for_all_replacements_p (lacc, rhs, lacc->offset)))
+ {
+ if (access_has_children_p (racc))
+ generate_subtree_copies (racc->first_child, racc->base, 0, 0, 0,
+ gsi, false, false);
+ if (access_has_children_p (lacc))
+ generate_subtree_copies (lacc->first_child, lacc->base, 0, 0, 0,
+ gsi, true, true);
}
else
{
- /* The interesting case is when ELT is fully instantiated. In this
- case we can have each element stored/loaded directly to/from the
- corresponding slot in OTHER. This avoids a block copy. */
-
- gimple_seq seq = NULL;
- gimple stmt = gsi_stmt (*gsi);
-
- update_stmt_if_modified (stmt);
- generate_copy_inout (elt, is_output, other, &seq);
- gcc_assert (seq);
- mark_all_v_defs_seq (seq);
-
- /* Preserve EH semantics. */
- if (stmt_ends_bb_p (stmt))
+ if (access_has_children_p (lacc) && access_has_children_p (racc))
{
- gimple_stmt_iterator si;
- gimple first;
- gimple_seq blist = NULL;
- bool thr = stmt_could_throw_p (stmt);
-
- /* If the last statement of this BB created an EH edge
- before scalarization, we have to locate the first
- statement that can throw in the new statement list and
- use that as the last statement of this BB, such that EH
- semantics is preserved. All statements up to this one
- are added to the same BB. All other statements in the
- list will be added to normal outgoing edges of the same
- BB. If they access any memory, it's the same memory, so
- we can assume they won't throw. */
- si = gsi_start (seq);
- for (first = gsi_stmt (si);
- thr && !gsi_end_p (si) && !stmt_could_throw_p (first);
- first = gsi_stmt (si))
+ gimple_stmt_iterator orig_gsi = *gsi;
+ bool refreshed;
+
+ if (lacc->grp_read && !lacc->grp_covered)
{
- gsi_remove (&si, false);
- gimple_seq_add_stmt (&blist, first);
+ handle_unscalarized_data_in_subtree (racc, lhs, gsi);
+ refreshed = true;
}
+ else
+ refreshed = false;
- /* Extract the first remaining statement from LIST, this is
- the EH statement if there is one. */
- gsi_remove (&si, false);
-
- if (blist)
- sra_insert_before (gsi, blist);
-
- /* Replace the old statement with this new representative. */
- gsi_replace (gsi, first, true);
+ load_assign_lhs_subreplacements (lacc->first_child, racc,
+ lacc->offset, racc->offset,
+ &orig_gsi, gsi, &refreshed, lhs);
+ if (!refreshed || !racc->grp_unscalarized_data)
+ {
+ if (*stmt == gsi_stmt (*gsi))
+ gsi_next (gsi);
- if (!gsi_end_p (si))
+ unlink_stmt_vdef (*stmt);
+ gsi_remove (&orig_gsi, true);
+ return SRA_SA_REMOVED;
+ }
+ }
+ else
+ {
+ if (access_has_children_p (racc))
{
- /* If any reference would trap, then they all would. And more
- to the point, the first would. Therefore none of the rest
- will trap since the first didn't. Indicate this by
- iterating over the remaining statements and set
- TREE_THIS_NOTRAP in all INDIRECT_REFs. */
- do
+ if (!racc->grp_unscalarized_data)
{
- walk_gimple_stmt (&si, NULL, mark_notrap, NULL);
- gsi_next (&si);
+ generate_subtree_copies (racc->first_child, lhs,
+ racc->offset, 0, 0, gsi,
+ false, false);
+ gcc_assert (*stmt == gsi_stmt (*gsi));
+ unlink_stmt_vdef (*stmt);
+ gsi_remove (gsi, true);
+ return SRA_SA_REMOVED;
}
- while (!gsi_end_p (si));
-
- insert_edge_copies_seq (seq, gsi_bb (*gsi));
+ else
+ generate_subtree_copies (racc->first_child, lhs,
+ racc->offset, 0, 0, gsi, false, true);
}
+ else if (access_has_children_p (lacc))
+ generate_subtree_copies (lacc->first_child, rhs, lacc->offset,
+ 0, 0, gsi, true, true);
}
- else
- sra_replace (gsi, seq);
}
+ return modify_this_stmt ? SRA_SA_PROCESSED : SRA_SA_NONE;
}
-/* Generate initializations for all scalarizable parameters. */
+/* Generate statements initializing scalar replacements of parts of function
+ parameters. */
static void
-scalarize_parms (void)
+initialize_parameter_reductions (void)
{
+ gimple_stmt_iterator gsi;
gimple_seq seq = NULL;
- unsigned i;
- bitmap_iterator bi;
-
- EXECUTE_IF_SET_IN_BITMAP (needs_copy_in, 0, i, bi)
- {
- tree var = referenced_var (i);
- struct sra_elt *elt = lookup_element (NULL, var, NULL, NO_INSERT);
- generate_copy_inout (elt, true, var, &seq);
- }
+ tree parm;
- if (seq)
+ for (parm = DECL_ARGUMENTS (current_function_decl);
+ parm;
+ parm = TREE_CHAIN (parm))
{
- insert_edge_copies_seq (seq, ENTRY_BLOCK_PTR);
- mark_all_v_defs_seq (seq);
- }
-}
-
-/* Entry point to phase 4. Update the function to match replacements. */
-
-static void
-scalarize_function (void)
-{
- static const struct sra_walk_fns fns = {
- scalarize_use, scalarize_copy, scalarize_init, scalarize_ldst, false
- };
+ VEC (access_p, heap) *access_vec;
+ struct access *access;
- sra_walk_function (&fns);
- scalarize_parms ();
- gsi_commit_edge_inserts ();
-}
-
-
-/* Debug helper function. Print ELT in a nice human-readable format. */
+ if (!bitmap_bit_p (candidate_bitmap, DECL_UID (parm)))
+ continue;
+ access_vec = get_base_access_vector (parm);
+ if (!access_vec)
+ continue;
-static void
-dump_sra_elt_name (FILE *f, struct sra_elt *elt)
-{
- if (elt->parent && TREE_CODE (elt->parent->type) == COMPLEX_TYPE)
- {
- fputs (elt->element == integer_zero_node ? "__real__ " : "__imag__ ", f);
- dump_sra_elt_name (f, elt->parent);
- }
- else
- {
- if (elt->parent)
- dump_sra_elt_name (f, elt->parent);
- if (DECL_P (elt->element))
+ if (!seq)
{
- if (TREE_CODE (elt->element) == FIELD_DECL)
- fputc ('.', f);
- print_generic_expr (f, elt->element, dump_flags);
+ seq = gimple_seq_alloc ();
+ gsi = gsi_start (seq);
}
- else if (TREE_CODE (elt->element) == BIT_FIELD_REF)
- fprintf (f, "$B" HOST_WIDE_INT_PRINT_DEC "F" HOST_WIDE_INT_PRINT_DEC,
- tree_low_cst (TREE_OPERAND (elt->element, 2), 1),
- tree_low_cst (TREE_OPERAND (elt->element, 1), 1));
- else if (TREE_CODE (elt->element) == RANGE_EXPR)
- fprintf (f, "["HOST_WIDE_INT_PRINT_DEC".."HOST_WIDE_INT_PRINT_DEC"]",
- TREE_INT_CST_LOW (TREE_OPERAND (elt->element, 0)),
- TREE_INT_CST_LOW (TREE_OPERAND (elt->element, 1)));
- else
- fprintf (f, "[" HOST_WIDE_INT_PRINT_DEC "]",
- TREE_INT_CST_LOW (elt->element));
- }
-}
-/* Likewise, but callable from the debugger. */
+ for (access = VEC_index (access_p, access_vec, 0);
+ access;
+ access = access->next_grp)
+ generate_subtree_copies (access, parm, 0, 0, 0, &gsi, true, true);
+ }
-void
-debug_sra_elt_name (struct sra_elt *elt)
-{
- dump_sra_elt_name (stderr, elt);
- fputc ('\n', stderr);
+ if (seq)
+ gsi_insert_seq_on_edge_immediate (single_succ_edge (ENTRY_BLOCK_PTR), seq);
}
-static void
-sra_init_cache (void)
+/* The "main" function of intraprocedural SRA passes. Runs the analysis and if
+ it reveals there are components of some aggregates to be scalarized, it runs
+ the required transformations. */
+static unsigned int
+perform_intra_sra (void)
{
- if (sra_type_decomp_cache)
- return;
+ int ret = 0;
+ sra_initialize ();
- sra_type_decomp_cache = BITMAP_ALLOC (NULL);
- sra_type_inst_cache = BITMAP_ALLOC (NULL);
-}
+ if (!find_var_candidates ())
+ goto out;
+ if (!scan_function (build_access_from_expr, build_accesses_from_assign, NULL,
+ true, NULL))
+ goto out;
-/* Main entry point. */
+ if (!analyze_all_variable_accesses ())
+ goto out;
-static unsigned int
-tree_sra (void)
-{
- /* Initialize local variables. */
- gcc_obstack_init (&sra_obstack);
- sra_candidates = BITMAP_ALLOC (NULL);
- needs_copy_in = BITMAP_ALLOC (NULL);
- sra_init_cache ();
- sra_map = htab_create (101, sra_elt_hash, sra_elt_eq, NULL);
-
- /* Scan. If we find anything, instantiate and scalarize. */
- if (find_candidates_for_sra ())
- {
- scan_function ();
- decide_instantiations ();
- scalarize_function ();
- }
+ scan_function (sra_modify_expr, sra_modify_assign, NULL,
+ false, NULL);
+ initialize_parameter_reductions ();
+ ret = TODO_update_ssa;
- /* Free allocated memory. */
- htab_delete (sra_map);
- sra_map = NULL;
- BITMAP_FREE (sra_candidates);
- BITMAP_FREE (needs_copy_in);
- BITMAP_FREE (sra_type_decomp_cache);
- BITMAP_FREE (sra_type_inst_cache);
- obstack_free (&sra_obstack, NULL);
- return 0;
+ out:
+ sra_deinitialize ();
+ return ret;
}
+/* Perform early intraprocedural SRA. */
static unsigned int
-tree_sra_early (void)
+early_intra_sra (void)
{
- unsigned int ret;
-
- early_sra = true;
- ret = tree_sra ();
- early_sra = false;
+ sra_mode = SRA_MODE_EARLY_INTRA;
+ return perform_intra_sra ();
+}
- return ret;
+/* Perform "late" intraprocedural SRA. */
+static unsigned int
+late_intra_sra (void)
+{
+ sra_mode = SRA_MODE_INTRA;
+ return perform_intra_sra ();
}
+
static bool
-gate_sra (void)
+gate_intra_sra (void)
{
return flag_tree_sra != 0;
}
+
struct gimple_opt_pass pass_sra_early =
{
{
GIMPLE_PASS,
- "esra", /* name */
- gate_sra, /* gate */
- tree_sra_early, /* execute */
+ "esra", /* name */
+ gate_intra_sra, /* gate */
+ early_intra_sra, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
TV_TREE_SRA, /* tv_id */
- PROP_cfg | PROP_ssa, /* properties_required */
+ PROP_cfg | PROP_ssa, /* properties_required */
0, /* properties_provided */
- 0, /* properties_destroyed */
+ 0, /* properties_destroyed */
0, /* todo_flags_start */
TODO_dump_func
| TODO_update_ssa
@@ -3683,20 +2317,21 @@ struct gimple_opt_pass pass_sra_early =
}
};
+
struct gimple_opt_pass pass_sra =
{
{
GIMPLE_PASS,
- "sra", /* name */
- gate_sra, /* gate */
- tree_sra, /* execute */
+ "sra", /* name */
+ gate_intra_sra, /* gate */
+ late_intra_sra, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
TV_TREE_SRA, /* tv_id */
- PROP_cfg | PROP_ssa, /* properties_required */
+ PROP_cfg | PROP_ssa, /* properties_required */
0, /* properties_provided */
- 0, /* properties_destroyed */
+ 0, /* properties_destroyed */
TODO_update_address_taken, /* todo_flags_start */
TODO_dump_func
| TODO_update_ssa
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 5bb1f82ad9b..0b8c2515fee 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -439,6 +439,55 @@ debug_points_to_info_for (tree var)
dump_points_to_info_for (stderr, var);
}
+
+/* Initializes the alias-oracle reference representation *R from REF. */
+
+void
+ao_ref_init (ao_ref *r, tree ref)
+{
+ r->ref = ref;
+ r->base = NULL_TREE;
+ r->offset = 0;
+ r->size = -1;
+ r->max_size = -1;
+ r->ref_alias_set = -1;
+ r->base_alias_set = -1;
+}
+
+/* Returns the base object of the memory reference *REF. */
+
+tree
+ao_ref_base (ao_ref *ref)
+{
+ if (ref->base)
+ return ref->base;
+ ref->base = get_ref_base_and_extent (ref->ref, &ref->offset, &ref->size,
+ &ref->max_size);
+ return ref->base;
+}
+
+/* Returns the base object alias set of the memory reference *REF. */
+
+static alias_set_type ATTRIBUTE_UNUSED
+ao_ref_base_alias_set (ao_ref *ref)
+{
+ if (ref->base_alias_set != -1)
+ return ref->base_alias_set;
+ ref->base_alias_set = get_alias_set (ao_ref_base (ref));
+ return ref->base_alias_set;
+}
+
+/* Returns the reference alias set of the memory reference *REF. */
+
+alias_set_type
+ao_ref_alias_set (ao_ref *ref)
+{
+ if (ref->ref_alias_set != -1)
+ return ref->ref_alias_set;
+ ref->ref_alias_set = get_alias_set (ref->ref);
+ return ref->ref_alias_set;
+}
+
/* Return 1 if TYPE1 and TYPE2 are to be considered equivalent for the
purpose of TBAA. Return 0 if they are distinct and -1 if we cannot
decide. */
@@ -490,8 +539,7 @@ nonaliasing_component_refs_p (tree ref1, tree type1,
/* Now search for the type1 in the access path of ref2. This
would be a common base for doing offset based disambiguation on. */
- /* Skip the outermost ref - we would have caught that earlier. */
- refp = &TREE_OPERAND (ref2, 0);
+ refp = &ref2;
while (handled_component_p (*refp)
&& same_type_for_tbaa (TREE_TYPE (*refp), type1) == 0)
refp = &TREE_OPERAND (*refp, 0);
@@ -507,7 +555,7 @@ nonaliasing_component_refs_p (tree ref1, tree type1,
return ranges_overlap_p (offset1, max_size1, offset2, max_size2);
}
/* If we didn't find a common base, try the other way around. */
- refp = &TREE_OPERAND (ref1, 0);
+ refp = &ref1;
while (handled_component_p (*refp)
&& same_type_for_tbaa (TREE_TYPE (*refp), type2) == 0)
refp = &TREE_OPERAND (*refp, 0);
@@ -675,7 +723,7 @@ indirect_refs_may_alias_p (tree ref1, tree ptr1,
/* Return true, if the two memory references REF1 and REF2 may alias. */
static bool
-refs_may_alias_p_1 (tree ref1, tree ref2, bool tbaa_p)
+refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
{
tree base1, base2;
HOST_WIDE_INT offset1 = 0, offset2 = 0;
@@ -684,18 +732,26 @@ refs_may_alias_p_1 (tree ref1, tree ref2, bool tbaa_p)
bool var1_p, var2_p, ind1_p, ind2_p;
alias_set_type set;
- gcc_assert ((SSA_VAR_P (ref1)
- || handled_component_p (ref1)
- || INDIRECT_REF_P (ref1)
- || TREE_CODE (ref1) == TARGET_MEM_REF)
- && (SSA_VAR_P (ref2)
- || handled_component_p (ref2)
- || INDIRECT_REF_P (ref2)
- || TREE_CODE (ref2) == TARGET_MEM_REF));
+ gcc_assert ((!ref1->ref
+ || SSA_VAR_P (ref1->ref)
+ || handled_component_p (ref1->ref)
+ || INDIRECT_REF_P (ref1->ref)
+ || TREE_CODE (ref1->ref) == TARGET_MEM_REF)
+ && (!ref2->ref
+ || SSA_VAR_P (ref2->ref)
+ || handled_component_p (ref2->ref)
+ || INDIRECT_REF_P (ref2->ref)
+ || TREE_CODE (ref2->ref) == TARGET_MEM_REF));
/* Decompose the references into their base objects and the access. */
- base1 = get_ref_base_and_extent (ref1, &offset1, &size1, &max_size1);
- base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &max_size2);
+ base1 = ao_ref_base (ref1);
+ offset1 = ref1->offset;
+ size1 = ref1->size;
+ max_size1 = ref1->max_size;
+ base2 = ao_ref_base (ref2);
+ offset2 = ref2->offset;
+ size2 = ref2->size;
+ max_size2 = ref2->max_size;
/* We can end up with registers or constants as bases for example from
*D.1663_44 = VIEW_CONVERT_EXPR<struct DB_LSN>(__tmp$B0F64_59);
@@ -719,14 +775,15 @@ refs_may_alias_p_1 (tree ref1, tree ref2, bool tbaa_p)
/* First defer to TBAA if possible. */
if (tbaa_p
&& flag_strict_aliasing
- && !alias_sets_conflict_p (get_alias_set (ref1), get_alias_set (ref2)))
+ && !alias_sets_conflict_p (ao_ref_alias_set (ref1),
+ ao_ref_alias_set (ref2)))
return false;
/* If one reference is a TARGET_MEM_REF weird things are allowed. Still
TBAA disambiguation based on the access type is possible, so bail
out only after that check. */
- if (TREE_CODE (ref1) == TARGET_MEM_REF
- || TREE_CODE (ref2) == TARGET_MEM_REF)
+ if ((ref1->ref && TREE_CODE (ref1->ref) == TARGET_MEM_REF)
+ || (ref2->ref && TREE_CODE (ref2->ref) == TARGET_MEM_REF))
return true;
/* Dispatch to the pointer-vs-decl or pointer-vs-pointer disambiguators. */
@@ -734,19 +791,19 @@ refs_may_alias_p_1 (tree ref1, tree ref2, bool tbaa_p)
ind2_p = INDIRECT_REF_P (base2);
set = tbaa_p ? -1 : 0;
if (var1_p && ind2_p)
- return indirect_ref_may_alias_decl_p (ref2, TREE_OPERAND (base2, 0),
+ return indirect_ref_may_alias_decl_p (ref2->ref, TREE_OPERAND (base2, 0),
offset2, max_size2, set,
- ref1, base1,
+ ref1->ref, base1,
offset1, max_size1, set);
else if (ind1_p && var2_p)
- return indirect_ref_may_alias_decl_p (ref1, TREE_OPERAND (base1, 0),
+ return indirect_ref_may_alias_decl_p (ref1->ref, TREE_OPERAND (base1, 0),
offset1, max_size1, set,
- ref2, base2,
+ ref2->ref, base2,
offset2, max_size2, set);
else if (ind1_p && ind2_p)
- return indirect_refs_may_alias_p (ref1, TREE_OPERAND (base1, 0),
+ return indirect_refs_may_alias_p (ref1->ref, TREE_OPERAND (base1, 0),
offset1, max_size1, set,
- ref2, TREE_OPERAND (base2, 0),
+ ref2->ref, TREE_OPERAND (base2, 0),
offset2, max_size2, set);
gcc_unreachable ();
@@ -755,7 +812,11 @@ refs_may_alias_p_1 (tree ref1, tree ref2, bool tbaa_p)
bool
refs_may_alias_p (tree ref1, tree ref2)
{
- bool res = refs_may_alias_p_1 (ref1, ref2, true);
+ ao_ref r1, r2;
+ bool res;
+ ao_ref_init (&r1, ref1);
+ ao_ref_init (&r2, ref2);
+ res = refs_may_alias_p_1 (&r1, &r2, true);
if (res)
++alias_stats.refs_may_alias_p_may_alias;
else
@@ -769,7 +830,10 @@ refs_may_alias_p (tree ref1, tree ref2)
bool
refs_anti_dependent_p (tree load, tree store)
{
- return refs_may_alias_p_1 (load, store, false);
+ ao_ref r1, r2;
+ ao_ref_init (&r1, load);
+ ao_ref_init (&r2, store);
+ return refs_may_alias_p_1 (&r1, &r2, false);
}
/* Returns true if there is a output dependence for the stores
@@ -778,7 +842,10 @@ refs_anti_dependent_p (tree load, tree store)
bool
refs_output_dependent_p (tree store1, tree store2)
{
- return refs_may_alias_p_1 (store1, store2, false);
+ ao_ref r1, r2;
+ ao_ref_init (&r1, store1);
+ ao_ref_init (&r2, store2);
+ return refs_may_alias_p_1 (&r1, &r2, false);
}
/* If the call CALL may use the memory reference REF return true,
@@ -907,7 +974,7 @@ ref_maybe_used_by_stmt_p (gimple stmt, tree ref)
return true, otherwise return false. */
static bool
-call_may_clobber_ref_p_1 (gimple call, tree ref)
+call_may_clobber_ref_p_1 (gimple call, ao_ref *ref)
{
tree base;
@@ -916,7 +983,7 @@ call_may_clobber_ref_p_1 (gimple call, tree ref)
& (ECF_PURE|ECF_CONST|ECF_LOOPING_CONST_OR_PURE|ECF_NOVOPS))
return false;
- base = get_base_address (ref);
+ base = ao_ref_base (ref);
if (!base)
return true;
@@ -957,10 +1024,13 @@ call_may_clobber_ref_p_1 (gimple call, tree ref)
return true;
}
-static bool
+static bool ATTRIBUTE_UNUSED
call_may_clobber_ref_p (gimple call, tree ref)
{
- bool res = call_may_clobber_ref_p_1 (call, ref);
+ bool res;
+ ao_ref r;
+ ao_ref_init (&r, ref);
+ res = call_may_clobber_ref_p_1 (call, &r);
if (res)
++alias_stats.call_may_clobber_ref_p_may_alias;
else
@@ -973,34 +1043,52 @@ call_may_clobber_ref_p (gimple call, tree ref)
otherwise return false. */
bool
-stmt_may_clobber_ref_p (gimple stmt, tree ref)
+stmt_may_clobber_ref_p_1 (gimple stmt, ao_ref *ref)
{
if (is_gimple_call (stmt))
{
tree lhs = gimple_call_lhs (stmt);
if (lhs
- && !is_gimple_reg (lhs)
- && refs_may_alias_p (ref, lhs))
- return true;
+ && !is_gimple_reg (lhs))
+ {
+ ao_ref r;
+ ao_ref_init (&r, lhs);
+ if (refs_may_alias_p_1 (ref, &r, true))
+ return true;
+ }
- return call_may_clobber_ref_p (stmt, ref);
+ return call_may_clobber_ref_p_1 (stmt, ref);
}
else if (is_gimple_assign (stmt))
- return refs_may_alias_p (ref, gimple_assign_lhs (stmt));
+ {
+ ao_ref r;
+ ao_ref_init (&r, gimple_assign_lhs (stmt));
+ return refs_may_alias_p_1 (ref, &r, true);
+ }
else if (gimple_code (stmt) == GIMPLE_ASM)
return true;
return false;
}
-static tree get_continuation_for_phi (gimple, tree, bitmap *);
+bool
+stmt_may_clobber_ref_p (gimple stmt, tree ref)
+{
+ ao_ref r;
+ ao_ref_init (&r, ref);
+ return stmt_may_clobber_ref_p_1 (stmt, &r);
+}
+
+
+static tree get_continuation_for_phi (gimple, ao_ref *, bitmap *);
/* Walk the virtual use-def chain of VUSE until hitting the virtual operand
TARGET or a statement clobbering the memory reference REF in which
case false is returned. The walk starts with VUSE, one argument of PHI. */
static bool
-maybe_skip_until (gimple phi, tree target, tree ref, tree vuse, bitmap *visited)
+maybe_skip_until (gimple phi, tree target, ao_ref *ref,
+ tree vuse, bitmap *visited)
{
if (!*visited)
*visited = BITMAP_ALLOC (NULL);
@@ -1024,7 +1112,7 @@ maybe_skip_until (gimple phi, tree target, tree ref, tree vuse, bitmap *visited)
}
/* A clobbering statement or the end of the IL ends it failing. */
else if (gimple_nop_p (def_stmt)
- || stmt_may_clobber_ref_p (def_stmt, ref))
+ || stmt_may_clobber_ref_p_1 (def_stmt, ref))
return false;
vuse = gimple_vuse (def_stmt);
}
@@ -1038,7 +1126,7 @@ maybe_skip_until (gimple phi, tree target, tree ref, tree vuse, bitmap *visited)
be found. */
static tree
-get_continuation_for_phi (gimple phi, tree ref, bitmap *visited)
+get_continuation_for_phi (gimple phi, ao_ref *ref, bitmap *visited)
{
unsigned nargs = gimple_phi_num_args (phi);
@@ -1096,9 +1184,9 @@ get_continuation_for_phi (gimple phi, tree ref, bitmap *visited)
TODO: Cache the vector of equivalent vuses per ref, vuse pair. */
void *
-walk_non_aliased_vuses (tree ref, tree vuse,
- void *(*walker)(tree, tree, void *),
- void *(*translate)(tree *, tree, void *),void *data)
+walk_non_aliased_vuses (ao_ref *ref, tree vuse,
+ void *(*walker)(ao_ref *, tree, void *),
+ void *(*translate)(ao_ref *, tree, void *), void *data)
{
bitmap visited = NULL;
void *res;
@@ -1121,11 +1209,11 @@ walk_non_aliased_vuses (tree ref, tree vuse,
vuse = get_continuation_for_phi (def_stmt, ref, &visited);
else
{
- if (stmt_may_clobber_ref_p (def_stmt, ref))
+ if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
{
if (!translate)
break;
- res = (*translate) (&ref, vuse, data);
+ res = (*translate) (ref, vuse, data);
/* Failed lookup and translation. */
if (res == (void *)-1)
{
diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
index bc96712f790..115d3935512 100644
--- a/gcc/tree-ssa-alias.h
+++ b/gcc/tree-ssa-alias.h
@@ -74,7 +74,39 @@ struct GTY(()) pt_solution
};
+/* Simplified and cached information about a memory reference tree.
+ Used by the alias-oracle internally and externally in alternate
+ interfaces. */
+typedef struct ao_ref_s
+{
+ /* The original full memory reference tree or NULL_TREE if that is
+ not available. */
+ tree ref;
+
+ /* The following fields are the decomposed reference as returned
+ by get_ref_base_and_extent. */
+ /* The base object of the memory reference or NULL_TREE if all of
+ the following fields are not yet computed. */
+ tree base;
+ /* The offset relative to the base. */
+ HOST_WIDE_INT offset;
+ /* The size of the access. */
+ HOST_WIDE_INT size;
+ /* The maximum possible extent of the access or -1 if unconstrained. */
+ HOST_WIDE_INT max_size;
+
+ /* The alias set of the access or -1 if not yet computed. */
+ alias_set_type ref_alias_set;
+
+ /* The alias set of the base object or -1 if not yet computed. */
+ alias_set_type base_alias_set;
+} ao_ref;
+
+
/* In tree-ssa-alias.c */
+extern void ao_ref_init (ao_ref *, tree);
+extern tree ao_ref_base (ao_ref *);
+extern alias_set_type ao_ref_alias_set (ao_ref *);
extern enum escape_type is_escape_site (gimple);
extern bool ptr_deref_may_alias_global_p (tree);
extern bool refs_may_alias_p (tree, tree);
@@ -82,9 +114,10 @@ extern bool refs_anti_dependent_p (tree, tree);
extern bool refs_output_dependent_p (tree, tree);
extern bool ref_maybe_used_by_stmt_p (gimple, tree);
extern bool stmt_may_clobber_ref_p (gimple, tree);
-extern void *walk_non_aliased_vuses (tree, tree,
- void *(*)(tree, tree, void *),
- void *(*)(tree *, tree, void *), void *);
+extern bool stmt_may_clobber_ref_p_1 (gimple, ao_ref *);
+extern void *walk_non_aliased_vuses (ao_ref *, tree,
+ void *(*)(ao_ref *, tree, void *),
+ void *(*)(ao_ref *, tree, void *), void *);
extern unsigned int walk_aliased_vdefs (tree, tree,
bool (*)(tree, tree, void *), void *,
bitmap *);
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index c3316191897..fb6eb4da209 100644
--- a/gcc/tree-ssa-ccp.c
+++ b/gcc/tree-ssa-ccp.c
@@ -958,6 +958,30 @@ ccp_fold (gimple stmt)
}
}
}
+ else if (TREE_CODE (rhs) == CONSTRUCTOR
+ && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE
+ && (CONSTRUCTOR_NELTS (rhs)
+ == TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs))))
+ {
+ unsigned i;
+ tree val, list;
+
+ list = NULL_TREE;
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
+ {
+ if (TREE_CODE (val) == SSA_NAME
+ && get_value (val)->lattice_val == CONSTANT)
+ val = get_value (val)->value;
+ if (TREE_CODE (val) == INTEGER_CST
+ || TREE_CODE (val) == REAL_CST
+ || TREE_CODE (val) == FIXED_CST)
+ list = tree_cons (NULL_TREE, val, list);
+ else
+ return NULL_TREE;
+ }
+
+ return build_vector (TREE_TYPE (rhs), nreverse (list));
+ }
if (kind == tcc_reference)
{
@@ -2654,6 +2678,25 @@ fold_gimple_assign (gimple_stmt_iterator *si)
build_fold_addr_expr (tem));
}
+ else if (TREE_CODE (rhs) == CONSTRUCTOR
+ && TREE_CODE (TREE_TYPE (rhs)) == VECTOR_TYPE
+ && (CONSTRUCTOR_NELTS (rhs)
+ == TYPE_VECTOR_SUBPARTS (TREE_TYPE (rhs))))
+ {
+ /* Fold a constant vector CONSTRUCTOR to VECTOR_CST. */
+ unsigned i;
+ tree val;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (rhs), i, val)
+ if (TREE_CODE (val) != INTEGER_CST
+ && TREE_CODE (val) != REAL_CST
+ && TREE_CODE (val) != FIXED_CST)
+ return NULL_TREE;
+
+ return build_vector_from_ctor (TREE_TYPE (rhs),
+ CONSTRUCTOR_ELTS (rhs));
+ }
+
/* If we couldn't fold the RHS, hand over to the generic
fold routines. */
if (result == NULL_TREE)
diff --git a/gcc/tree-ssa-copy.c b/gcc/tree-ssa-copy.c
index 9dad1cdc940..d919681fb1a 100644
--- a/gcc/tree-ssa-copy.c
+++ b/gcc/tree-ssa-copy.c
@@ -151,44 +151,6 @@ may_propagate_copy_into_asm (tree dest)
}
-/* Given two SSA_NAMEs pointers ORIG and NEW such that we are copy
- propagating NEW into ORIG, consolidate aliasing information so that
- they both share the same memory tags. */
-
-void
-merge_alias_info (tree orig_name, tree new_name)
-{
- gcc_assert (POINTER_TYPE_P (TREE_TYPE (orig_name))
- && POINTER_TYPE_P (TREE_TYPE (new_name)));
-
-#if defined ENABLE_CHECKING
- gcc_assert (useless_type_conversion_p (TREE_TYPE (orig_name),
- TREE_TYPE (new_name)));
-#endif
-
- /* Check that flow-sensitive information is compatible. Notice that
- we may not merge flow-sensitive information here. This function
- is called when propagating equivalences dictated by the IL, like
- a copy operation P_i = Q_j, and from equivalences dictated by
- control-flow, like if (P_i == Q_j).
-
- In the former case, P_i and Q_j are equivalent in every block
- dominated by the assignment, so their flow-sensitive information
- is always the same. However, in the latter case, the pointers
- P_i and Q_j are only equivalent in one of the sub-graphs out of
- the predicate, so their flow-sensitive information is not the
- same in every block dominated by the predicate.
-
- Since we cannot distinguish one case from another in this
- function, we cannot merge flow-sensitive information by
- intersecting. Instead the only thing we can do is to _not_
- merge flow-sensitive information.
-
- ??? At some point we should enhance this machinery to distinguish
- both cases in the caller. */
-}
-
-
/* Common code for propagate_value and replace_exp.
Replace use operand OP_P with VAL. FOR_PROPAGATION indicates if the
@@ -198,9 +160,8 @@ static void
replace_exp_1 (use_operand_p op_p, tree val,
bool for_propagation ATTRIBUTE_UNUSED)
{
- tree op = USE_FROM_PTR (op_p);
-
#if defined ENABLE_CHECKING
+ tree op = USE_FROM_PTR (op_p);
gcc_assert (!(for_propagation
&& TREE_CODE (op) == SSA_NAME
&& TREE_CODE (val) == SSA_NAME
@@ -208,11 +169,7 @@ replace_exp_1 (use_operand_p op_p, tree val,
#endif
if (TREE_CODE (val) == SSA_NAME)
- {
- if (TREE_CODE (op) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (op)))
- merge_alias_info (op, val);
- SET_USE (op_p, val);
- }
+ SET_USE (op_p, val);
else
SET_USE (op_p, unsave_expr_now (val));
}
@@ -262,11 +219,7 @@ propagate_tree_value (tree *op_p, tree val)
#endif
if (TREE_CODE (val) == SSA_NAME)
- {
- if (*op_p && TREE_CODE (*op_p) == SSA_NAME && POINTER_TYPE_P (TREE_TYPE (*op_p)))
- merge_alias_info (*op_p, val);
- *op_p = val;
- }
+ *op_p = val;
else
*op_p = unsave_expr_now (val);
}
@@ -872,8 +825,24 @@ fini_copy_prop (void)
for (i = 1; i < num_ssa_names; i++)
{
tree var = ssa_name (i);
- if (var && copy_of[i].value && copy_of[i].value != var)
- tmp[i].value = get_last_copy_of (var);
+ if (!var
+ || !copy_of[i].value
+ || copy_of[i].value == var)
+ continue;
+
+ tmp[i].value = get_last_copy_of (var);
+
+ /* In theory the points-to solution of all members of the
+ copy chain is their intersection. For now we do not bother
+ to compute this but only make sure we do not lose points-to
+ information completely by setting the points-to solution
+ of the representative to the first solution we find if
+ it doesn't have one already. */
+ if (tmp[i].value != var
+ && POINTER_TYPE_P (TREE_TYPE (var))
+ && SSA_NAME_PTR_INFO (var)
+ && !SSA_NAME_PTR_INFO (tmp[i].value))
+ duplicate_ssa_name_ptr_info (tmp[i].value, SSA_NAME_PTR_INFO (var));
}
substitute_and_fold (tmp, false);
diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c
index 0673fab851f..a02b1c5209f 100644
--- a/gcc/tree-ssa-live.c
+++ b/gcc/tree-ssa-live.c
@@ -552,7 +552,9 @@ mark_all_vars_used (tree *expr_p, void *data)
walk_tree (expr_p, mark_all_vars_used_1, data, NULL);
}
-/* Dump scope blocks. */
+
+/* Dump scope blocks starting at SCOPE to FILE. INDENT is the
+ indentation level and FLAGS is as in print_generic_expr. */
static void
dump_scope_block (FILE *file, int indent, tree scope, int flags)
@@ -606,12 +608,26 @@ dump_scope_block (FILE *file, int indent, tree scope, int flags)
fprintf (file, "\n%*s}\n",indent, "");
}
+
+/* Dump the tree of lexical scopes of current_function_decl to FILE.
+ FLAGS is as in print_generic_expr. */
+
void
dump_scope_blocks (FILE *file, int flags)
{
dump_scope_block (file, 0, DECL_INITIAL (current_function_decl), flags);
}
+
+/* Dump the tree of lexical scopes of current_function_decl to stderr.
+ FLAGS is as in print_generic_expr. */
+
+void
+debug_scope_blocks (int flags)
+{
+ dump_scope_blocks (stderr, flags);
+}
+
/* Remove local variables that are not referenced in the IL. */
void
@@ -623,6 +639,12 @@ remove_unused_locals (void)
var_ann_t ann;
bitmap global_unused_vars = NULL;
+ /* Removing declarations from lexical blocks when not optimizing is
+ not only a waste of time, it actually causes differences in stack
+ layout. */
+ if (!optimize)
+ return;
+
mark_scope_block_unused (DECL_INITIAL (current_function_decl));
/* Assume all locals are unused. */
@@ -685,8 +707,7 @@ remove_unused_locals (void)
if (TREE_CODE (var) != FUNCTION_DECL
&& (!(ann = var_ann (var))
- || !ann->used)
- && (optimize || DECL_ARTIFICIAL (var)))
+ || !ann->used))
{
if (is_global_var (var))
{
@@ -745,8 +766,7 @@ remove_unused_locals (void)
&& TREE_CODE (t) != PARM_DECL
&& TREE_CODE (t) != RESULT_DECL
&& !(ann = var_ann (t))->used
- && !TREE_ADDRESSABLE (t)
- && (optimize || DECL_ARTIFICIAL (t)))
+ && !TREE_ADDRESSABLE (t))
remove_referenced_var (t);
remove_unused_scope_block_p (DECL_INITIAL (current_function_decl));
if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index b7047e12bc9..00cc18fd159 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -1922,6 +1922,24 @@ strip_offset_1 (tree expr, bool inside_addr, bool top_compref,
return fold_convert (orig_type, expr);
+ case MULT_EXPR:
+ op1 = TREE_OPERAND (expr, 1);
+ if (!cst_and_fits_in_hwi (op1))
+ return orig_expr;
+
+ op0 = TREE_OPERAND (expr, 0);
+ op0 = strip_offset_1 (op0, false, false, &off0);
+ if (op0 == TREE_OPERAND (expr, 0))
+ return orig_expr;
+
+ *offset = off0 * int_cst_value (op1);
+ if (integer_zerop (op0))
+ expr = op0;
+ else
+ expr = fold_build2 (MULT_EXPR, type, op0, op1);
+
+ return fold_convert (orig_type, expr);
+
case ARRAY_REF:
case ARRAY_RANGE_REF:
if (!inside_addr)
@@ -3302,6 +3320,19 @@ force_expr_to_var_cost (tree expr, bool speed)
break;
+ case NEGATE_EXPR:
+ op0 = TREE_OPERAND (expr, 0);
+ STRIP_NOPS (op0);
+ op1 = NULL_TREE;
+
+ if (is_gimple_val (op0))
+ cost0 = zero_cost;
+ else
+ cost0 = force_expr_to_var_cost (op0, speed);
+
+ cost1 = zero_cost;
+ break;
+
default:
/* Just an arbitrary value, FIXME. */
return new_cost (target_spill_cost[speed], 0);
@@ -3313,6 +3344,7 @@ force_expr_to_var_cost (tree expr, bool speed)
case POINTER_PLUS_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
+ case NEGATE_EXPR:
cost = new_cost (add_cost (mode, speed), 0);
break;
@@ -3415,8 +3447,8 @@ ptr_difference_cost (struct ivopts_data *data,
unsigned HOST_WIDE_INT *offset, bitmap *depends_on)
{
HOST_WIDE_INT diff = 0;
- comp_cost cost;
- bool speed = optimize_loop_for_speed_p (data->current_loop);
+ aff_tree aff_e1, aff_e2;
+ tree type;
gcc_assert (TREE_CODE (e1) == ADDR_EXPR);
@@ -3434,12 +3466,14 @@ ptr_difference_cost (struct ivopts_data *data,
*symbol_present = false;
*var_present = true;
-
- cost = force_var_cost (data, e1, depends_on);
- cost = add_costs (cost, force_var_cost (data, e2, depends_on));
- cost.cost += add_cost (Pmode, speed);
- return cost;
+ type = signed_type_for (TREE_TYPE (e1));
+ tree_to_aff_combination (e1, type, &aff_e1);
+ tree_to_aff_combination (e2, type, &aff_e2);
+ aff_combination_scale (&aff_e2, double_int_minus_one);
+ aff_combination_add (&aff_e1, &aff_e2);
+
+ return force_var_cost (data, aff_combination_to_tree (&aff_e1), depends_on);
}
/* Estimates cost of expressing difference E1 - E2 as
@@ -3453,9 +3487,10 @@ difference_cost (struct ivopts_data *data,
tree e1, tree e2, bool *symbol_present, bool *var_present,
unsigned HOST_WIDE_INT *offset, bitmap *depends_on)
{
- comp_cost cost;
enum machine_mode mode = TYPE_MODE (TREE_TYPE (e1));
unsigned HOST_WIDE_INT off1, off2;
+ aff_tree aff_e1, aff_e2;
+ tree type;
e1 = strip_offset (e1, &off1);
e2 = strip_offset (e2, &off2);
@@ -3465,8 +3500,8 @@ difference_cost (struct ivopts_data *data,
STRIP_NOPS (e2);
if (TREE_CODE (e1) == ADDR_EXPR)
- return ptr_difference_cost (data, e1, e2, symbol_present, var_present, offset,
- depends_on);
+ return ptr_difference_cost (data, e1, e2, symbol_present, var_present,
+ offset, depends_on);
*symbol_present = false;
if (operand_equal_p (e1, e2, 0))
@@ -3474,23 +3509,26 @@ difference_cost (struct ivopts_data *data,
*var_present = false;
return zero_cost;
}
+
*var_present = true;
+
if (integer_zerop (e2))
return force_var_cost (data, e1, depends_on);
if (integer_zerop (e1))
{
- cost = force_var_cost (data, e2, depends_on);
+ comp_cost cost = force_var_cost (data, e2, depends_on);
cost.cost += multiply_by_cost (-1, mode, data->speed);
-
return cost;
}
- cost = force_var_cost (data, e1, depends_on);
- cost = add_costs (cost, force_var_cost (data, e2, depends_on));
- cost.cost += add_cost (mode, data->speed);
+ type = signed_type_for (TREE_TYPE (e1));
+ tree_to_aff_combination (e1, type, &aff_e1);
+ tree_to_aff_combination (e2, type, &aff_e2);
+ aff_combination_scale (&aff_e2, double_int_minus_one);
+ aff_combination_add (&aff_e1, &aff_e2);
- return cost;
+ return force_var_cost (data, aff_combination_to_tree (&aff_e1), depends_on);
}
/* Determines the cost of the computation by that USE is expressed
@@ -3511,7 +3549,6 @@ get_computation_cost_at (struct ivopts_data *data,
HOST_WIDE_INT ratio, aratio;
bool var_present, symbol_present;
comp_cost cost;
- unsigned n_sums;
double_int rat;
bool speed = optimize_bb_for_speed_p (gimple_bb (at));
@@ -3544,7 +3581,7 @@ get_computation_cost_at (struct ivopts_data *data,
return infinite_cost;
}
- if (TYPE_PRECISION (utype) != TYPE_PRECISION (ctype))
+ if (TYPE_PRECISION (utype) < TYPE_PRECISION (ctype))
{
/* TODO -- add direct handling of this case. */
goto fallback;
@@ -3569,6 +3606,9 @@ get_computation_cost_at (struct ivopts_data *data,
else
return infinite_cost;
+ STRIP_NOPS (cbase);
+ ctype = TREE_TYPE (cbase);
+
/* use = ubase + ratio * (var - cbase). If either cbase is a constant
or ratio == 1, it is better to handle this like
@@ -3591,6 +3631,18 @@ get_computation_cost_at (struct ivopts_data *data,
&symbol_present, &var_present, &offset,
depends_on);
}
+ else if (address_p
+ && !POINTER_TYPE_P (ctype)
+ && multiplier_allowed_in_address_p (ratio,
+ TYPE_MODE (TREE_TYPE (utype))))
+ {
+ cbase
+ = fold_build2 (MULT_EXPR, ctype, cbase, build_int_cst (ctype, ratio));
+ cost = difference_cost (data,
+ ubase, cbase,
+ &symbol_present, &var_present, &offset,
+ depends_on);
+ }
else
{
cost = force_var_cost (data, cbase, depends_on);
@@ -3608,39 +3660,38 @@ get_computation_cost_at (struct ivopts_data *data,
offset -= ratio * cstepi;
/* Now the computation is in shape symbol + var1 + const + ratio * var2.
- (symbol/var/const parts may be omitted). If we are looking for an address,
- find the cost of addressing this. */
+ (symbol/var1/const parts may be omitted). If we are looking for an
+ address, find the cost of addressing this. */
if (address_p)
- return add_costs (cost, get_address_cost (symbol_present, var_present,
- offset, ratio,
- TYPE_MODE (TREE_TYPE (*use->op_p)), speed));
+ return add_costs (cost,
+ get_address_cost (symbol_present, var_present,
+ offset, ratio,
+ TYPE_MODE (TREE_TYPE (utype)), speed));
/* Otherwise estimate the costs for computing the expression. */
- aratio = ratio > 0 ? ratio : -ratio;
if (!symbol_present && !var_present && !offset)
{
if (ratio != 1)
cost.cost += multiply_by_cost (ratio, TYPE_MODE (ctype), speed);
-
return cost;
}
- if (aratio != 1)
- cost.cost += multiply_by_cost (aratio, TYPE_MODE (ctype), speed);
-
- n_sums = 1;
- if (var_present
- /* Symbol + offset should be compile-time computable. */
- && (symbol_present || offset))
- n_sums++;
+ /* Symbol + offset should be compile-time computable so consider that they
+ are added once to the variable, if present. */
+ if (var_present && (symbol_present || offset))
+ cost.cost += add_cost (TYPE_MODE (ctype), speed)
+ / AVG_LOOP_NITER (data->current_loop);
/* Having offset does not affect runtime cost in case it is added to
symbol, but it increases complexity. */
if (offset)
cost.complexity++;
- cost.cost += n_sums * add_cost (TYPE_MODE (ctype), speed);
- return cost;
+ cost.cost += add_cost (TYPE_MODE (ctype), speed);
+
+ aratio = ratio > 0 ? ratio : -ratio;
+ if (aratio != 1)
+ cost.cost += multiply_by_cost (aratio, TYPE_MODE (ctype), speed);
fallback:
{
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 4a8aee7c20c..0f3c829713e 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -904,19 +904,9 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
case REALPART_EXPR:
case IMAGPART_EXPR:
{
- tree ref;
- HOST_WIDE_INT offset, size, maxsize;
-
if (TREE_THIS_VOLATILE (expr))
gimple_set_has_volatile_ops (stmt, true);
- ref = get_ref_base_and_extent (expr, &offset, &size, &maxsize);
- if (TREE_CODE (ref) == INDIRECT_REF)
- {
- get_indirect_ref_operands (stmt, ref, flags, false);
- flags |= opf_no_vops;
- }
-
get_expr_operands (stmt, &TREE_OPERAND (expr, 0), flags);
if (code == COMPONENT_REF)
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index f443585c0e7..fc311bcdbf9 100644
--- a/gcc/tree-ssa-pre.c
+++ b/gcc/tree-ssa-pre.c
@@ -1252,12 +1252,12 @@ do_unary:
static tree
translate_vuse_through_block (VEC (vn_reference_op_s, heap) *operands,
- tree vuse,
+ alias_set_type set, tree type, tree vuse,
basic_block phiblock,
basic_block block)
{
gimple phi = SSA_NAME_DEF_STMT (vuse);
- tree ref;
+ ao_ref ref;
if (gimple_bb (phi) != phiblock)
return vuse;
@@ -1268,13 +1268,13 @@ translate_vuse_through_block (VEC (vn_reference_op_s, heap) *operands,
return PHI_ARG_DEF (phi, e->dest_idx);
}
- if (!(ref = get_ref_from_reference_ops (operands)))
+ if (!ao_ref_init_from_vn_reference (&ref, set, type, operands))
return NULL_TREE;
/* Use the alias-oracle to find either the PHI node in this block,
the first VUSE used in this block that is equivalent to vuse or
the first VUSE which definition in this block kills the value. */
- while (!stmt_may_clobber_ref_p (phi, ref))
+ while (!stmt_may_clobber_ref_p_1 (phi, &ref))
{
vuse = gimple_vuse (phi);
phi = SSA_NAME_DEF_STMT (vuse);
@@ -1317,23 +1317,7 @@ get_expr_type (const pre_expr e)
case CONSTANT:
return TREE_TYPE (PRE_EXPR_CONSTANT (e));
case REFERENCE:
- {
- vn_reference_op_t vro;
-
- gcc_assert (PRE_EXPR_REFERENCE (e)->operands);
- vro = VEC_index (vn_reference_op_s,
- PRE_EXPR_REFERENCE (e)->operands,
- 0);
- /* We don't store type along with COMPONENT_REF because it is
- always the same as FIELD_DECL's type. */
- if (!vro->type)
- {
- gcc_assert (vro->opcode == COMPONENT_REF);
- return TREE_TYPE (vro->op0);
- }
- return vro->type;
- }
-
+ return PRE_EXPR_REFERENCE (e)->type;
case NARY:
return PRE_EXPR_NARY (e)->type;
}
@@ -1661,6 +1645,7 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
if (vuse)
{
newvuse = translate_vuse_through_block (newoperands,
+ ref->set, ref->type,
vuse, phiblock, pred);
if (newvuse == NULL_TREE)
{
@@ -1675,7 +1660,8 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
unsigned int new_val_id;
pre_expr constant;
- tree result = vn_reference_lookup_pieces (newvuse,
+ tree result = vn_reference_lookup_pieces (newvuse, ref->set,
+ ref->type,
newoperands,
&newref, true);
if (newref)
@@ -1706,7 +1692,8 @@ phi_translate_1 (pre_expr expr, bitmap_set_t set1, bitmap_set_t set2,
new_val_id = get_next_value_id ();
VEC_safe_grow_cleared (bitmap_set_t, heap, value_expressions,
get_max_value_id() + 1);
- newref = vn_reference_insert_pieces (newvuse,
+ newref = vn_reference_insert_pieces (newvuse, ref->set,
+ ref->type,
newoperands,
result, new_val_id);
newoperands = NULL;
@@ -1884,10 +1871,10 @@ value_dies_in_block_x (pre_expr expr, basic_block block)
tree vuse = PRE_EXPR_REFERENCE (expr)->vuse;
vn_reference_t refx = PRE_EXPR_REFERENCE (expr);
gimple def;
- tree ref = NULL_TREE;
gimple_stmt_iterator gsi;
unsigned id = get_expression_id (expr);
bool res = false;
+ ao_ref ref;
if (!vuse)
return false;
@@ -1902,6 +1889,7 @@ value_dies_in_block_x (pre_expr expr, basic_block block)
top of the basic block, a statement uses VUSE there can be no kill
inbetween that use and the original statement that loaded {e, VUSE},
so we can stop walking. */
+ ref.base = NULL_TREE;
for (gsi = gsi_start_bb (block); !gsi_end_p (gsi); gsi_next (&gsi))
{
tree def_vuse, def_vdef;
@@ -1924,16 +1912,15 @@ value_dies_in_block_x (pre_expr expr, basic_block block)
}
/* Init ref only if we really need it. */
- if (ref == NULL_TREE)
+ if (ref.base == NULL_TREE
+ && !ao_ref_init_from_vn_reference (&ref, refx->set, refx->type,
+ refx->operands))
{
- if (!(ref = get_ref_from_reference_ops (refx->operands)))
- {
- res = true;
- break;
- }
+ res = true;
+ break;
}
/* If the statement may clobber expr, it dies. */
- if (stmt_may_clobber_ref_p (def, ref))
+ if (stmt_may_clobber_ref_p_1 (def, &ref))
{
res = true;
break;
@@ -3793,7 +3780,8 @@ compute_avail (void)
continue;
copy_reference_ops_from_call (stmt, &ops);
- vn_reference_lookup_pieces (gimple_vuse (stmt),
+ vn_reference_lookup_pieces (gimple_vuse (stmt), 0,
+ gimple_expr_type (stmt),
ops, &ref, false);
VEC_free (vn_reference_op_s, heap, ops);
if (!ref)
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index d2dafb3023f..3a4415c5759 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -543,28 +543,35 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
a matching type is not necessary and a mismatching type
is always a spurious difference. */
temp.type = NULL_TREE;
+ temp.op0 = TREE_OPERAND (ref, 1);
+ temp.op1 = TREE_OPERAND (ref, 2);
/* If this is a reference to a union member, record the union
member size as operand. Do so only if we are doing
expression insertion (during FRE), as PRE currently gets
confused with this. */
if (may_insert
- && TREE_OPERAND (ref, 2) == NULL_TREE
- && TREE_CODE (DECL_CONTEXT (TREE_OPERAND (ref, 1))) == UNION_TYPE
- && integer_zerop (DECL_FIELD_OFFSET (TREE_OPERAND (ref, 1)))
- && integer_zerop (DECL_FIELD_BIT_OFFSET (TREE_OPERAND (ref, 1))))
- temp.op0 = TYPE_SIZE (TREE_TYPE (TREE_OPERAND (ref, 1)));
- else
- {
- /* Record field as operand. */
- temp.op0 = TREE_OPERAND (ref, 1);
- temp.op1 = TREE_OPERAND (ref, 2);
- }
+ && temp.op1 == NULL_TREE
+ && TREE_CODE (DECL_CONTEXT (temp.op0)) == UNION_TYPE
+ && integer_zerop (DECL_FIELD_OFFSET (temp.op0))
+ && integer_zerop (DECL_FIELD_BIT_OFFSET (temp.op0))
+ && host_integerp (TYPE_SIZE (TREE_TYPE (temp.op0)), 0))
+ temp.op0 = DECL_SIZE (temp.op0);
break;
case ARRAY_RANGE_REF:
case ARRAY_REF:
/* Record index as operand. */
temp.op0 = TREE_OPERAND (ref, 1);
- temp.op1 = TREE_OPERAND (ref, 2);
+ /* Record even constant lower bounds. */
+ if (TREE_OPERAND (ref, 2))
+ temp.op1 = TREE_OPERAND (ref, 2);
+ else
+ {
+ tree domain = TYPE_DOMAIN (TREE_TYPE (TREE_OPERAND (ref, 0)));
+ if (domain
+ && TYPE_MIN_VALUE (domain)
+ && !integer_zerop (TYPE_MIN_VALUE (domain)))
+ temp.op1 = TYPE_MIN_VALUE (domain);
+ }
temp.op2 = TREE_OPERAND (ref, 3);
break;
case STRING_CST:
@@ -612,24 +619,68 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
}
}
-/* Re-create a reference tree from the reference ops OPS.
- Returns NULL_TREE if the ops were not handled.
- This routine needs to be kept in sync with copy_reference_ops_from_ref. */
+/* Build a alias-oracle reference abstraction in *REF from the vn_reference
+ operands in *OPS, the reference alias set SET and the reference type TYPE.
+ Return true if something useful was produced. */
-tree
-get_ref_from_reference_ops (VEC(vn_reference_op_s, heap) *ops)
+bool
+ao_ref_init_from_vn_reference (ao_ref *ref,
+ alias_set_type set, tree type,
+ VEC (vn_reference_op_s, heap) *ops)
{
vn_reference_op_t op;
unsigned i;
- tree ref, *op0_p = &ref;
+ tree base = NULL_TREE;
+ tree *op0_p = &base;
+ HOST_WIDE_INT offset = 0;
+ HOST_WIDE_INT max_size;
+ HOST_WIDE_INT size = -1;
+ tree size_tree = NULL_TREE;
+
+ /* First get the final access size from just the outermost expression. */
+ op = VEC_index (vn_reference_op_s, ops, 0);
+ if (op->opcode == COMPONENT_REF)
+ {
+ if (TREE_CODE (op->op0) == INTEGER_CST)
+ size_tree = op->op0;
+ else
+ size_tree = DECL_SIZE (op->op0);
+ }
+ else if (op->opcode == BIT_FIELD_REF)
+ size_tree = op->op0;
+ else
+ {
+ enum machine_mode mode = TYPE_MODE (type);
+ if (mode == BLKmode)
+ size_tree = TYPE_SIZE (type);
+ else
+ size = GET_MODE_BITSIZE (mode);
+ }
+ if (size_tree != NULL_TREE)
+ {
+ if (!host_integerp (size_tree, 1))
+ size = -1;
+ else
+ size = TREE_INT_CST_LOW (size_tree);
+ }
+ /* Initially, maxsize is the same as the accessed element size.
+ In the following it will only grow (or become -1). */
+ max_size = size;
+
+ /* Compute cumulative bit-offset for nested component-refs and array-refs,
+ and find the ultimate containing object. */
for (i = 0; VEC_iterate (vn_reference_op_s, ops, i, op); ++i)
{
switch (op->opcode)
{
+ /* These may be in the reference ops, but we cannot do anything
+ sensible with them here. */
case CALL_EXPR:
- return NULL_TREE;
+ case ADDR_EXPR:
+ return false;
+ /* Record the base objects. */
case ALIGN_INDIRECT_REF:
case INDIRECT_REF:
*op0_p = build1 (op->opcode, op->type, NULL_TREE);
@@ -642,26 +693,69 @@ get_ref_from_reference_ops (VEC(vn_reference_op_s, heap) *ops)
op0_p = &TREE_OPERAND (*op0_p, 0);
break;
+ case VAR_DECL:
+ case PARM_DECL:
+ case RESULT_DECL:
+ case SSA_NAME:
+ case FILTER_EXPR:
+ case EXC_PTR_EXPR:
+ *op0_p = op->op0;
+ break;
+
+ /* And now the usual component-reference style ops. */
case BIT_FIELD_REF:
- *op0_p = build3 (BIT_FIELD_REF, op->type, NULL_TREE,
- op->op0, op->op1);
- op0_p = &TREE_OPERAND (*op0_p, 0);
+ offset += tree_low_cst (op->op1, 0);
break;
case COMPONENT_REF:
- /* We cannot re-construct our fancy union reference handling. */
- if (TREE_CODE (op->op0) == INTEGER_CST)
- return NULL_TREE;
- *op0_p = build3 (COMPONENT_REF, TREE_TYPE (op->op0), NULL_TREE,
- op->op0, op->op1);
- op0_p = &TREE_OPERAND (*op0_p, 0);
- break;
+ {
+ tree field = op->op0;
+ /* We do not have a complete COMPONENT_REF tree here so we
+ cannot use component_ref_field_offset. Do the interesting
+ parts manually. */
+
+ /* Our union trick, done for offset zero only. */
+ if (TREE_CODE (field) == INTEGER_CST)
+ ;
+ else if (op->op1
+ || !host_integerp (DECL_FIELD_OFFSET (field), 1))
+ max_size = -1;
+ else
+ {
+ offset += (TREE_INT_CST_LOW (DECL_FIELD_OFFSET (field))
+ * BITS_PER_UNIT);
+ offset += TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field));
+ }
+ break;
+ }
case ARRAY_RANGE_REF:
case ARRAY_REF:
- *op0_p = build4 (op->opcode, op->type, NULL_TREE,
- op->op0, op->op1, op->op2);
- op0_p = &TREE_OPERAND (*op0_p, 0);
+ /* Same for ARRAY_REFs. We do not have access to the array
+ type here, but we recorded the lower bound in op1. */
+ if (op->op2
+ || !host_integerp (op->op0, 0)
+ || (op->op1 && !host_integerp (op->op1, 0))
+ || !host_integerp (TYPE_SIZE (op->type), 1))
+ max_size = -1;
+ else
+ {
+ HOST_WIDE_INT hindex = TREE_INT_CST_LOW (op->op0);
+ if (op->op1)
+ hindex -= TREE_INT_CST_LOW (op->op1);
+ hindex *= TREE_INT_CST_LOW (TYPE_SIZE (op->type));
+ offset += hindex;
+ }
+ break;
+
+ case REALPART_EXPR:
+ break;
+
+ case IMAGPART_EXPR:
+ offset += size;
+ break;
+
+ case VIEW_CONVERT_EXPR:
break;
case STRING_CST:
@@ -670,37 +764,26 @@ get_ref_from_reference_ops (VEC(vn_reference_op_s, heap) *ops)
case VECTOR_CST:
case REAL_CST:
case CONSTRUCTOR:
- case VAR_DECL:
- case PARM_DECL:
case CONST_DECL:
- case RESULT_DECL:
- case SSA_NAME:
- case FILTER_EXPR:
- case EXC_PTR_EXPR:
- *op0_p = op->op0;
- break;
-
- case ADDR_EXPR:
- if (op->op0 != NULL_TREE)
- {
- gcc_assert (is_gimple_min_invariant (op->op0));
- *op0_p = op->op0;
- break;
- }
- /* Fallthrough. */
- case IMAGPART_EXPR:
- case REALPART_EXPR:
- case VIEW_CONVERT_EXPR:
- *op0_p = build1 (op->opcode, op->type, NULL_TREE);
- op0_p = &TREE_OPERAND (*op0_p, 0);
- break;
+ return false;
default:
- return NULL_TREE;
+ return false;
}
}
- return ref;
+ if (base == NULL_TREE)
+ return false;
+
+ ref->ref = NULL_TREE;
+ ref->base = base;
+ ref->offset = offset;
+ ref->size = size;
+ ref->max_size = max_size;
+ ref->ref_alias_set = set;
+ ref->base_alias_set = -1;
+
+ return true;
}
/* Copy the operations present in load/store/call REF into RESULT, a vector of
@@ -920,7 +1003,7 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
with the current VUSE and performs the expression lookup. */
static void *
-vn_reference_lookup_2 (tree op ATTRIBUTE_UNUSED, tree vuse, void *vr_)
+vn_reference_lookup_2 (ao_ref *op ATTRIBUTE_UNUSED, tree vuse, void *vr_)
{
vn_reference_t vr = (vn_reference_t)vr_;
void **slot;
@@ -949,16 +1032,18 @@ vn_reference_lookup_2 (tree op ATTRIBUTE_UNUSED, tree vuse, void *vr_)
of VUSE. */
static void *
-vn_reference_lookup_3 (tree *refp, tree vuse, void *vr_)
+vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *vr_)
{
vn_reference_t vr = (vn_reference_t)vr_;
gimple def_stmt = SSA_NAME_DEF_STMT (vuse);
tree fndecl;
- tree ref = *refp;
tree base;
HOST_WIDE_INT offset, size, maxsize;
- base = get_ref_base_and_extent (ref, &offset, &size, &maxsize);
+ base = ao_ref_base (ref);
+ offset = ref->offset;
+ size = ref->size;
+ maxsize = ref->max_size;
/* If we cannot constrain the size of the reference we cannot
test if anything kills it. */
@@ -968,7 +1053,7 @@ vn_reference_lookup_3 (tree *refp, tree vuse, void *vr_)
/* def_stmt may-defs *ref. See if we can derive a value for *ref
from that defintion.
1) Memset. */
- if (is_gimple_reg_type (TREE_TYPE (ref))
+ if (is_gimple_reg_type (vr->type)
&& is_gimple_call (def_stmt)
&& (fndecl = gimple_call_fndecl (def_stmt))
&& DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_NORMAL
@@ -987,13 +1072,18 @@ vn_reference_lookup_3 (tree *refp, tree vuse, void *vr_)
&& operand_equal_p (base, base2, 0)
&& offset2 <= offset
&& offset2 + size2 >= offset + maxsize)
- return vn_reference_insert (ref,
- fold_convert (TREE_TYPE (ref),
- integer_zero_node), vuse);
+ {
+ tree val = fold_convert (vr->type, integer_zero_node);
+ unsigned int value_id = get_or_alloc_constant_value_id (val);
+ return vn_reference_insert_pieces (vuse, vr->set, vr->type,
+ VEC_copy (vn_reference_op_s,
+ heap, vr->operands),
+ val, value_id);
+ }
}
/* 2) Assignment from an empty CONSTRUCTOR. */
- else if (is_gimple_reg_type (TREE_TYPE (ref))
+ else if (is_gimple_reg_type (vr->type)
&& gimple_assign_single_p (def_stmt)
&& gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR
&& CONSTRUCTOR_NELTS (gimple_assign_rhs1 (def_stmt)) == 0)
@@ -1005,9 +1095,14 @@ vn_reference_lookup_3 (tree *refp, tree vuse, void *vr_)
if (operand_equal_p (base, base2, 0)
&& offset2 <= offset
&& offset2 + size2 >= offset + maxsize)
- return vn_reference_insert (ref,
- fold_convert (TREE_TYPE (ref),
- integer_zero_node), vuse);
+ {
+ tree val = fold_convert (vr->type, integer_zero_node);
+ unsigned int value_id = get_or_alloc_constant_value_id (val);
+ return vn_reference_insert_pieces (vuse, vr->set, vr->type,
+ VEC_copy (vn_reference_op_s,
+ heap, vr->operands),
+ val, value_id);
+ }
}
/* For aggregate copies translate the reference through them if
@@ -1022,6 +1117,7 @@ vn_reference_lookup_3 (tree *refp, tree vuse, void *vr_)
int i, j;
VEC (vn_reference_op_s, heap) *lhs = NULL, *rhs = NULL;
vn_reference_op_t vro;
+ ao_ref r;
/* See if the assignment kills REF. */
base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
@@ -1071,9 +1167,12 @@ vn_reference_lookup_3 (tree *refp, tree vuse, void *vr_)
VEC_replace (vn_reference_op_s, vr->operands, i + 1 + j, vro);
VEC_free (vn_reference_op_s, heap, rhs);
vr->hashcode = vn_reference_compute_hash (vr);
- *refp = get_ref_from_reference_ops (vr->operands);
- if (!*refp)
+
+ /* Adjust *ref from the new operands. */
+ if (!ao_ref_init_from_vn_reference (&r, vr->set, vr->type, vr->operands))
return (void *)-1;
+ gcc_assert (ref->size == r.size);
+ *ref = r;
/* Keep looking for the adjusted *REF / VR pair. */
return NULL;
@@ -1089,7 +1188,7 @@ vn_reference_lookup_3 (tree *refp, tree vuse, void *vr_)
vn_reference_t stored in the hashtable if something is found. */
tree
-vn_reference_lookup_pieces (tree vuse,
+vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
VEC (vn_reference_op_s, heap) *operands,
vn_reference_t *vnresult, bool maywalk)
{
@@ -1110,6 +1209,8 @@ vn_reference_lookup_pieces (tree vuse,
* VEC_length (vn_reference_op_s, operands));
vr1.operands = operands = shared_lookup_references
= valueize_refs (shared_lookup_references);
+ vr1.type = type;
+ vr1.set = set;
vr1.hashcode = vn_reference_compute_hash (&vr1);
vn_reference_lookup_1 (&vr1, vnresult);
@@ -1117,10 +1218,10 @@ vn_reference_lookup_pieces (tree vuse,
&& maywalk
&& vr1.vuse)
{
- tree ref = get_ref_from_reference_ops (operands);
- if (ref)
+ ao_ref r;
+ if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands))
*vnresult =
- (vn_reference_t)walk_non_aliased_vuses (ref, vr1.vuse,
+ (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
vn_reference_lookup_2,
vn_reference_lookup_3, &vr1);
if (vr1.operands != operands)
@@ -1151,14 +1252,18 @@ vn_reference_lookup (tree op, tree vuse, bool maywalk,
vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
vr1.operands = operands = valueize_shared_reference_ops_from_ref (op);
+ vr1.type = TREE_TYPE (op);
+ vr1.set = get_alias_set (op);
vr1.hashcode = vn_reference_compute_hash (&vr1);
if (maywalk
&& vr1.vuse)
{
vn_reference_t wvnresult;
+ ao_ref r;
+ ao_ref_init (&r, op);
wvnresult =
- (vn_reference_t)walk_non_aliased_vuses (op, vr1.vuse,
+ (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
vn_reference_lookup_2,
vn_reference_lookup_3, &vr1);
if (vr1.operands != operands)
@@ -1193,6 +1298,8 @@ vn_reference_insert (tree op, tree result, tree vuse)
vr1->value_id = get_or_alloc_constant_value_id (result);
vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
vr1->operands = valueize_refs (create_reference_ops_from_ref (op));
+ vr1->type = TREE_TYPE (op);
+ vr1->set = get_alias_set (op);
vr1->hashcode = vn_reference_compute_hash (vr1);
vr1->result = TREE_CODE (result) == SSA_NAME ? SSA_VAL (result) : result;
@@ -1220,7 +1327,7 @@ vn_reference_insert (tree op, tree result, tree vuse)
structure we created. */
vn_reference_t
-vn_reference_insert_pieces (tree vuse,
+vn_reference_insert_pieces (tree vuse, alias_set_type set, tree type,
VEC (vn_reference_op_s, heap) *operands,
tree result, unsigned int value_id)
@@ -1232,6 +1339,8 @@ vn_reference_insert_pieces (tree vuse,
vr1->value_id = value_id;
vr1->vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
vr1->operands = valueize_refs (operands);
+ vr1->type = type;
+ vr1->set = set;
vr1->hashcode = vn_reference_compute_hash (vr1);
if (result && TREE_CODE (result) == SSA_NAME)
result = SSA_VAL (result);
@@ -1825,6 +1934,8 @@ visit_reference_op_call (tree lhs, gimple stmt)
vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
vr1.operands = valueize_shared_reference_ops_from_call (stmt);
+ vr1.type = gimple_expr_type (stmt);
+ vr1.set = 0;
vr1.hashcode = vn_reference_compute_hash (&vr1);
result = vn_reference_lookup_1 (&vr1, NULL);
if (result)
@@ -1842,6 +1953,8 @@ visit_reference_op_call (tree lhs, gimple stmt)
vr2 = (vn_reference_t) pool_alloc (current_info->references_pool);
vr2->vuse = vr1.vuse;
vr2->operands = valueize_refs (create_reference_ops_from_call (stmt));
+ vr2->type = vr1.type;
+ vr2->set = vr1.set;
vr2->hashcode = vr1.hashcode;
vr2->result = lhs;
slot = htab_find_slot_with_hash (current_info->references,
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index c8171c22710..706ea4e44b8 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -92,6 +92,8 @@ typedef struct vn_reference_s
unsigned int value_id;
hashval_t hashcode;
tree vuse;
+ alias_set_type set;
+ tree type;
VEC (vn_reference_op_s, heap) *operands;
tree result;
} *vn_reference_t;
@@ -177,13 +179,14 @@ void vn_reference_fold_indirect (VEC (vn_reference_op_s, heap) **,
unsigned int *);
void copy_reference_ops_from_ref (tree, VEC(vn_reference_op_s, heap) **);
void copy_reference_ops_from_call (gimple, VEC(vn_reference_op_s, heap) **);
-tree get_ref_from_reference_ops (VEC(vn_reference_op_s, heap) *ops);
-tree vn_reference_lookup_pieces (tree,
+bool ao_ref_init_from_vn_reference (ao_ref *, alias_set_type, tree,
+ VEC (vn_reference_op_s, heap) *);
+tree vn_reference_lookup_pieces (tree, alias_set_type, tree,
VEC (vn_reference_op_s, heap) *,
vn_reference_t *, bool);
tree vn_reference_lookup (tree, tree, bool, vn_reference_t *);
vn_reference_t vn_reference_insert (tree, tree, tree);
-vn_reference_t vn_reference_insert_pieces (tree,
+vn_reference_t vn_reference_insert_pieces (tree, alias_set_type, tree,
VEC (vn_reference_op_s, heap) *,
tree, unsigned int);
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index ea47ec61d36..827a9162234 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -1864,7 +1864,8 @@ equiv_class_label_eq (const void *p1, const void *p2)
{
const_equiv_class_label_t const eql1 = (const_equiv_class_label_t) p1;
const_equiv_class_label_t const eql2 = (const_equiv_class_label_t) p2;
- return bitmap_equal_p (eql1->labels, eql2->labels);
+ return (eql1->hashcode == eql2->hashcode
+ && bitmap_equal_p (eql1->labels, eql2->labels));
}
/* Lookup a equivalence class in TABLE by the bitmap of LABELS it
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index e74251d69c3..3279d8c8f1e 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -1196,15 +1196,15 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
}
}
- vect_versioning_for_alias_required =
- (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)) > 0);
+ vect_versioning_for_alias_required
+ = LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo);
/* Temporarily, if versioning for alias is required, we disable peeling
until we support peeling and versioning. Often peeling for alignment
will require peeling for loop-bound, which in turn requires that we
know how to adjust the loop ivs after the loop. */
if (vect_versioning_for_alias_required
- || !vect_can_advance_ivs_p (loop_vinfo)
+ || !vect_can_advance_ivs_p (loop_vinfo)
|| !slpeel_can_duplicate_loop_p (loop, single_exit (loop)))
do_peeling = false;
@@ -1366,7 +1366,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
}
/* Versioning requires at least one misaligned data reference. */
- if (VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)) == 0)
+ if (!LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo))
do_versioning = false;
else if (!do_versioning)
VEC_truncate (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo), 0);
@@ -2356,10 +2356,9 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
tree data_ref_base = base_name;
fprintf (vect_dump, "create vector-pointer variable to type: ");
print_generic_expr (vect_dump, vectype, TDF_SLIM);
- if (TREE_CODE (data_ref_base) == VAR_DECL)
- fprintf (vect_dump, " vectorizing a one dimensional array ref: ");
- else if (TREE_CODE (data_ref_base) == ARRAY_REF)
- fprintf (vect_dump, " vectorizing a multidimensional array ref: ");
+ if (TREE_CODE (data_ref_base) == VAR_DECL
+ || TREE_CODE (data_ref_base) == ARRAY_REF)
+ fprintf (vect_dump, " vectorizing an array ref: ");
else if (TREE_CODE (data_ref_base) == COMPONENT_REF)
fprintf (vect_dump, " vectorizing a record based array ref: ");
else if (TREE_CODE (data_ref_base) == SSA_NAME)
@@ -2497,8 +2496,6 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
duplicate_ssa_name_ptr_info (indx_before_incr, DR_PTR_INFO (dr));
duplicate_ssa_name_ptr_info (indx_after_incr, DR_PTR_INFO (dr));
}
- merge_alias_info (vect_ptr_init, indx_before_incr);
- merge_alias_info (vect_ptr_init, indx_after_incr);
if (ptr_incr)
*ptr_incr = incr;
@@ -2529,8 +2526,6 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
duplicate_ssa_name_ptr_info (indx_before_incr, DR_PTR_INFO (dr));
duplicate_ssa_name_ptr_info (indx_after_incr, DR_PTR_INFO (dr));
}
- merge_alias_info (vect_ptr_init, indx_before_incr);
- merge_alias_info (vect_ptr_init, indx_after_incr);
if (ptr_incr)
*ptr_incr = incr;
@@ -2601,7 +2596,6 @@ bump_vector_ptr (tree dataref_ptr, gimple ptr_incr, gimple_stmt_iterator *gsi,
/* Copy the points-to information if it exists. */
if (DR_PTR_INFO (dr))
duplicate_ssa_name_ptr_info (new_dataref_ptr, DR_PTR_INFO (dr));
- merge_alias_info (new_dataref_ptr, dataref_ptr);
if (!ptr_incr)
return new_dataref_ptr;
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
index 3d7f5938afa..eaf263c4270 100644
--- a/gcc/tree-vect-loop-manip.c
+++ b/gcc/tree-vect-loop-manip.c
@@ -371,7 +371,6 @@ slpeel_update_phi_nodes_for_guard1 (edge guard_edge, struct loop *loop,
basic_block orig_bb = loop->header;
edge new_exit_e;
tree current_new_name;
- tree name;
gimple_stmt_iterator gsi_orig, gsi_update;
/* Create new bb between loop and new_merge_bb. */
@@ -387,15 +386,6 @@ slpeel_update_phi_nodes_for_guard1 (edge guard_edge, struct loop *loop,
orig_phi = gsi_stmt (gsi_orig);
update_phi = gsi_stmt (gsi_update);
- /* Virtual phi; Mark it for renaming. We actually want to call
- mar_sym_for_renaming, but since all ssa renaming datastructures
- are going to be freed before we get to call ssa_update, we just
- record this name for now in a bitmap, and will mark it for
- renaming later. */
- name = PHI_RESULT (orig_phi);
- if (!is_gimple_reg (SSA_NAME_VAR (name)))
- bitmap_set_bit (vect_memsyms_to_rename, DECL_UID (SSA_NAME_VAR (name)));
-
/** 1. Handle new-merge-point phis **/
/* 1.1. Generate new phi node in NEW_MERGE_BB: */
@@ -1690,7 +1680,7 @@ conservative_cost_threshold (loop_vec_info loop_vinfo,
th = (unsigned) min_profitable_iters;
if (th && vect_print_dump_info (REPORT_COST))
- fprintf (vect_dump, "Vectorization may not be profitable.");
+ fprintf (vect_dump, "Profitability threshold is %u loop iterations.", th);
return th;
}
@@ -1740,8 +1730,8 @@ vect_do_peeling_for_loop_bound (loop_vec_info loop_vinfo, tree *ratio,
/* If cost model check not done during versioning and
peeling for alignment. */
- if (!VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
- && !VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo))
+ if (!LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo)
+ && !LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo)
&& !LOOP_PEELING_FOR_ALIGNMENT (loop_vinfo)
&& !cond_expr)
{
@@ -2290,10 +2280,10 @@ vect_create_cond_for_alias_checks (loop_vec_info loop_vinfo,
else
*cond_expr = part_cond_expr;
}
- if (vect_print_dump_info (REPORT_VECTORIZED_LOCATIONS))
- fprintf (vect_dump, "created %u versioning for alias checks.\n",
- VEC_length (ddr_p, may_alias_ddrs));
+ if (vect_print_dump_info (REPORT_VECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "created %u versioning for alias checks.\n",
+ VEC_length (ddr_p, may_alias_ddrs));
}
@@ -2349,11 +2339,11 @@ vect_loop_versioning (loop_vec_info loop_vinfo, bool do_versioning,
*cond_expr = force_gimple_operand (*cond_expr, cond_expr_stmt_list,
false, NULL_TREE);
- if (VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)))
+ if (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo))
vect_create_cond_for_align_checks (loop_vinfo, cond_expr,
cond_expr_stmt_list);
- if (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
+ if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
vect_create_cond_for_alias_checks (loop_vinfo, cond_expr,
cond_expr_stmt_list);
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 33b0a9d5796..72de3d6441c 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -846,7 +846,7 @@ vect_analyze_loop_form (struct loop *loop)
if (loop->num_nodes != 2)
{
if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
- fprintf (vect_dump, "not vectorized: too many BBs in loop.");
+ fprintf (vect_dump, "not vectorized: control flow in loop.");
return NULL;
}
@@ -908,7 +908,7 @@ vect_analyze_loop_form (struct loop *loop)
if (loop->num_nodes != 5)
{
if (vect_print_dump_info (REPORT_BAD_FORM_LOOPS))
- fprintf (vect_dump, "not vectorized: too many BBs in loop.");
+ fprintf (vect_dump, "not vectorized: control flow in loop.");
destroy_loop_vec_info (inner_loop_vinfo, true);
return NULL;
}
@@ -1756,7 +1756,7 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo)
}
/* Requires loop versioning tests to handle misalignment. */
- if (VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo)))
+ if (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo))
{
/* FIXME: Make cost depend on complexity of individual check. */
vec_outside_cost +=
@@ -1766,7 +1766,8 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo)
"versioning to treat misalignment.\n");
}
- if (VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
+ /* Requires loop versioning with alias checks. */
+ if (LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
{
/* FIXME: Make cost depend on complexity of individual check. */
vec_outside_cost +=
@@ -1776,11 +1777,9 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo)
"versioning aliasing.\n");
}
- if (VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
- || VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
- {
- vec_outside_cost += TARG_COND_TAKEN_BRANCH_COST;
- }
+ if (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo)
+ || LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
+ vec_outside_cost += TARG_COND_TAKEN_BRANCH_COST;
/* Count statements in scalar loop. Using this as scalar cost for a single
iteration for now.
@@ -1946,12 +1945,12 @@ vect_estimate_min_profitable_iters (loop_vec_info loop_vinfo)
decide whether to vectorize at compile time. Hence the scalar version
do not carry cost model guard costs. */
if (!LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
- || VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
- || VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
+ || LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo)
+ || LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
{
/* Cost model check occurs at versioning. */
- if (VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
- || VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
+ if (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo)
+ || LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
scalar_outside_cost += TARG_COND_NOT_TAKEN_BRANCH_COST;
else
{
@@ -3648,16 +3647,12 @@ vect_transform_loop (loop_vec_info loop_vinfo)
|| (LOOP_VINFO_NITERS_KNOWN_P (loop_vinfo)
&& LOOP_VINFO_INT_NITERS (loop_vinfo) % vectorization_factor != 0));
- if (VEC_length (gimple, LOOP_VINFO_MAY_MISALIGN_STMTS (loop_vinfo))
- || VEC_length (ddr_p, LOOP_VINFO_MAY_ALIAS_DDRS (loop_vinfo)))
+ if (LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT (loop_vinfo)
+ || LOOP_REQUIRES_VERSIONING_FOR_ALIAS (loop_vinfo))
vect_loop_versioning (loop_vinfo,
!do_peeling_for_loop_bound,
&cond_expr, &cond_expr_stmt_list);
- /* CHECKME: we wouldn't need this if we called update_ssa once
- for all loops. */
- bitmap_zero (vect_memsyms_to_rename);
-
/* If the loop has a symbolic number of iterations 'n' (i.e. it's not a
compile time constant), or it is a constant that doesn't divide by the
vectorization factor, then an epilog loop needs to be created.
@@ -3812,8 +3807,6 @@ vect_transform_loop (loop_vec_info loop_vinfo)
slpeel_make_loop_iterate_ntimes (loop, ratio);
- mark_set_for_renaming (vect_memsyms_to_rename);
-
/* The memory tags and pointers in vectorized statements need to
have their SSA forms updated. FIXME, why can't this be delayed
until all the loops have been transformed? */
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index 6c932109baf..1017847a5f1 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -912,7 +912,8 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
if (unrolling_factor != 1 && !loop_vinfo)
{
if (vect_print_dump_info (REPORT_SLP))
- fprintf (vect_dump, "Build SLP failed: unrolling required in BB SLP");
+ fprintf (vect_dump, "Build SLP failed: unrolling required in basic"
+ " block SLP");
return false;
}
@@ -1367,7 +1368,7 @@ vect_slp_analyze_bb (basic_block bb)
}
if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "BB will be vectorized using SLP\n");
+ fprintf (vect_dump, "Basic block will be vectorized using SLP\n");
return bb_vinfo;
}
@@ -2088,7 +2089,7 @@ vect_slp_transform_bb (basic_block bb)
update_ssa (TODO_update_ssa);
if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "BB VECTORIZED\n");
+ fprintf (vect_dump, "BASIC BLOCK VECTORIZED\n");
destroy_bb_vec_info (bb_vinfo);
}
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 5ca8d942e18..be6e2c6ec18 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -2903,7 +2903,9 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
scalar_dest = gimple_assign_lhs (stmt);
if (TREE_CODE (scalar_dest) != ARRAY_REF
&& TREE_CODE (scalar_dest) != INDIRECT_REF
- && !STMT_VINFO_STRIDED_ACCESS (stmt_info))
+ && TREE_CODE (scalar_dest) != COMPONENT_REF
+ && TREE_CODE (scalar_dest) != IMAGPART_EXPR
+ && TREE_CODE (scalar_dest) != REALPART_EXPR)
return false;
gcc_assert (gimple_assign_single_p (stmt));
@@ -3285,7 +3287,9 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
code = gimple_assign_rhs_code (stmt);
if (code != ARRAY_REF
&& code != INDIRECT_REF
- && !STMT_VINFO_STRIDED_ACCESS (stmt_info))
+ && code != COMPONENT_REF
+ && code != IMAGPART_EXPR
+ && code != REALPART_EXPR)
return false;
if (!STMT_VINFO_DATA_REF (stmt_info))
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index 4ab8547dee2..2c2103eda0a 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -81,9 +81,6 @@ static enum verbosity_levels user_vect_verbosity_level = MAX_VERBOSITY_LEVEL;
/* Loop or bb location. */
LOC vect_location;
-/* Bitmap of virtual variables to be renamed. */
-bitmap vect_memsyms_to_rename;
-
/* Vector mapping GIMPLE stmt to stmt_vec_info. */
VEC(vec_void_p,heap) *stmt_vec_info_vec;
@@ -206,10 +203,6 @@ vectorize_loops (void)
/* Fix the verbosity level if not defined explicitly by the user. */
vect_set_dump_settings (false);
- /* Allocate the bitmap that records which virtual variables
- need to be renamed. */
- vect_memsyms_to_rename = BITMAP_ALLOC (NULL);
-
init_stmt_vec_info_vec ();
/* ----------- Analyze loops. ----------- */
@@ -244,7 +237,7 @@ vectorize_loops (void)
/* ----------- Finalize. ----------- */
- BITMAP_FREE (vect_memsyms_to_rename);
+ mark_sym_for_renaming (gimple_vop (cfun));
for (i = 1; i < vect_loops_num; i++)
{
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index bf2917008b1..c78e76853b6 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -239,33 +239,38 @@ typedef struct _loop_vec_info {
} *loop_vec_info;
/* Access Functions. */
-#define LOOP_VINFO_LOOP(L) (L)->loop
-#define LOOP_VINFO_BBS(L) (L)->bbs
-#define LOOP_VINFO_NITERS(L) (L)->num_iters
+#define LOOP_VINFO_LOOP(L) (L)->loop
+#define LOOP_VINFO_BBS(L) (L)->bbs
+#define LOOP_VINFO_NITERS(L) (L)->num_iters
/* Since LOOP_VINFO_NITERS can change after prologue peeling
retain total unchanged scalar loop iterations for cost model. */
-#define LOOP_VINFO_NITERS_UNCHANGED(L) (L)->num_iters_unchanged
-#define LOOP_VINFO_COST_MODEL_MIN_ITERS(L) (L)->min_profitable_iters
-#define LOOP_VINFO_VECTORIZABLE_P(L) (L)->vectorizable
-#define LOOP_VINFO_VECT_FACTOR(L) (L)->vectorization_factor
-#define LOOP_VINFO_PTR_MASK(L) (L)->ptr_mask
-#define LOOP_VINFO_DATAREFS(L) (L)->datarefs
-#define LOOP_VINFO_DDRS(L) (L)->ddrs
-#define LOOP_VINFO_INT_NITERS(L) (TREE_INT_CST_LOW ((L)->num_iters))
-#define LOOP_PEELING_FOR_ALIGNMENT(L) (L)->peeling_for_alignment
-#define LOOP_VINFO_UNALIGNED_DR(L) (L)->unaligned_dr
-#define LOOP_VINFO_MAY_MISALIGN_STMTS(L) (L)->may_misalign_stmts
-#define LOOP_VINFO_LOC(L) (L)->loop_line_number
-#define LOOP_VINFO_MAY_ALIAS_DDRS(L) (L)->may_alias_ddrs
-#define LOOP_VINFO_STRIDED_STORES(L) (L)->strided_stores
-#define LOOP_VINFO_SLP_INSTANCES(L) (L)->slp_instances
+#define LOOP_VINFO_NITERS_UNCHANGED(L) (L)->num_iters_unchanged
+#define LOOP_VINFO_COST_MODEL_MIN_ITERS(L) (L)->min_profitable_iters
+#define LOOP_VINFO_VECTORIZABLE_P(L) (L)->vectorizable
+#define LOOP_VINFO_VECT_FACTOR(L) (L)->vectorization_factor
+#define LOOP_VINFO_PTR_MASK(L) (L)->ptr_mask
+#define LOOP_VINFO_DATAREFS(L) (L)->datarefs
+#define LOOP_VINFO_DDRS(L) (L)->ddrs
+#define LOOP_VINFO_INT_NITERS(L) (TREE_INT_CST_LOW ((L)->num_iters))
+#define LOOP_PEELING_FOR_ALIGNMENT(L) (L)->peeling_for_alignment
+#define LOOP_VINFO_UNALIGNED_DR(L) (L)->unaligned_dr
+#define LOOP_VINFO_MAY_MISALIGN_STMTS(L) (L)->may_misalign_stmts
+#define LOOP_VINFO_LOC(L) (L)->loop_line_number
+#define LOOP_VINFO_MAY_ALIAS_DDRS(L) (L)->may_alias_ddrs
+#define LOOP_VINFO_STRIDED_STORES(L) (L)->strided_stores
+#define LOOP_VINFO_SLP_INSTANCES(L) (L)->slp_instances
#define LOOP_VINFO_SLP_UNROLLING_FACTOR(L) (L)->slp_unrolling_factor
+#define LOOP_REQUIRES_VERSIONING_FOR_ALIGNMENT(L) \
+VEC_length (gimple, (L)->may_misalign_stmts) > 0
+#define LOOP_REQUIRES_VERSIONING_FOR_ALIAS(L) \
+VEC_length (ddr_p, (L)->may_alias_ddrs) > 0
+
#define NITERS_KNOWN_P(n) \
(host_integerp ((n),0) \
&& TREE_INT_CST_LOW ((n)) > 0)
-#define LOOP_VINFO_NITERS_KNOWN_P(L) \
+#define LOOP_VINFO_NITERS_KNOWN_P(L) \
NITERS_KNOWN_P((L)->num_iters)
static inline loop_vec_info
@@ -728,9 +733,6 @@ known_alignment_for_access_p (struct data_reference *data_ref_info)
extern FILE *vect_dump;
extern LOC vect_loop_location;
-/* Bitmap of virtual variables to be renamed. */
-extern bitmap vect_memsyms_to_rename;
-
/*-----------------------------------------------------------------*/
/* Function prototypes. */
/*-----------------------------------------------------------------*/
diff --git a/gcc/tree.c b/gcc/tree.c
index ddfa0a43258..5e562a59e05 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -4169,7 +4169,8 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
if (*no_add_attrs == false)
DECL_DLLIMPORT_P (node) = 1;
}
- else if (DECL_DECLARED_INLINE_P (node))
+ else if (TREE_CODE (node) == FUNCTION_DECL
+ && DECL_DECLARED_INLINE_P (node))
/* An exported function, even if inline, must be emitted. */
DECL_EXTERNAL (node) = 0;
diff --git a/gcc/tree.h b/gcc/tree.h
index 0adf75d9530..d88d85f18c0 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1502,6 +1502,11 @@ struct GTY(()) tree_vec {
_ce___->value = VALUE; \
} while (0)
+/* True if NODE, a FIELD_DECL, is to be processed as a bitfield for
+ constructor output purposes. */
+#define CONSTRUCTOR_BITFIELD_P(NODE) \
+ (DECL_BIT_FIELD (FIELD_DECL_CHECK (NODE)) && DECL_MODE (NODE) != BLKmode)
+
/* A single element of a CONSTRUCTOR. VALUE holds the actual value of the
element. INDEX can optionally design the position of VALUE: in arrays,
it is the index where VALUE has to be placed; in structures, it is the
@@ -5020,7 +5025,7 @@ extern tree tree_overlaps_hard_reg_set (tree, HARD_REG_SET *);
/* Generate a new label for the CFI info to refer to. */
-extern char *dwarf2out_cfi_label (void);
+extern char *dwarf2out_cfi_label (bool);
/* Entry point to update the canonical frame address (CFA). */
diff --git a/gcc/unwind-dw2.c b/gcc/unwind-dw2.c
index dd3dd549cd1..68a1a282b34 100644
--- a/gcc/unwind-dw2.c
+++ b/gcc/unwind-dw2.c
@@ -1473,18 +1473,31 @@ uw_init_context_1 (struct _Unwind_Context *context,
context->ra = __builtin_extract_return_addr (outer_ra);
}
+static void _Unwind_DebugHook (void *, void *) __attribute__ ((__noinline__));
+
+/* This function is called during unwinding. It is intended as a hook
+ for a debugger to intercept exceptions. CFA is the CFA of the
+ target frame. HANDLER is the PC to which control will be
+ transferred. */
+static void
+_Unwind_DebugHook (void *cfa __attribute__ ((__unused__)),
+ void *handler __attribute__ ((__unused__)))
+{
+ asm ("");
+}
/* Install TARGET into CURRENT so that we can return to it. This is a
macro because __builtin_eh_return must be invoked in the context of
our caller. */
-#define uw_install_context(CURRENT, TARGET) \
- do \
- { \
- long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
- void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
- __builtin_eh_return (offset, handler); \
- } \
+#define uw_install_context(CURRENT, TARGET) \
+ do \
+ { \
+ long offset = uw_install_context_1 ((CURRENT), (TARGET)); \
+ void *handler = __builtin_frob_return_addr ((TARGET)->ra); \
+ _Unwind_DebugHook ((TARGET)->cfa, handler); \
+ __builtin_eh_return (offset, handler); \
+ } \
while (0)
static long
diff --git a/gcc/varasm.c b/gcc/varasm.c
index c85cf9ddf27..c5de9ae7a73 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -114,7 +114,6 @@ static void output_constant_def_contents (rtx);
static void output_addressed_constants (tree);
static unsigned HOST_WIDE_INT array_size_for_constructor (tree);
static unsigned min_align (unsigned, unsigned);
-static void output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int);
static void globalize_decl (tree);
#ifdef BSS_SECTION_ASM_OP
#ifdef ASM_OUTPUT_BSS
@@ -4366,6 +4365,55 @@ initializer_constant_valid_p (tree value, tree endtype)
return 0;
}
+/* Return true if VALUE is a valid constant-valued expression
+ for use in initializing a static bit-field; one that can be
+ an element of a "constant" initializer. */
+
+bool
+initializer_constant_valid_for_bitfield_p (tree value)
+{
+ /* For bitfields we support integer constants or possibly nested aggregates
+ of such. */
+ switch (TREE_CODE (value))
+ {
+ case CONSTRUCTOR:
+ {
+ unsigned HOST_WIDE_INT idx;
+ tree elt;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (value), idx, elt)
+ if (!initializer_constant_valid_for_bitfield_p (elt))
+ return false;
+ return true;
+ }
+
+ case INTEGER_CST:
+ return true;
+
+ case VIEW_CONVERT_EXPR:
+ case NON_LVALUE_EXPR:
+ return
+ initializer_constant_valid_for_bitfield_p (TREE_OPERAND (value, 0));
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+/* output_constructor outer state of relevance in recursive calls, typically
+ for nested aggregate bitfields. */
+
+typedef struct {
+ unsigned int bit_offset; /* current position in ... */
+ int byte; /* ... the outer byte buffer. */
+} oc_outer_state;
+
+static unsigned HOST_WIDE_INT
+ output_constructor (tree, unsigned HOST_WIDE_INT, unsigned int,
+ oc_outer_state *);
+
/* Output assembler code for constant EXP to FILE, with no label.
This includes the pseudo-op such as ".int" or ".byte", and a newline.
Assumes output_addressed_constants has been done on EXP already.
@@ -4504,7 +4552,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
switch (TREE_CODE (exp))
{
case CONSTRUCTOR:
- output_constructor (exp, size, align);
+ output_constructor (exp, size, align, NULL);
return;
case STRING_CST:
thissize = MIN ((unsigned HOST_WIDE_INT)TREE_STRING_LENGTH (exp),
@@ -4542,7 +4590,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT size, unsigned int align)
case RECORD_TYPE:
case UNION_TYPE:
gcc_assert (TREE_CODE (exp) == CONSTRUCTOR);
- output_constructor (exp, size, align);
+ output_constructor (exp, size, align, NULL);
return;
case ERROR_MARK:
@@ -4598,316 +4646,462 @@ array_size_for_constructor (tree val)
return tree_low_cst (i, 1);
}
-/* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
- Generate at least SIZE bytes, padding if necessary. */
+/* Other datastructures + helpers for output_constructor. */
-static void
-output_constructor (tree exp, unsigned HOST_WIDE_INT size,
- unsigned int align)
-{
- tree type = TREE_TYPE (exp);
- tree field = 0;
- tree min_index = 0;
- /* Number of bytes output or skipped so far.
- In other words, current position within the constructor. */
- HOST_WIDE_INT total_bytes = 0;
- /* Nonzero means BYTE contains part of a byte, to be output. */
- int byte_buffer_in_use = 0;
- int byte = 0;
- unsigned HOST_WIDE_INT cnt;
- constructor_elt *ce;
+/* output_constructor local state to support interaction with helpers. */
- gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
+typedef struct {
- if (TREE_CODE (type) == RECORD_TYPE)
- field = TYPE_FIELDS (type);
+ /* Received arguments. */
+ tree exp; /* Constructor expression. */
+ unsigned HOST_WIDE_INT size; /* # bytes to output - pad if necessary. */
+ unsigned int align; /* Known initial alignment. */
- if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_DOMAIN (type) != 0)
- min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (type));
+ /* Constructor expression data. */
+ tree type; /* Expression type. */
+ tree field; /* Current field decl in a record. */
+ tree min_index; /* Lower bound if specified for an array. */
- /* As LINK goes through the elements of the constant,
- FIELD goes through the structure fields, if the constant is a structure.
- if the constant is a union, then we override this,
- by getting the field from the TREE_LIST element.
- But the constant could also be an array. Then FIELD is zero.
+ /* Output processing state. */
+ HOST_WIDE_INT total_bytes; /* # bytes output so far / current position. */
+ bool byte_buffer_in_use; /* Whether byte ... */
+ int byte; /* ... contains part of a bitfield byte yet to
+ be output. */
- There is always a maximum of one element in the chain LINK for unions
- (even if the initializer in a source program incorrectly contains
- more one). */
- for (cnt = 0;
- VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), cnt, ce);
- cnt++, field = field ? TREE_CHAIN (field) : 0)
+ int last_relative_index; /* Implicit or explicit index of the last
+ array element output within a bitfield. */
+ /* Current element. */
+ tree val; /* Current element value. */
+ tree index; /* Current element index. */
+
+} oc_local_state;
+
+/* Helper for output_constructor. From the current LOCAL state, output a
+ RANGE_EXPR element. */
+
+static void
+output_constructor_array_range (oc_local_state *local)
+{
+ unsigned HOST_WIDE_INT fieldsize
+ = int_size_in_bytes (TREE_TYPE (local->type));
+
+ HOST_WIDE_INT lo_index
+ = tree_low_cst (TREE_OPERAND (local->index, 0), 0);
+ HOST_WIDE_INT hi_index
+ = tree_low_cst (TREE_OPERAND (local->index, 1), 0);
+ HOST_WIDE_INT index;
+
+ unsigned int align2
+ = min_align (local->align, fieldsize * BITS_PER_UNIT);
+
+ for (index = lo_index; index <= hi_index; index++)
{
- tree val = ce->value;
- tree index = 0;
+ /* Output the element's initial value. */
+ if (local->val == NULL_TREE)
+ assemble_zeros (fieldsize);
+ else
+ output_constant (local->val, fieldsize, align2);
+
+ /* Count its size. */
+ local->total_bytes += fieldsize;
+ }
+}
- /* The element in a union constructor specifies the proper field
- or index. */
- if ((TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE
- || TREE_CODE (type) == QUAL_UNION_TYPE)
- && ce->index != 0)
- field = ce->index;
+/* Helper for output_constructor. From the current LOCAL state, output a
+ field element that is not true bitfield or part of an outer one. */
- else if (TREE_CODE (type) == ARRAY_TYPE)
- index = ce->index;
+static void
+output_constructor_regular_field (oc_local_state *local)
+{
+ /* Field size and position. Since this structure is static, we know the
+ positions are constant. */
+ unsigned HOST_WIDE_INT fieldsize;
+ HOST_WIDE_INT fieldpos;
-#ifdef ASM_COMMENT_START
- if (field && flag_verbose_asm)
- fprintf (asm_out_file, "%s %s:\n",
- ASM_COMMENT_START,
- DECL_NAME (field)
- ? IDENTIFIER_POINTER (DECL_NAME (field))
- : "<anonymous>");
-#endif
+ unsigned int align2;
- /* Eliminate the marker that makes a cast not be an lvalue. */
- if (val != 0)
- STRIP_NOPS (val);
+ if (local->index != NULL_TREE)
+ fieldpos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (local->val)), 1)
+ * ((tree_low_cst (local->index, 0)
+ - tree_low_cst (local->min_index, 0))));
+ else if (local->field != NULL_TREE)
+ fieldpos = int_byte_position (local->field);
+ else
+ fieldpos = 0;
+
+ /* Output any buffered-up bit-fields preceding this element. */
+ if (local->byte_buffer_in_use)
+ {
+ assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+ local->total_bytes++;
+ local->byte_buffer_in_use = false;
+ }
+
+ /* Advance to offset of this element.
+ Note no alignment needed in an array, since that is guaranteed
+ if each element has the proper size. */
+ if ((local->field != NULL_TREE || local->index != NULL_TREE)
+ && fieldpos != local->total_bytes)
+ {
+ gcc_assert (fieldpos >= local->total_bytes);
+ assemble_zeros (fieldpos - local->total_bytes);
+ local->total_bytes = fieldpos;
+ }
+
+ /* Find the alignment of this element. */
+ align2 = min_align (local->align, BITS_PER_UNIT * fieldpos);
- if (index && TREE_CODE (index) == RANGE_EXPR)
+ /* Determine size this element should occupy. */
+ if (local->field)
+ {
+ fieldsize = 0;
+
+ /* If this is an array with an unspecified upper bound,
+ the initializer determines the size. */
+ /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
+ but we cannot do this until the deprecated support for
+ initializing zero-length array members is removed. */
+ if (TREE_CODE (TREE_TYPE (local->field)) == ARRAY_TYPE
+ && TYPE_DOMAIN (TREE_TYPE (local->field))
+ && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (local->field))))
{
- unsigned HOST_WIDE_INT fieldsize
- = int_size_in_bytes (TREE_TYPE (type));
- HOST_WIDE_INT lo_index = tree_low_cst (TREE_OPERAND (index, 0), 0);
- HOST_WIDE_INT hi_index = tree_low_cst (TREE_OPERAND (index, 1), 0);
- HOST_WIDE_INT index;
- unsigned int align2 = min_align (align, fieldsize * BITS_PER_UNIT);
-
- for (index = lo_index; index <= hi_index; index++)
- {
- /* Output the element's initial value. */
- if (val == 0)
- assemble_zeros (fieldsize);
- else
- output_constant (val, fieldsize, align2);
-
- /* Count its size. */
- total_bytes += fieldsize;
- }
+ fieldsize = array_size_for_constructor (local->val);
+ /* Given a non-empty initialization, this field had
+ better be last. */
+ gcc_assert (!fieldsize || !TREE_CHAIN (local->field));
}
- else if (field == 0 || !DECL_BIT_FIELD (field))
+ else if (DECL_SIZE_UNIT (local->field))
{
- /* An element that is not a bit-field. */
+ /* ??? This can't be right. If the decl size overflows
+ a host integer we will silently emit no data. */
+ if (host_integerp (DECL_SIZE_UNIT (local->field), 1))
+ fieldsize = tree_low_cst (DECL_SIZE_UNIT (local->field), 1);
+ }
+ }
+ else
+ fieldsize = int_size_in_bytes (TREE_TYPE (local->type));
+
+ /* Output the element's initial value. */
+ if (local->val == NULL_TREE)
+ assemble_zeros (fieldsize);
+ else
+ output_constant (local->val, fieldsize, align2);
- unsigned HOST_WIDE_INT fieldsize;
- /* Since this structure is static,
- we know the positions are constant. */
- HOST_WIDE_INT pos = field ? int_byte_position (field) : 0;
- unsigned int align2;
+ /* Count its size. */
+ local->total_bytes += fieldsize;
+}
- if (index != 0)
- pos = (tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (val)), 1)
- * (tree_low_cst (index, 0) - tree_low_cst (min_index, 0)));
+/* Helper for output_constructor. From the current LOCAL and OUTER states,
+ output an element that is a true bitfield or part of an outer one. */
- /* Output any buffered-up bit-fields preceding this element. */
- if (byte_buffer_in_use)
- {
- assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
- total_bytes++;
- byte_buffer_in_use = 0;
- }
-
- /* Advance to offset of this element.
- Note no alignment needed in an array, since that is guaranteed
- if each element has the proper size. */
- if ((field != 0 || index != 0) && pos != total_bytes)
- {
- gcc_assert (pos >= total_bytes);
- assemble_zeros (pos - total_bytes);
- total_bytes = pos;
- }
+static void
+output_constructor_bitfield (oc_local_state *local, oc_outer_state *outer)
+{
+ /* Bit size of this element. */
+ HOST_WIDE_INT ebitsize
+ = (local->field
+ ? tree_low_cst (DECL_SIZE (local->field), 1)
+ : tree_low_cst (TYPE_SIZE (TREE_TYPE (local->type)), 1));
+
+ /* Relative index of this element if this is an array component. */
+ HOST_WIDE_INT relative_index
+ = (!local->field
+ ? (local->index
+ ? (tree_low_cst (local->index, 0)
+ - tree_low_cst (local->min_index, 0))
+ : local->last_relative_index + 1)
+ : 0);
+
+ /* Bit position of this element from the start of the containing
+ constructor. */
+ HOST_WIDE_INT constructor_relative_ebitpos
+ = (local->field
+ ? int_bit_position (local->field)
+ : ebitsize * relative_index);
+
+ /* Bit position of this element from the start of a possibly ongoing
+ outer byte buffer. */
+ HOST_WIDE_INT byte_relative_ebitpos
+ = ((outer ? outer->bit_offset : 0) + constructor_relative_ebitpos);
+
+ /* From the start of a possibly ongoing outer byte buffer, offsets to
+ the first bit of this element and to the first bit past the end of
+ this element. */
+ HOST_WIDE_INT next_offset = byte_relative_ebitpos;
+ HOST_WIDE_INT end_offset = byte_relative_ebitpos + ebitsize;
+
+ local->last_relative_index = relative_index;
+
+ if (local->val == NULL_TREE)
+ local->val = integer_zero_node;
+
+ while (TREE_CODE (local->val) == VIEW_CONVERT_EXPR
+ || TREE_CODE (local->val) == NON_LVALUE_EXPR)
+ local->val = TREE_OPERAND (local->val, 0);
+
+ if (TREE_CODE (local->val) != INTEGER_CST
+ && TREE_CODE (local->val) != CONSTRUCTOR)
+ {
+ error ("invalid initial value for member %qE", DECL_NAME (local->field));
+ return;
+ }
- /* Find the alignment of this element. */
- align2 = min_align (align, BITS_PER_UNIT * pos);
+ /* If this field does not start in this (or, next) byte,
+ skip some bytes. */
+ if (next_offset / BITS_PER_UNIT != local->total_bytes)
+ {
+ /* Output remnant of any bit field in previous bytes. */
+ if (local->byte_buffer_in_use)
+ {
+ assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+ local->total_bytes++;
+ local->byte_buffer_in_use = false;
+ }
+
+ /* If still not at proper byte, advance to there. */
+ if (next_offset / BITS_PER_UNIT != local->total_bytes)
+ {
+ gcc_assert (next_offset / BITS_PER_UNIT >= local->total_bytes);
+ assemble_zeros (next_offset / BITS_PER_UNIT - local->total_bytes);
+ local->total_bytes = next_offset / BITS_PER_UNIT;
+ }
+ }
+
+ /* Set up the buffer if necessary. */
+ if (!local->byte_buffer_in_use)
+ {
+ local->byte = 0;
+ if (ebitsize > 0)
+ local->byte_buffer_in_use = true;
+ }
+
+ /* If this is nested constructor, recurse passing the bit offset and the
+ pending data, then retrieve the new pending data afterwards. */
+ if (TREE_CODE (local->val) == CONSTRUCTOR)
+ {
+ oc_outer_state output_state;
- /* Determine size this element should occupy. */
- if (field)
+ output_state.bit_offset = next_offset % BITS_PER_UNIT;
+ output_state.byte = local->byte;
+ local->total_bytes
+ += output_constructor (local->val, 0, 0, &output_state);
+ local->byte = output_state.byte;
+ return;
+ }
+
+ /* Otherwise, we must split the element into pieces that fall within
+ separate bytes, and combine each byte with previous or following
+ bit-fields. */
+ while (next_offset < end_offset)
+ {
+ int this_time;
+ int shift;
+ HOST_WIDE_INT value;
+ HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
+ HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
+
+ /* Advance from byte to byte
+ within this element when necessary. */
+ while (next_byte != local->total_bytes)
+ {
+ assemble_integer (GEN_INT (local->byte), 1, BITS_PER_UNIT, 1);
+ local->total_bytes++;
+ local->byte = 0;
+ }
+
+ /* Number of bits we can process at once
+ (all part of the same byte). */
+ this_time = MIN (end_offset - next_offset,
+ BITS_PER_UNIT - next_bit);
+ if (BYTES_BIG_ENDIAN)
+ {
+ /* On big-endian machine, take the most significant bits
+ first (of the bits that are significant)
+ and put them into bytes from the most significant end. */
+ shift = end_offset - next_offset - this_time;
+
+ /* Don't try to take a bunch of bits that cross
+ the word boundary in the INTEGER_CST. We can
+ only select bits from the LOW or HIGH part
+ not from both. */
+ if (shift < HOST_BITS_PER_WIDE_INT
+ && shift + this_time > HOST_BITS_PER_WIDE_INT)
{
- fieldsize = 0;
-
- /* If this is an array with an unspecified upper bound,
- the initializer determines the size. */
- /* ??? This ought to only checked if DECL_SIZE_UNIT is NULL,
- but we cannot do this until the deprecated support for
- initializing zero-length array members is removed. */
- if (TREE_CODE (TREE_TYPE (field)) == ARRAY_TYPE
- && TYPE_DOMAIN (TREE_TYPE (field))
- && ! TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (field))))
- {
- fieldsize = array_size_for_constructor (val);
- /* Given a non-empty initialization, this field had
- better be last. */
- gcc_assert (!fieldsize || !TREE_CHAIN (field));
- }
- else if (DECL_SIZE_UNIT (field))
- {
- /* ??? This can't be right. If the decl size overflows
- a host integer we will silently emit no data. */
- if (host_integerp (DECL_SIZE_UNIT (field), 1))
- fieldsize = tree_low_cst (DECL_SIZE_UNIT (field), 1);
- }
+ this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
+ shift = HOST_BITS_PER_WIDE_INT;
}
+
+ /* Now get the bits from the appropriate constant word. */
+ if (shift < HOST_BITS_PER_WIDE_INT)
+ value = TREE_INT_CST_LOW (local->val);
else
- fieldsize = int_size_in_bytes (TREE_TYPE (type));
-
- /* Output the element's initial value. */
- if (val == 0)
- assemble_zeros (fieldsize);
- else
- output_constant (val, fieldsize, align2);
-
- /* Count its size. */
- total_bytes += fieldsize;
+ {
+ gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
+ value = TREE_INT_CST_HIGH (local->val);
+ shift -= HOST_BITS_PER_WIDE_INT;
+ }
+
+ /* Get the result. This works only when:
+ 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
+ local->byte |= (((value >> shift)
+ & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
+ << (BITS_PER_UNIT - this_time - next_bit));
}
- else if (val != 0 && TREE_CODE (val) != INTEGER_CST)
- error ("invalid initial value for member %qE",
- DECL_NAME (field));
else
{
- /* Element that is a bit-field. */
+ /* On little-endian machines,
+ take first the least significant bits of the value
+ and pack them starting at the least significant
+ bits of the bytes. */
+ shift = next_offset - byte_relative_ebitpos;
+
+ /* Don't try to take a bunch of bits that cross
+ the word boundary in the INTEGER_CST. We can
+ only select bits from the LOW or HIGH part
+ not from both. */
+ if (shift < HOST_BITS_PER_WIDE_INT
+ && shift + this_time > HOST_BITS_PER_WIDE_INT)
+ this_time = (HOST_BITS_PER_WIDE_INT - shift);
+
+ /* Now get the bits from the appropriate constant word. */
+ if (shift < HOST_BITS_PER_WIDE_INT)
+ value = TREE_INT_CST_LOW (local->val);
+ else
+ {
+ gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
+ value = TREE_INT_CST_HIGH (local->val);
+ shift -= HOST_BITS_PER_WIDE_INT;
+ }
+
+ /* Get the result. This works only when:
+ 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
+ local->byte |= (((value >> shift)
+ & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
+ << next_bit);
+ }
+
+ next_offset += this_time;
+ local->byte_buffer_in_use = true;
+ }
+}
- HOST_WIDE_INT next_offset = int_bit_position (field);
- HOST_WIDE_INT end_offset
- = (next_offset + tree_low_cst (DECL_SIZE (field), 1));
+/* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
+ Generate at least SIZE bytes, padding if necessary. OUTER designates the
+ caller output state of relevance in recursive invocations. */
- if (val == 0)
- val = integer_zero_node;
+static unsigned HOST_WIDE_INT
+output_constructor (tree exp, unsigned HOST_WIDE_INT size,
+ unsigned int align, oc_outer_state * outer)
+{
+ unsigned HOST_WIDE_INT cnt;
+ constructor_elt *ce;
- /* If this field does not start in this (or, next) byte,
- skip some bytes. */
- if (next_offset / BITS_PER_UNIT != total_bytes)
- {
- /* Output remnant of any bit field in previous bytes. */
- if (byte_buffer_in_use)
- {
- assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
- total_bytes++;
- byte_buffer_in_use = 0;
- }
+ oc_local_state local;
- /* If still not at proper byte, advance to there. */
- if (next_offset / BITS_PER_UNIT != total_bytes)
- {
- gcc_assert (next_offset / BITS_PER_UNIT >= total_bytes);
- assemble_zeros (next_offset / BITS_PER_UNIT - total_bytes);
- total_bytes = next_offset / BITS_PER_UNIT;
- }
- }
+ /* Setup our local state to communicate with helpers. */
+ local.exp = exp;
+ local.size = size;
+ local.align = align;
- if (! byte_buffer_in_use)
- byte = 0;
+ local.total_bytes = 0;
+ local.byte_buffer_in_use = outer != NULL;
+ local.byte = outer ? outer->byte : 0;
- /* We must split the element into pieces that fall within
- separate bytes, and combine each byte with previous or
- following bit-fields. */
+ local.type = TREE_TYPE (exp);
- /* next_offset is the offset n fbits from the beginning of
- the structure to the next bit of this element to be processed.
- end_offset is the offset of the first bit past the end of
- this element. */
- while (next_offset < end_offset)
- {
- int this_time;
- int shift;
- HOST_WIDE_INT value;
- HOST_WIDE_INT next_byte = next_offset / BITS_PER_UNIT;
- HOST_WIDE_INT next_bit = next_offset % BITS_PER_UNIT;
-
- /* Advance from byte to byte
- within this element when necessary. */
- while (next_byte != total_bytes)
- {
- assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
- total_bytes++;
- byte = 0;
- }
+ local.last_relative_index = -1;
- /* Number of bits we can process at once
- (all part of the same byte). */
- this_time = MIN (end_offset - next_offset,
- BITS_PER_UNIT - next_bit);
- if (BYTES_BIG_ENDIAN)
- {
- /* On big-endian machine, take the most significant bits
- first (of the bits that are significant)
- and put them into bytes from the most significant end. */
- shift = end_offset - next_offset - this_time;
-
- /* Don't try to take a bunch of bits that cross
- the word boundary in the INTEGER_CST. We can
- only select bits from the LOW or HIGH part
- not from both. */
- if (shift < HOST_BITS_PER_WIDE_INT
- && shift + this_time > HOST_BITS_PER_WIDE_INT)
- {
- this_time = shift + this_time - HOST_BITS_PER_WIDE_INT;
- shift = HOST_BITS_PER_WIDE_INT;
- }
-
- /* Now get the bits from the appropriate constant word. */
- if (shift < HOST_BITS_PER_WIDE_INT)
- value = TREE_INT_CST_LOW (val);
- else
- {
- gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
- value = TREE_INT_CST_HIGH (val);
- shift -= HOST_BITS_PER_WIDE_INT;
- }
-
- /* Get the result. This works only when:
- 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
- byte |= (((value >> shift)
- & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
- << (BITS_PER_UNIT - this_time - next_bit));
- }
- else
- {
- /* On little-endian machines,
- take first the least significant bits of the value
- and pack them starting at the least significant
- bits of the bytes. */
- shift = next_offset - int_bit_position (field);
-
- /* Don't try to take a bunch of bits that cross
- the word boundary in the INTEGER_CST. We can
- only select bits from the LOW or HIGH part
- not from both. */
- if (shift < HOST_BITS_PER_WIDE_INT
- && shift + this_time > HOST_BITS_PER_WIDE_INT)
- this_time = (HOST_BITS_PER_WIDE_INT - shift);
-
- /* Now get the bits from the appropriate constant word. */
- if (shift < HOST_BITS_PER_WIDE_INT)
- value = TREE_INT_CST_LOW (val);
- else
- {
- gcc_assert (shift < 2 * HOST_BITS_PER_WIDE_INT);
- value = TREE_INT_CST_HIGH (val);
- shift -= HOST_BITS_PER_WIDE_INT;
- }
-
- /* Get the result. This works only when:
- 1 <= this_time <= HOST_BITS_PER_WIDE_INT. */
- byte |= (((value >> shift)
- & (((HOST_WIDE_INT) 2 << (this_time - 1)) - 1))
- << next_bit);
- }
+ local.min_index = NULL_TREE;
+ if (TREE_CODE (local.type) == ARRAY_TYPE
+ && TYPE_DOMAIN (local.type) != NULL_TREE)
+ local.min_index = TYPE_MIN_VALUE (TYPE_DOMAIN (local.type));
+
+ gcc_assert (HOST_BITS_PER_WIDE_INT >= BITS_PER_UNIT);
- next_offset += this_time;
- byte_buffer_in_use = 1;
- }
- }
- }
+ /* As CE goes through the elements of the constant, FIELD goes through the
+ structure fields if the constant is a structure. If the constant is a
+ union, we override this by getting the field from the TREE_LIST element.
+ But the constant could also be an array. Then FIELD is zero.
- if (byte_buffer_in_use)
+ There is always a maximum of one element in the chain LINK for unions
+ (even if the initializer in a source program incorrectly contains
+ more one). */
+
+ local.field = NULL_TREE;
+ if (TREE_CODE (local.type) == RECORD_TYPE)
+ local.field = TYPE_FIELDS (local.type);
+
+ for (cnt = 0;
+ VEC_iterate (constructor_elt, CONSTRUCTOR_ELTS (exp), cnt, ce);
+ cnt++, local.field = local.field ? TREE_CHAIN (local.field) : 0)
{
- assemble_integer (GEN_INT (byte), 1, BITS_PER_UNIT, 1);
- total_bytes++;
+ local.val = ce->value;
+ local.index = NULL_TREE;
+
+ /* The element in a union constructor specifies the proper field
+ or index. */
+ if ((TREE_CODE (local.type) == RECORD_TYPE
+ || TREE_CODE (local.type) == UNION_TYPE
+ || TREE_CODE (local.type) == QUAL_UNION_TYPE)
+ && ce->index != NULL_TREE)
+ local.field = ce->index;
+
+ else if (TREE_CODE (local.type) == ARRAY_TYPE)
+ local.index = ce->index;
+
+#ifdef ASM_COMMENT_START
+ if (local.field && flag_verbose_asm)
+ fprintf (asm_out_file, "%s %s:\n",
+ ASM_COMMENT_START,
+ DECL_NAME (local.field)
+ ? IDENTIFIER_POINTER (DECL_NAME (local.field))
+ : "<anonymous>");
+#endif
+
+ /* Eliminate the marker that makes a cast not be an lvalue. */
+ if (local.val != NULL_TREE)
+ STRIP_NOPS (local.val);
+
+ /* Output the current element, using the appropriate helper ... */
+
+ /* For an array slice not part of an outer bitfield. */
+ if (!outer
+ && local.index != NULL_TREE
+ && TREE_CODE (local.index) == RANGE_EXPR)
+ output_constructor_array_range (&local);
+
+ /* For a field that is neither a true bitfield nor part of an outer one,
+ known to be at least byte aligned and multiple-of-bytes long. */
+ else if (!outer
+ && (local.field == NULL_TREE
+ || !CONSTRUCTOR_BITFIELD_P (local.field)))
+ output_constructor_regular_field (&local);
+
+ /* For a true bitfield or part of an outer one. */
+ else
+ output_constructor_bitfield (&local, outer);
}
- if ((unsigned HOST_WIDE_INT)total_bytes < size)
- assemble_zeros (size - total_bytes);
+ /* If we are not at toplevel, save the pending data for our caller.
+ Otherwise output the pending data and padding zeros as needed. */
+ if (outer)
+ outer->byte = local.byte;
+ else
+ {
+ if (local.byte_buffer_in_use)
+ {
+ assemble_integer (GEN_INT (local.byte), 1, BITS_PER_UNIT, 1);
+ local.total_bytes++;
+ }
+
+ if ((unsigned HOST_WIDE_INT)local.total_bytes < local.size)
+ {
+ assemble_zeros (local.size - local.total_bytes);
+ local.total_bytes = local.size;
+ }
+ }
+
+ return local.total_bytes;
}
/* Mark DECL as weak. */