aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2009-05-29 00:44:55 +0000
committerIan Lance Taylor <iant@google.com>2009-05-29 00:44:55 +0000
commit7f794ff8cdee91ebc42cdd0a8bb9fae084f40102 (patch)
treee8b21472b24b249a2ca4c86c80e6075a3882c580
parentf04406d03a367f3075c1ca521c7b32392f913105 (diff)
Merge from trunk revision 147962.
git-svn-id: https://gcc.gnu.org/svn/gcc/branches/gcc-in-cxx@147966 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog1506
-rw-r--r--gcc/DATESTAMP2
-rw-r--r--gcc/Makefile.in123
-rw-r--r--gcc/ada/ChangeLog44
-rw-r--r--gcc/ada/back_end.adb28
-rw-r--r--gcc/ada/gcc-interface/Make-lang.in30
-rw-r--r--gcc/ada/gcc-interface/Makefile.in24
-rw-r--r--gcc/ada/gcc-interface/decl.c60
-rw-r--r--gcc/ada/gcc-interface/lang-specs.h1
-rw-r--r--gcc/ada/gcc-interface/misc.c8
-rw-r--r--gcc/ada/lib.ads6
-rw-r--r--gcc/ada/switch.adb34
-rw-r--r--gcc/ada/switch.ads18
-rw-r--r--gcc/alias.c3
-rw-r--r--gcc/bitmap.c17
-rw-r--r--gcc/builtins.c3
-rw-r--r--gcc/c-common.c250
-rw-r--r--gcc/c-common.h4
-rw-r--r--gcc/c-convert.c3
-rw-r--r--gcc/c-decl.c16
-rw-r--r--gcc/c-format.c2
-rw-r--r--gcc/c-opts.c2
-rw-r--r--gcc/c-parser.c80
-rw-r--r--gcc/c-typeck.c11
-rw-r--r--gcc/c.opt2
-rw-r--r--gcc/cfgexpand.c2
-rw-r--r--gcc/cgraph.c24
-rw-r--r--gcc/cgraph.h18
-rw-r--r--gcc/common.opt4
-rw-r--r--gcc/config.gcc9
-rw-r--r--gcc/config.in7
-rw-r--r--gcc/config/alpha/x-alpha2
-rw-r--r--gcc/config/arm/arm.c44
-rw-r--r--gcc/config/arm/arm.md12
-rw-r--r--gcc/config/arm/lib1funcs.asm21
-rw-r--r--gcc/config/arm/linux-eabi.h16
-rw-r--r--gcc/config/arm/neon.md44
-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.md145
-rw-r--r--gcc/config/avr/avr-protos.h2
-rw-r--r--gcc/config/avr/avr.c2
-rw-r--r--gcc/config/avr/avr.h2
-rw-r--r--gcc/config/avr/avr.md2
-rw-r--r--gcc/config/avr/libgcc.S2
-rw-r--r--gcc/config/darwin.h32
-rw-r--r--gcc/config/i386/biarch32.h29
-rw-r--r--gcc/config/i386/cpuid.h1
-rw-r--r--gcc/config/i386/cygming.opt4
-rw-r--r--gcc/config/i386/driver-i386.c43
-rw-r--r--gcc/config/i386/i386.c147
-rw-r--r--gcc/config/i386/i386.h17
-rw-r--r--gcc/config/i386/i386.md619
-rw-r--r--gcc/config/i386/i386.opt4
-rw-r--r--gcc/config/i386/linux.h6
-rw-r--r--gcc/config/i386/predicates.md27
-rw-r--r--gcc/config/i386/sol2.h8
-rw-r--r--gcc/config/i386/sse.md6
-rw-r--r--gcc/config/i386/t-cygming8
-rw-r--r--gcc/config/i386/t-cygwin8
-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/i386/x86-64.h13
-rw-r--r--gcc/config/ia64/div.md278
-rw-r--r--gcc/config/ia64/hpux.h2
-rw-r--r--gcc/config/ia64/ia64-protos.h3
-rw-r--r--gcc/config/ia64/ia64.c35
-rw-r--r--gcc/config/ia64/ia64.h2
-rw-r--r--gcc/config/ia64/ia64.md456
-rw-r--r--gcc/config/ia64/ia64.opt4
-rw-r--r--gcc/config/ia64/t-ia647
-rw-r--r--gcc/config/ia64/vect.md14
-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/m68k/constraints.md5
-rw-r--r--gcc/config/m68k/m68k-protos.h7
-rw-r--r--gcc/config/m68k/m68k.c688
-rw-r--r--gcc/config/m68k/m68k.h6
-rw-r--r--gcc/config/m68k/m68k.md51
-rw-r--r--gcc/config/m68k/m68k.opt4
-rw-r--r--gcc/config/m68k/predicates.md4
-rw-r--r--gcc/config/mips/mips.c4
-rw-r--r--gcc/config/mips/mips.h71
-rw-r--r--gcc/config/mips/mips.md173
-rw-r--r--gcc/config/mips/x-native2
-rw-r--r--gcc/config/picochip/picochip.c3
-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/s390/2064.md36
-rw-r--r--gcc/config/s390/2084.md126
-rw-r--r--gcc/config/s390/constraints.md34
-rw-r--r--gcc/config/s390/fixdfdi.h12
-rw-r--r--gcc/config/s390/libgcc-glibc.ver2
-rw-r--r--gcc/config/s390/s390-modes.def28
-rw-r--r--gcc/config/s390/s390-protos.h4
-rw-r--r--gcc/config/s390/s390.c300
-rw-r--r--gcc/config/s390/s390.h14
-rw-r--r--gcc/config/s390/s390.md22
-rw-r--r--gcc/config/s390/tpf-unwind.h26
-rw-r--r--gcc/config/score/t-score-elf6
-rw-r--r--gcc/config/sh/sh-protos.h1
-rw-r--r--gcc/config/sh/sh.c21
-rw-r--r--gcc/config/sh/sh.h14
-rw-r--r--gcc/config/sh/sh.md12
-rw-r--r--gcc/config/sh/t-sh3
-rw-r--r--gcc/config/sh/t-symbian8
-rw-r--r--gcc/config/spu/predicates.md16
-rw-r--r--gcc/config/spu/spu-protos.h7
-rw-r--r--gcc/config/spu/spu.c630
-rw-r--r--gcc/config/spu/spu.md409
-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-protos.h6
-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/configure54
-rw-r--r--gcc/configure.ac25
-rw-r--r--gcc/cp/ChangeLog254
-rw-r--r--gcc/cp/Make-lang.in10
-rw-r--r--gcc/cp/call.c840
-rw-r--r--gcc/cp/class.c19
-rw-r--r--gcc/cp/cp-tree.h67
-rw-r--r--gcc/cp/cvt.c33
-rw-r--r--gcc/cp/decl.c30
-rw-r--r--gcc/cp/decl2.c36
-rw-r--r--gcc/cp/error.c2
-rw-r--r--gcc/cp/except.c11
-rw-r--r--gcc/cp/init.c248
-rw-r--r--gcc/cp/mangle.c11
-rw-r--r--gcc/cp/method.c8
-rw-r--r--gcc/cp/name-lookup.c34
-rw-r--r--gcc/cp/name-lookup.h7
-rw-r--r--gcc/cp/parser.c179
-rw-r--r--gcc/cp/pt.c470
-rw-r--r--gcc/cp/semantics.c113
-rw-r--r--gcc/cp/tree.c130
-rw-r--r--gcc/cp/typeck.c242
-rw-r--r--gcc/cp/typeck2.c37
-rw-r--r--gcc/cse.c240
-rw-r--r--gcc/dbxout.c12
-rw-r--r--gcc/defaults.h175
-rw-r--r--gcc/doc/c-tree.texi8
-rw-r--r--gcc/doc/contrib.texi4
-rw-r--r--gcc/doc/extend.texi2
-rw-r--r--gcc/doc/gccint.texi2
-rw-r--r--gcc/doc/gimple.texi43
-rw-r--r--gcc/doc/invoke.texi135
-rw-r--r--gcc/doc/passes.texi94
-rw-r--r--gcc/doc/plugins.texi106
-rw-r--r--gcc/doc/rtl.texi8
-rw-r--r--gcc/doc/tm.texi59
-rw-r--r--gcc/doc/tree-ssa.texi35
-rw-r--r--gcc/dwarf2out.c6
-rw-r--r--gcc/except.c37
-rw-r--r--gcc/except.h4
-rw-r--r--gcc/expr.c61
-rw-r--r--gcc/final.c105
-rw-r--r--gcc/fold-const.c43
-rw-r--r--gcc/fortran/ChangeLog203
-rw-r--r--gcc/fortran/Make-lang.in12
-rw-r--r--gcc/fortran/decl.c3
-rw-r--r--gcc/fortran/expr.c2
-rw-r--r--gcc/fortran/gfortran.h7
-rw-r--r--gcc/fortran/gfortranspec.c19
-rw-r--r--gcc/fortran/interface.c26
-rw-r--r--gcc/fortran/intrinsic.c434
-rw-r--r--gcc/fortran/intrinsic.h1
-rw-r--r--gcc/fortran/intrinsic.texi266
-rw-r--r--gcc/fortran/iso-c-binding.def43
-rw-r--r--gcc/fortran/iso-fortran-env.def14
-rw-r--r--gcc/fortran/lang.opt2
-rw-r--r--gcc/fortran/match.c5
-rw-r--r--gcc/fortran/module.c8
-rw-r--r--gcc/fortran/options.c4
-rw-r--r--gcc/fortran/primary.c7
-rw-r--r--gcc/fortran/resolve.c42
-rw-r--r--gcc/fortran/simplify.c220
-rw-r--r--gcc/fortran/symbol.c1
-rw-r--r--gcc/fortran/trans-array.c7
-rw-r--r--gcc/fortran/trans-decl.c333
-rw-r--r--gcc/fortran/trans-expr.c32
-rw-r--r--gcc/fortran/trans-types.c95
-rw-r--r--gcc/gcc-plugin.h50
-rw-r--r--gcc/gcse.c20
-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-low.c1
-rw-r--r--gcc/gimple-pretty-print.c25
-rw-r--r--gcc/gimple.c31
-rw-r--r--gcc/gimple.def11
-rw-r--r--gcc/gimple.h63
-rw-r--r--gcc/gimplify.c31
-rw-r--r--gcc/gstab.h7
-rw-r--r--gcc/hooks.c7
-rw-r--r--gcc/hooks.h2
-rw-r--r--gcc/hwint.h2
-rw-r--r--gcc/ipa-cp.c13
-rw-r--r--gcc/ipa-inline.c421
-rw-r--r--gcc/ipa-prop.c96
-rw-r--r--gcc/java/ChangeLog12
-rw-r--r--gcc/java/Make-lang.in21
-rw-r--r--gcc/mips-tfile.c2
-rw-r--r--gcc/objc/ChangeLog16
-rw-r--r--gcc/objc/Make-lang.in6
-rw-r--r--gcc/objc/objc-act.c2
-rw-r--r--gcc/objcp/ChangeLog11
-rw-r--r--gcc/objcp/Make-lang.in9
-rw-r--r--gcc/omp-low.c2
-rw-r--r--gcc/output.h6
-rw-r--r--gcc/params.def16
-rw-r--r--gcc/params.h2
-rw-r--r--gcc/passes.c7
-rw-r--r--gcc/plugin.c35
-rw-r--r--gcc/predict.c4
-rw-r--r--gcc/print-tree.c2
-rw-r--r--gcc/reg-stack.c24
-rw-r--r--gcc/target-def.h10
-rw-r--r--gcc/target.h24
-rw-r--r--gcc/testsuite/ChangeLog438
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/enum3.C17
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit1.C58
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/explicit2.C29
-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/debug/dwarf2/nested-1.C29
-rw-r--r--gcc/testsuite/g++.dg/ext/dllexport2.C52
-rw-r--r--gcc/testsuite/g++.dg/ext/dllexport2a.cc21
-rw-r--r--gcc/testsuite/g++.dg/ext/packed6.C2
-rw-r--r--gcc/testsuite/g++.dg/ext/vector16.C11
-rw-r--r--gcc/testsuite/g++.dg/opt/memcpy1.C2
-rw-r--r--gcc/testsuite/g++.dg/plugin/attribute_plugin.c8
-rw-r--r--gcc/testsuite/g++.dg/plugin/dumb_plugin.c10
-rw-r--r--gcc/testsuite/g++.dg/plugin/selfassign.c9
-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/dtor6.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/Wstrict-aliasing-float-ref-int-obj.C4
-rw-r--r--gcc/testsuite/g++.dg/warn/translate-ice-1.C45
-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/20090518-1.c6
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20090519-1.c11
-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/pr40204.c14
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40233.c10
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr40252.c6
-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/Wstrict-aliasing-converted-assigned.c4
-rw-r--r--gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c6
-rw-r--r--gcc/testsuite/gcc.dg/compat/struct-layout-1_generate.c2
-rw-r--r--gcc/testsuite/gcc.dg/dll-6.c52
-rw-r--r--gcc/testsuite/gcc.dg/dll-6a.c21
-rw-r--r--gcc/testsuite/gcc.dg/dll-7.c52
-rw-r--r--gcc/testsuite/gcc.dg/dll-7a.c21
-rw-r--r--gcc/testsuite/gcc.dg/falign-labels-1.c39
-rw-r--r--gcc/testsuite/gcc.dg/ipa/modif-1.c5
-rw-r--r--gcc/testsuite/gcc.dg/plugin/ggcplug-test-1.c12
-rw-r--r--gcc/testsuite/gcc.dg/plugin/ggcplug.c109
-rw-r--r--gcc/testsuite/gcc.dg/plugin/plugin.exp4
-rw-r--r--gcc/testsuite/gcc.dg/plugin/selfassign.c9
-rw-r--r--gcc/testsuite/gcc.dg/pr33667.c2
-rw-r--r--gcc/testsuite/gcc.dg/pr40172-1.c31
-rw-r--r--gcc/testsuite/gcc.dg/pr40172-2.c16
-rw-r--r--gcc/testsuite/gcc.dg/pr40172-3.c17
-rw-r--r--gcc/testsuite/gcc.dg/prefetch-loop-arrays-1.c2
-rw-r--r--gcc/testsuite/gcc.dg/simd-1b.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/pr40087.c30
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/sra-2.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-14.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-15.c2
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-24.c34
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-25.c18
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-26.c18
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-1.c62
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-10.c53
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-11.c52
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-13.c49
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-14.c50
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-15.c54
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-16.c71
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-17.c60
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-18.c49
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-19.c56
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-2.c59
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-20.c68
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-21.c68
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-22.c67
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-3.c45
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-4.c45
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-5.c53
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-6.c51
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-7.c52
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-8.c50
-rw-r--r--gcc/testsuite/gcc.dg/vect/bb-slp-9.c53
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-tree-reassoc-bb-slp-12.c53
-rw-r--r--gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c40
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr40238.c35
-rw-r--r--gcc/testsuite/gcc.dg/vect/pr40254.c39
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-40.c7
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-42.c25
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-46.c7
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect-76.c2
-rw-r--r--gcc/testsuite/gcc.dg/vect/vect.exp11
-rw-r--r--gcc/testsuite/gcc.dg/vector-4.c11
-rw-r--r--gcc/testsuite/gcc.target/arm/neon-vmla-1.c10
-rw-r--r--gcc/testsuite/gcc.target/arm/neon-vmls-1.c10
-rw-r--r--gcc/testsuite/gcc.target/arm/thumb2-mul-space-2.c15
-rw-r--r--gcc/testsuite/gcc.target/arm/thumb2-mul-space-3.c17
-rw-r--r--gcc/testsuite/gcc.target/arm/thumb2-mul-space.c10
-rw-r--r--gcc/testsuite/gcc.target/arm/thumb2-mul-speed.c27
-rw-r--r--gcc/testsuite/gcc.target/i386/movbe-1.c18
-rw-r--r--gcc/testsuite/gcc.target/i386/movbe-2.c19
-rw-r--r--gcc/testsuite/gcc.target/i386/pr37216.c17
-rw-r--r--gcc/testsuite/gcc.target/ia64/mfused-madd-vect.c33
-rw-r--r--gcc/testsuite/gcc.target/ia64/mfused-madd.c64
-rw-r--r--gcc/testsuite/gcc.target/ia64/mno-fused-madd-vect.c31
-rw-r--r--gcc/testsuite/gcc.target/ia64/mno-fused-madd.c64
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-gd-xgot.c13
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-gd.c13
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-ie-xgot.c13
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-ie.c13
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-ld-xgot-xtls.c14
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-ld-xgot.c14
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-ld-xtls.c14
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-ld.c14
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-le-xtls.c13
-rw-r--r--gcc/testsuite/gcc.target/m68k/tls-le.c13
-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/mips/extend-1.c14
-rw-r--r--gcc/testsuite/gcc.target/mips/octeon-exts-2.c5
-rw-r--r--gcc/testsuite/gcc.target/mips/octeon-exts-5.c5
-rw-r--r--gcc/testsuite/gcc.target/mips/octeon-exts-6.c14
-rw-r--r--gcc/testsuite/gcc.target/x86_64/abi/asm-support.S2
-rw-r--r--gcc/testsuite/gfortran.dg/array_memset_2.f906
-rw-r--r--gcc/testsuite/gfortran.dg/bound_4.f906
-rw-r--r--gcc/testsuite/gfortran.dg/bounds_check_14.f906
-rw-r--r--gcc/testsuite/gfortran.dg/bounds_check_fail_3.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/bounds_check_fail_4.f9012
-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/c_kind_int128_test1.f0310
-rw-r--r--gcc/testsuite/gfortran.dg/c_kind_int128_test2.f032
-rw-r--r--gcc/testsuite/gfortran.dg/c_kind_params.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/c_kinds.c17
-rw-r--r--gcc/testsuite/gfortran.dg/default_format_1.f905
-rw-r--r--gcc/testsuite/gfortran.dg/default_format_denormal_1.f902
-rw-r--r--gcc/testsuite/gfortran.dg/elemental_dependency_1.f906
-rw-r--r--gcc/testsuite/gfortran.dg/erf_2.F9052
-rw-r--r--gcc/testsuite/gfortran.dg/erfc_scaled_2.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/interface_27.f9041
-rw-r--r--gcc/testsuite/gfortran.dg/interface_28.f9039
-rw-r--r--gcc/testsuite/gfortran.dg/nullify_4.f908
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_11.f901
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_18.f9025
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_19.f9035
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_comp_10.f9031
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_comp_8.f9058
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_comp_9.f9037
-rw-r--r--gcc/testsuite/gfortran.dg/proc_ptr_result_1.f909
-rw-r--r--gcc/testsuite/gfortran.dg/string_1.f9014
-rw-r--r--gcc/testsuite/gfortran.dg/string_2.f9012
-rw-r--r--gcc/testsuite/gfortran.dg/string_3.f9019
-rw-r--r--gcc/testsuite/gfortran.dg/vector_subscript_4.f902
-rw-r--r--gcc/testsuite/gnat.dg/addr6.adb31
-rw-r--r--gcc/testsuite/gnat.dg/loop_optimization6.adb25
-rw-r--r--gcc/testsuite/gnat.dg/loop_optimization6.ads4
-rw-r--r--gcc/testsuite/gnat.dg/misaligned_nest.adb26
-rw-r--r--gcc/testsuite/gnat.dg/specs/rep_clause3.ads36
-rw-r--r--gcc/testsuite/lib/target-supports.exp23
-rw-r--r--gcc/timevar.def1
-rw-r--r--gcc/toplev.h3
-rw-r--r--gcc/tree-cfg.c24
-rw-r--r--gcc/tree-complex.c1
-rw-r--r--gcc/tree-data-ref.c158
-rw-r--r--gcc/tree-data-ref.h3
-rw-r--r--gcc/tree-dfa.c6
-rw-r--r--gcc/tree-flow-inline.h15
-rw-r--r--gcc/tree-flow.h9
-rw-r--r--gcc/tree-inline.c27
-rw-r--r--gcc/tree-mudflap.c20
-rw-r--r--gcc/tree-parloops.c10
-rw-r--r--gcc/tree-pass.h2
-rw-r--r--gcc/tree-pretty-print.c210
-rw-r--r--gcc/tree-scalar-evolution.c97
-rw-r--r--gcc/tree-sra.c48
-rw-r--r--gcc/tree-ssa-alias.c295
-rw-r--r--gcc/tree-ssa-alias.h41
-rw-r--r--gcc/tree-ssa-ccp.c54
-rw-r--r--gcc/tree-ssa-copy.c73
-rw-r--r--gcc/tree-ssa-copyrename.c14
-rw-r--r--gcc/tree-ssa-dce.c4
-rw-r--r--gcc/tree-ssa-dom.c43
-rw-r--r--gcc/tree-ssa-forwprop.c46
-rw-r--r--gcc/tree-ssa-live.c30
-rw-r--r--gcc/tree-ssa-loop-im.c4
-rw-r--r--gcc/tree-ssa-loop-ivopts.c6
-rw-r--r--gcc/tree-ssa-loop-niter.c109
-rw-r--r--gcc/tree-ssa-operands.c71
-rw-r--r--gcc/tree-ssa-operands.h4
-rw-r--r--gcc/tree-ssa-pre.c97
-rw-r--r--gcc/tree-ssa-propagate.c10
-rw-r--r--gcc/tree-ssa-sccvn.c422
-rw-r--r--gcc/tree-ssa-sccvn.h9
-rw-r--r--gcc/tree-ssa-structalias.c383
-rw-r--r--gcc/tree-vect-data-refs.c313
-rw-r--r--gcc/tree-vect-loop.c42
-rw-r--r--gcc/tree-vect-patterns.c7
-rw-r--r--gcc/tree-vect-slp.c514
-rw-r--r--gcc/tree-vect-stmts.c286
-rw-r--r--gcc/tree-vectorizer.c101
-rw-r--r--gcc/tree-vectorizer.h63
-rw-r--r--gcc/tree.c97
-rw-r--r--gcc/tree.def9
-rw-r--r--gcc/tree.h25
-rw-r--r--gcc/unwind-dw2-fde.c20
-rw-r--r--gcc/unwind-dw2.c27
480 files changed, 16827 insertions, 5807 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c4177e61f5f..afd6cc87347 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,1408 @@
+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.
+ * 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.
+ * 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.
+ * cgraph.h (struct inline_summary): New filed self_wize,
+ size_inlining_benefit, self_time and time_inlining_benefit.
+ (struct cgraph_global_info): Replace insns by time ans size fields.
+ * ipa-cp (ipcp_cloning_candidate_p): Base estimate on size
+ (ipcp_estimate_growth, ipcp_insert_stage): Likewise.
+ (ipcp_update_callgraph): Do not touch function bodies.
+ * ipa-inline.c: Include except.h
+ (MAX_TIME): New constant.
+ (overall_insns): Remove.
+ (leaf_node_p): New.
+ (overall_size, max_benefit): New static variables.
+ (cgraph_estimate_time_after_inlining): New function.
+ (cgraph_estimate_size_after_inlining): Rewrite using benefits.
+ (cgraph_clone_inlined_nodes): Update size.
+ (cgraph_mark_inline_edge): Update size.
+ (cgraph_estimate_growth): Use size info.
+ (cgraph_check_inline_limits): Check size.
+ (cgraph_default_inline_p): Likewise.
+ (cgraph_edge_badness): Compute badness based on benefit and size cost.
+ (cgraph_decide_recursive_inlining): Check size.
+ (cgraph_decide_inlining_of_small_function): Update size; dump sizes and
+ times.
+ (cgraph_decide_inlining): Likewise.
+ (cgraph_decide_inlining_incrementally): Likewise; honor
+ PARAM_EARLY_INLINING_INSNS.
+ (likely_eliminated_by_inlining_p): New predicate.
+ (estimate_function_body_sizes): New function.
+ (compute_inline_parameters): Use it.
+ * except.c (must_not_throw_labels): New function.
+ * except.h (must_not_throw_labels): Declare.
+ * tree-inline.c (init_inline_once): Kill inlining_weigths
+ * tree-ssa-structalias.c: Avoid uninitialized warning.
+ * params.def (PARAM_MAX_INLINE_INSNS_SINGLE): Reduce to 300.
+ (PARAM_MAX_INLINE_INSNS_AUTO): Reduce to 60.
+ (PARAM_INLINE_CALL_COST): Remove.
+ (PARAM_EARLY_INLINING_INSNS): New.
+
+2009-05-25 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/36327
+ * tree-ssa-alias.c (walk_non_aliased_vuses): Add second walker
+ callback for reference translation or lookup at the point
+ of may-defs.
+ * tree-ssa-alias.h (walk_non_aliased_vuses): Adjust prototype.
+ * tree-ssa-sccvn.c (get_ref_from_reference_ops): Bail out
+ for union COMPONENT_REFs.
+ (vn_reference_lookup_3): New callback. Lookup from memset
+ and CONSTRUCTOR assignment, translate through struct copies.
+ (vn_reference_lookup_pieces): Make sure to not free the
+ passed operands array. Adjust walk_non_aliased_vuses call.
+ (vn_reference_lookup): Adjust walk_non_aliased_vuses call,
+ make sure we do not leak memory.
+
+2009-05-25 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-alias.h (dump_points_to_solution): Declare.
+ * tree-inline.c (expand_call_inline): Reset the escaped and
+ callused solutions.
+ * tree-ssa-structalias.c (pass_build_ealias): New.
+ * tree-pass.h (pass_build_ealias): Declare.
+ * passes.c (init_optimization_passes): Add PTA during
+ early optimizations.
+ * tree-ssa-alias.c (dump_alias_info): Dump the ESCAPED
+ and CALLUSED solutions.
+ (dump_points_to_solution): New function, split out from ...
+ (dump_points_to_info_for): ... here.
+ * tree-parloops.c (parallelize_loops): Reset the escaped and
+ callused solutions.
+
+2009-05-25 Rainer Orth <ro@TechFak.Uni-Bielefeld.DE>
+
+ PR bootstrap/40027
+ * config/i386/i386.c (USE_HIDDEN_LINKONCE): Only define if missing.
+ * config/i386/sol2.h [!TARGET_GNU_LD] (USE_HIDDEN_LINKONCE): Define.
+
+2009-05-25 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/40238
+ * tree-vect-stmts.c (vect_init_vector): Insert initialization
+ statements after basic block's labels.
+ * tree-vect-slp.c (vect_slp_transform_bb): Call destroy_bb_vec_info()
+ to free the allocated memory.
+
+2009-05-24 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * gcc/config/sh/sh.c (sh_set_return_address): Mark store of
+ return address with a USE.
+
+2009-05-24 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/40233
+ * tree.c (make_vector_type): Build the TYPE_DEBUG_REPRESENTATION_TYPEs
+ array type from the main variant of the inner type.
+
+2009-05-24 Jan-Benedict Glaw <jbglaw@lug-owl.de>
+
+ * config/vax/vax-protos.h (legitimate_constant_address_p): Change
+ definition to bool (from int) to un-break build.
+ (legitimate_constant_p, vax_mode_dependent_address_p): Likewise.
+
+2009-05-24 Paolo Bonzini <bonzini@gnu.org>
+
+ * tree-ssa-operands.h (push_stmt_changes, pop_stmt_changes,
+ discard_stmt_changes): Delete.
+ * tree-ssa-operands.c (scb_stack): Delete.
+ (init_ssa_operands): Do not initialize it.
+ (fini_ssa_operands): Do not free it.
+ (push_stmt_changes, pop_stmt_changes, discard_stmt_changes): Delete.
+
+ * tree-cfg.c (replace_uses_by): Replace pop_stmt_changes with
+ update_stmt, remove the others. Fix comments.
+ * tree-dfa.c (optimize_stack_restore): Likewise.
+ * tree-ssa-forwprop.c (forward_propagate_addr_expr): Likewise.
+ * tree-ssa-loop-ivopts.c (rewrite_use): Likewise.
+ * tree-ssa-dce.c (eliminate_unnecessary_stmts): Likewise.
+ * tree-ssa-ccp.c (optimize_stack_restore, execute_fold_all_builtins):
+ Likewise.
+ * tree-ssa-propagate.c (substitute_and_fold): Likewise.
+ * tree-ssa-dom.c (propagate_rhs_into_lhs): Likewise.
+ (dom_opt_finalize_block): Likewise, adjusting access to stmts_to_rescan.
+ (optimize_stmt): Likewise, adjusting access to stmts_to_rescan.
+ (stmts_to_rescan): Change item type to gimple.
+ (tree_ssa_dominator_optimize): Change type of stmts_to_rescan.
+
+2009-05-24 Ira Rosen <irar@il.ibm.com>
+
+ * doc/passes.texi (Tree-SSA passes): Document SLP pass.
+ * tree-pass.h (pass_slp_vectorize): New pass.
+ * params.h (SLP_MAX_INSNS_IN_BB): Define.
+ * timevar.def (TV_TREE_SLP_VECTORIZATION): Define.
+ * tree-vectorizer.c (timevar.h): Include.
+ (user_vect_verbosity_level): Declare.
+ (vect_location): Fix comment.
+ (vect_set_verbosity_level): Update user_vect_verbosity_level
+ instead of vect_verbosity_level.
+ (vect_set_dump_settings): Add an argument. Ignore user defined
+ verbosity if dump flags require higher level of verbosity. Print to
+ stderr only for loop vectorization.
+ (vectorize_loops): Update call to vect_set_dump_settings.
+ (execute_vect_slp): New function.
+ (gate_vect_slp): Likewise.
+ (struct gimple_opt_pass pass_slp_vectorize): New.
+ * tree-vectorizer.h (struct _bb_vec_info): Define along macros to
+ access its members.
+ (vec_info_for_bb): New function.
+ (struct _stmt_vec_info): Add bb_vinfo and a macro for its access.
+ (VECTORIZATION_ENABLED): New macro.
+ (SLP_ENABLED, SLP_DISABLED): Likewise.
+ (vect_is_simple_use): Add bb_vec_info argument.
+ (new_stmt_vec_info, vect_analyze_data_ref_dependences,
+ vect_analyze_data_refs_alignment, vect_verify_datarefs_alignment,
+ vect_analyze_data_ref_accesses, vect_analyze_data_refs,
+ vect_schedule_slp, vect_analyze_slp): Likewise.
+ (vect_analyze_stmt): Add slp_tree argument.
+ (find_bb_location): Declare.
+ (vect_slp_analyze_bb, vect_slp_transform_bb): Likewise.
+ * tree-vect-loop.c (new_loop_vec_info): Adjust function calls.
+ (vect_analyze_loop_operations, vect_analyze_loop,
+ get_initial_def_for_induction, vect_create_epilog_for_reduction,
+ vect_finalize_reduction, vectorizable_reduction,
+ vectorizable_live_operation, vect_transform_loop): Likewise.
+ * tree-data-ref.c (dr_analyze_innermost): Update comment,
+ skip evolution analysis if analyzing a basic block.
+ (dr_analyze_indices): Likewise.
+ (initialize_data_dependence_relation): Skip the test whether the
+ object is invariant for basic blocks.
+ (compute_all_dependences): Skip dependence analysis for data
+ references in basic blocks.
+ (find_data_references_in_stmt): Don't fail in case of invariant
+ access in basic block.
+ (find_data_references_in_bb): New function.
+ (find_data_references_in_loop): Move code to
+ find_data_references_in_bb and add a call to it.
+ (compute_data_dependences_for_bb): New function.
+ * tree-data-ref.h (compute_data_dependences_for_bb): Declare.
+ * tree-vect-data-refs.c (vect_check_interleaving): Adjust to the case
+ that STEP is 0.
+ (vect_analyze_data_ref_dependence): Check for interleaving in case of
+ unknown dependence in basic block and fail in case of dependence in
+ basic block.
+ (vect_analyze_data_ref_dependences): Add bb_vinfo argument, get data
+ dependence instances from either loop or basic block vectorization
+ info.
+ (vect_compute_data_ref_alignment): Check if it is loop vectorization
+ before calling nested_in_vect_loop_p.
+ (vect_compute_data_refs_alignment): Add bb_vinfo argument, get data
+ dependence instances from either loop or basic block vectorization
+ info.
+ (vect_verify_datarefs_alignment): Likewise.
+ (vect_enhance_data_refs_alignment): Adjust function calls.
+ (vect_analyze_data_refs_alignment): Likewise.
+ (vect_analyze_group_access): Fix printing. Skip different checks if
+ DR_STEP is 0. Keep strided stores either in loop or basic block
+ vectorization data structure. Fix indentation.
+ (vect_analyze_data_ref_access): Fix comments, allow zero step in
+ basic blocks.
+ (vect_analyze_data_ref_accesses): Add bb_vinfo argument, get data
+ dependence instances from either loop or basic block vectorization
+ info.
+ (vect_analyze_data_refs): Update comment. Call
+ compute_data_dependences_for_bb to analyze basic blocks.
+ (vect_create_addr_base_for_vector_ref): Check for outer loop only in
+ case of loop vectorization. In case of basic block vectorization use
+ data-ref itself as a base.
+ (vect_create_data_ref_ptr): In case of basic block vectorization:
+ don't advance the pointer, add new statements before the current
+ statement. Adjust function calls.
+ (vect_supportable_dr_alignment): Support only aligned accesses in
+ basic block vectorization.
+ * common.opt (ftree-slp-vectorize): New flag.
+ * tree-vect-patterns.c (widened_name_p): Adjust function calls.
+ (vect_pattern_recog_1): Likewise.
+ * tree-vect-stmts.c (process_use): Likewise.
+ (vect_init_vector): Add new statements in the beginning of the basic
+ block in case of basic block SLP.
+ (vect_get_vec_def_for_operand): Adjust function calls.
+ (vect_finish_stmt_generation): Likewise.
+ (vectorizable_call): Add assert that it is loop vectorization, adjust
+ function calls.
+ (vectorizable_conversion, vectorizable_assignment): Likewise.
+ (vectorizable_operation): In case of basic block SLP, take
+ vectorization factor from statement's type and skip the relevance
+ check. Adjust function calls.
+ (vectorizable_type_demotion): Add assert that it is loop
+ vectorization, adjust function calls.
+ (vectorizable_type_promotion): Likewise.
+ (vectorizable_store): Check for outer loop only in case of loop
+ vectorization. Adjust function calls. For basic blocks, skip the
+ relevance check and don't advance pointers.
+ (vectorizable_load): Likewise.
+ (vectorizable_condition): Add assert that it is loop vectorization,
+ adjust function calls.
+ (vect_analyze_stmt): Add argument. In case of basic block SLP, check
+ that it is not reduction, get vector type, call only supported
+ functions, skip loop specific parts.
+ (vect_transform_stmt): Check for outer loop only in case of loop
+ vectorization.
+ (new_stmt_vec_info): Add new argument and initialize bb_vinfo.
+ (vect_is_simple_use): Fix comment, add new argument, fix conditions
+ for external definition.
+ * passes.c (pass_slp_vectorize): New pass.
+ * tree-vect-slp.c (find_bb_location): New function.
+ (vect_get_and_check_slp_defs): Add argument, adjust function calls,
+ check for patterns only in loops.
+ (vect_build_slp_tree): Add argument, adjust function calls, fail in
+ case of multiple types in basic block SLP.
+ (vect_mark_slp_stmts_relevant): New function.
+ (vect_supported_load_permutation_p): Fix comment.
+ (vect_analyze_slp_instance): Add argument. In case of basic block
+ SLP, take vectorization factor from statement's type, check that
+ unrolling factor is 1. Adjust function call. Save SLP instance in
+ either loop or basic block vectorization structure. Return FALSE,
+ if SLP failed.
+ (vect_analyze_slp): Add argument. Get strided stores groups from
+ either loop or basic block vectorization structure. Return FALSE
+ if basic block SLP failed.
+ (new_bb_vec_info): New function.
+ (destroy_bb_vec_info, vect_slp_analyze_node_operations,
+ vect_slp_analyze_operations, vect_slp_analyze_bb): Likewise.
+ (vect_schedule_slp): Add argument. Get SLP instances from either
+ loop or basic block vectorization structure. Set vectorization factor
+ to be 1 for basic block SLP.
+ (vect_slp_transform_bb): New function.
+ * params.def (PARAM_SLP_MAX_INSNS_IN_BB): Define.
+
+2009-05-23 Mark Mitchell <mark@codesourcery.com>
+
+ * final.c (shorten_branches): Do not align labels for jump tables.
+ (final_scan_insn): Use JUMP_TABLE_DATA_P.
+
+2009-05-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * doc/passes.texi: Standardize spelling of RTL, Tree and Tree SSA.
+ Remove outdated reference to flow.c and fix nits.
+ * doc/gccint.texi: Tweak RTL description.
+ * doc/rtl.texi: Likewise.
+
+2009-05-23 Denis Chertykov <chertykov@gmail.com>
+
+ * config/avr/avr.c: Change my email address.
+ * config/avr/avr.h: Likewise.
+ * config/avr/avr.md: Likewise.
+ * config/avr/avr-protos.h: Likewise.
+ * config/avr/libgcc.S: Likewise.
+
+2009-05-22 Trevor Smigiel <Trevor_Smigiel@playstation.sony.com>
+
+ * config/spu/spu-protos.h (aligned_mem_p, spu_valid_mov): Remove.
+ (spu_split_load, spu_split_store): Change return type to int.
+ (spu_split_convert): Declare.
+ * config/spu/predicates.md (spu_mem_operand): Remove.
+ (spu_mov_operand): Update.
+ (spu_dest_operand, shiftrt_operator, extend_operator): Define.
+ * config/spu/spu.c (regno_aligned_for_load): Remove.
+ (reg_aligned_for_addr, spu_expand_load): Define.
+ (spu_expand_extv): Reimplement and handle MEM.
+ (spu_expand_insv): Handle MEM.
+ (spu_sched_reorder): Handle insn's with length 0.
+ (spu_legitimate_address_p): Reimplement.
+ (store_with_one_insn_p): Return TRUE for any mode with size
+ larger than 16 bytes.
+ (address_needs_split): Define.
+ (spu_expand_mov): Call spu_split_load and spu_split_store for MEM
+ operands.
+ (spu_convert_move): Define.
+ (spu_split_load): Use spu_expand_load and change all MEM's to TImode.
+ (spu_split_store): Change all MEM's to TImode.
+ (spu_init_expanders): Preallocate registers that correspond to
+ LAST_VIRTUAL_REG+1 and LAST_VIRTUAL_REG+2 and set them with
+ mark_reg_pointer.
+ (spu_split_convert): Define.
+ * config/spu/spu.md (QHSI, QHSDI): New mode iterators.
+ (_move<mode>, _movdi, _movti): Update predicate and condition.
+ (load, store): Change to define_split.
+ (extendqiti2, extendhiti2, extendsiti2, extendditi2): Simplify to
+ extend<mode>ti2.
+ (zero_extendqiti2, zero_extendhiti2, <v>lshr<mode>3_imm): Define.
+ (lshr<mode>3, lshr<mode>3_imm, lshr<mode>3_re): Simplify to one
+ define_insn_and_split of lshr<mode>3.
+ (shrqbybi_<mode>, shrqby_<mode>): Simplify to define_expand.
+ (<v>ashr<mode>3_imm): Define.
+ (extv, extzv, insv): Allow MEM operands.
+ (trunc_shr_ti<mode>, trunc_shr_tidi, shl_ext_<mode>ti,
+ shl_ext_diti, sext_trunc_lshr_tiqisi, zext_trunc_lshr_tiqisi,
+ sext_trunc_lshr_tihisi, zext_trunc_lshr_tihisi): Define for combine.
+ (_spu_convert2): Change to define_insn_and_split and remove the
+ corresponding define_peephole2.
+ (stack_protect_set, stack_protect_test, stack_protect_test_si):
+ Change predicates to memory_operand.
+
+2009-05-22 Mark Mitchell <mark@codesourcery.com>
+
+ * config/arm/thumb2.md: Add 16-bit multiply instructions.
+
+2009-05-21 Michael Meissner <meissner@linux.vnet.ibm.com>
+
+ PR tree-optimization/40219
+ * tree.c (iterative_hash_expr): Make sure the builtin function is
+ a normal builtin function and not a front end or back end builtin
+ before indexing into the built_in_decls array.
+
+2009-05-22 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/38964
+ * alias.c (write_dependence_p): Do not use TBAA for answering
+ anti-dependence or output-dependence.
+ * tree-ssa-structalias.c (set_uids_in_ptset): Remove TBAA pruning code.
+ (emit_pointer_definition): Remove.
+ (emit_alias_warning): Likewise.
+ (find_what_var_points_to): Remove TBAA pruning code.
+ (find_what_p_points_to): Likewise. Do not warn about strict-aliasing
+ violations.
+ (compute_points_to_sets): Remove code computing the set of
+ dereferenced pointers.
+ * tree-data-ref.c (dr_may_alias_p): Properly use the split
+ oracle for querying anti and output dependencies.
+ * tree-ssa-alias.c (refs_may_alias_p_1): Add argument specifying
+ if TBAA may be applied.
+ (refs_anti_dependent_p): New function.
+ (refs_output_dependent_p): Likewise.
+ * tree-ssa-alias.h (refs_anti_dependent_p): Declare.
+ (refs_output_dependent_p): Likewise.
+ * doc/tree-ssa.texi (Memory model): New section.
+ * doc/c-tree.texi (CHANGE_DYNAMIC_TYPE_EXPR): Remove.
+ * doc/gimple.texi (GIMPLE_CHANGE_DYNAMIC_TYPE): Remove.
+ * cfgexpand.c (expand_gimple_basic_block): Do not handle
+ GIMPLE_CHANGE_DYNAMIC_TYPE or CHANGE_DYNAMIC_TYPE_EXPR.
+ * expr.c (expand_expr_real_1): Likewise.
+ * gimple-low.c (lower_stmt): Likewise.
+ * gimple-pretty-print.c (dump_gimple_stmt): Likewise.
+ (dump_gimple_cdt): Remove.
+ * gimple.c (gss_for_code): Do not handle GIMPLE_CHANGE_DYNAMIC_TYPE.
+ (gimple_size): Likewise.
+ (walk_gimple_op): Likewise.
+ (is_gimple_stmt): Likewise.
+ (walk_stmt_load_store_addr_ops): Likewise.
+ (gimple_build_cdt): Remove.
+ * gimple.def (GIMPLE_CHANGE_DYNAMIC_TYPE): Remove.
+ * gimple.h (gimple_cdt_new_type): Remove.
+ (gimple_cdt_new_type_ptr): Likewise.
+ (gimple_cdt_set_new_type): Likewise.
+ (gimple_cdt_location): Likewise.
+ (gimple_cdt_location_ptr): Likewise.
+ (gimple_cdt_set_location): Likewise.
+ * gimplify.c (gimplify_expr): Do not handle CHANGE_DYNAMIC_TYPE_EXPR.
+ * tree-cfg.c (remove_useless_stmts_1): Do not handle
+ GIMPLE_CHANGE_DYNAMIC_TYPE.
+ (verify_types_in_gimple_stmt): Likewise.
+ * tree-inline.c (estimate_num_insns): Likewise.
+ (expand_call_inline): Do not copy DECL_NO_TBAA_P.
+ (copy_decl_to_var): Likewise.
+ (copy_result_decl_to_var): Likewise.
+ * tree-pretty-print.c (dump_generic_node): Do not handle
+ CHANGE_DYNAMIC_TYPE_EXPR.
+ * tree-ssa-dce.c (mark_stmt_if_obviously_necessary): Likewise.
+ * tree-ssa-operands.c (get_expr_operands): Likewise.
+ * tree-ssa-structalias.c (struct variable_info): Remove
+ no_tbaa_pruning member.
+ (new_var_info): Do not set it based on DECL_NO_TBAA_P.
+ (unify_nodes): Do not copy it.
+ (find_func_aliases): Do not handle GIMPLE_CHANGE_DYNAMIC_TYPE.
+ (dump_solution_for_var): Do not dump no_tbaa_pruning state.
+ (set_uids_in_ptset): Do not check it.
+ (find_what_var_points_to): Likewise.
+ (compute_tbaa_pruning): Remove.
+ (compute_points_to_sets): Do not call it.
+ * tree.c (walk_tree_1): Do not handle CHANGE_DYNAMIC_TYPE_EXPR.
+ * tree.def (CHANGE_DYNAMIC_TYPE_EXPR): Remove.
+ * tree.h (CHANGE_DYNAMIC_TYPE_NEW_TYPE): Remove.
+ (CHANGE_DYNAMIC_TYPE_LOCATION): Likewise.
+ (DECL_NO_TBAA_P): Likewise.
+ (struct tree_decl_common): Move no_tbaa_flag to unused flags section.
+ * omp-low.c (copy_var_decl): Do not copy DECL_NO_TBAA_P.
+ (expand_omp_atomic_pipeline): Do not set it.
+ * print-tree.c (print_node): Do not dump it.
+ * tree-ssa-copyrename.c (copy_rename_partition_coalesce): Remove
+ redundant check.
+
+2009-05-22 Vladimir Makarov <vmakarov@redhat.com>
+
+ PR target/39856
+ * reg-stack.c (subst_stack_regs_pat): Remove gcc_assert for note
+ for clobber.
+
+2009-05-22 Mark Mitchell <mark@codesourcery.com>
+
+ * tree.c (handle_dll_attribute): Mark dllexport'd inlines as
+ non-external.
+
+2009-05-22 Ben Elliston <bje@au.ibm.com>
+
+ * Makefile.in (bversion.h, s-bversion): New targets.
+ (TOPLEV_H): Add bversion.h.
+ * toplev.h: Include "bversion.h".
+ (ATTRIBUTE_GCC_DIAG): When building with checking disabled, use
+ the __format__ attribute only if compiling with the same version
+ of GCC as the sources (the "build version").
+
+2009-05-22 Ben Elliston <bje@au.ibm.com>
+
+ * c-format.c (handle_format_attribute): Fix comment typo.
+
+2009-05-21 Steve Ellcey <sje@cup.hp.com>
+
+ PR target/37846
+ * config/ia64/ia64.opt (mfused-madd): New.
+ * config/ia64/ia64.h (TARGET_DEFAULT): Set MASK_FUSED_MADD.
+ * config/ia64/hpux.h (TARGET_DEFAULT): Ditto.
+ * config/ia64/ia64.md (maddsf4, msubsf4, nmaddsf4,
+ madddf4, madddf4_trunc, msubdf4, msubdf4_trunc, nmadddf4,
+ nmadddf4_truncsf, maddxf4, maddxf4_truncsf, maddxf4_truncdf,
+ msubxf4, msubxf4_truncsf msubxf4_truncdf, nmaddxf4,
+ nmaddxf4_truncsf, nmaddxf4_truncdf): Check TARGET_FUSED_MADD.
+ * config/ia64/vect.md (addv2sf3, subv2sf3): Force fpma/fpms
+ instruction if !TARGET_FUSED_MADD.
+ (fpma, fpms): Remove colon from name.
+
+2009-05-22 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-sccvn.c (copy_reference_ops_from_ref): Record
+ TMR_ORIGINAL. Always either record TMR_SYMBOL or TMR_BASE.
+ * tree-ssa-pre.c (create_component_ref_by_pieces_1): Handle
+ TARGET_MEM_REF.
+ (create_expression_by_pieces): Only convert if necessary.
+ * gimplify.c (gimplify_expr): Handle TARGET_MEM_REF.
+ * tree-ssa-loop-im.c (gen_lsm_tmp_name): Handle INTEGER_CST.
+
+2009-05-21 Adam Nemet <anemet@caviumnetworks.com>
+
+ * config/mips/mips.md (*extzv_trunc<mode>_exts): Turn into a
+ regular pattern from a template and rename it ...
+ (*extzv_truncsi_exts): ... to this.
+
+2009-05-21 Richard Guenther <rguenther@suse.de>
+
+ * cgraph.h (struct cgraph_node): Remove inline_decl member.
+ * ipa-inline.c (cgraph_mark_inline_edge): Do not check it.
+ (cgraph_default_inline_p): Likewise.
+ (cgraph_decide_inlining_incrementally): Likewise.
+
+2009-05-21 H.J. Lu <hongjiu.lu@intel.com>
+ Uros Bizjak <ubizjak@gmail.com>
+
+ * config/i386/cpuid.h (bit_MOVBE): New.
+
+ * config/i386/driver-i386.c (host_detect_local_cpu): Check movbe.
+
+ * config/i386/i386.c (OPTION_MASK_ISA_MOVBE_SET): New.
+ (OPTION_MASK_ISA_MOVBE_UNSET): Likewise.
+ (ix86_handle_option): Handle OPT_mmovbe.
+ (ix86_target_string): Add -mmovbe.
+ (pta_flags): Add PTA_MOVBE.
+ (processor_alias_table): Add PTA_MOVBE to "atom".
+ (override_options): Handle PTA_MOVBE.
+
+ * config/i386/i386.h (TARGET_MOVBE): New.
+
+ * config/i386/i386.md (bswapsi2): Check TARGET_MOVBE.
+ (*bswapsi_movbe): New.
+ (*bswapdi_movbe): Likewise.
+ (bswapdi2): Renamed to ...
+ (*bswapdi_1): This.
+ (bswapdi2): New expander.
+
+ * config/i386/i386.opt (mmovbe): New.
+
+ * doc/invoke.texi: Document -mmovbe.
+
+2009-05-21 Taras Glek <tglek@mozilla.com>
+
+ * plugin.c (try_init_one_plugin): Updated to new plugin_init API.
+ * gcc-plugin.h (plugin_init): Updated signature.
+ * gcc-plugin.h (plugin_name_args): Moved to this header.
+ * doc/plugins.texi (plugin_init): Updated documention to reflect
+ API change.
+ * doc/plugins.texi (plugin_name_args): Added to documention.
+
+2009-05-21 Mark Mitchell <mark@codesourcery.com>
+
+ * config/arm/neon.md (*mul<mode>3add<mode>_neon): New pattern.
+ (*mul<mode>3neg<mode>add<mode>_neon): Likewise.
+
+2009-05-21 Shujing Zhao <pearly.zhao@oracle.com>
+
+ * config/i386/i386.c: Use REG_P, MEM_P, CONST_INT_P, LABEL_P and
+ JUMP_TABLE_DATA_P predicates where applicable.
+ * config/i386/predicates.md: Ditto.
+ * config/i386/sse.md: Ditto.
+
+2009-05-21 Jakub Jelinek <jakub@redhat.com>
+
+ * config/i386/i386.md (adddi_4_rex64, addsi_4, addhi_4): For
+ operand2 -128 override length_immediate attribute to 1.
+ * config/i386/predicates.md (constm128_operand): New predicate.
+
+ * config/i386/i386.c (memory_address_length): Handle %r12
+ the same as %rsp and %r13 the same as %rbp. For %rsp and %rbp
+ also check REGNO.
+ (ix86_attr_length_address_default): For MODE_SI lea in 64-bit
+ mode look through optional ZERO_EXTEND and SUBREG.
+ * config/i386/i386.md (R12_REG): New define_constant.
+ (prefix_data16): For sse unit set also for MODE_TI insns.
+ (prefix_rex): For -m32 always return 0. For TYPE_IMOVX
+ insns set if operand 1 is ext_QIreg_operand.
+ (modrm): For TYPE_IMOV clear only if not MODE_DI. For
+ TYPE_{ALU{,1},ICMP,TEST} insn clear if there is non-shortened
+ immediate.
+ (*movdi_extzv_1, zero_extendhidi2, zero_extendqidi2): Change
+ mode from MODE_DI to MODE_SI.
+ (movdi_1_rex64): Override modrm and length_immediate attributes
+ only for movabs (TYPE_IMOV, alternative 2).
+ (zero_extendsidi2_rex64): Clear prefix_0f attribute if TYPE_IMOVX.
+ (*float<SSEMODEI24:mode><MODEF:mode>2_mixed_interunit,
+ *float<SSEMODEI24:mode><MODEF:mode>2_mixed_nointerunit,
+ *float<SSEMODEI24:mode><MODEF:mode>2_sse_interunit,
+ *float<SSEMODEI24:mode><MODEF:mode>2_sse_nointerunit): Set
+ prefix_rex attribute if DImode.
+ (*adddi_1_rex64, *adddi_2_rex64, *adddi_3_rex64, *adddi_5_rex64,
+ *addsi_1, *addsi_1_zext, *addsi_2, *addsi_2_zext, *addsi_3,
+ *addsi_3_zext, *addsi_5, *addhi_1_lea, *addhi_1, *addhi_2, *addhi_3,
+ *addhi_5, *addqi_1_lea, *addqi_1): Override length_immediate
+ attribute to 1 if TYPE_ALU and operand 2 is const128_operand.
+ (pro_epilogue_adjust_stack_1, pro_epilogue_adjust_stack_rex64):
+ Likewise. For TYPE_IMOV clear length_immediate attribute.
+ (*ashldi3_1_rex64, *ashldi3_cmp_rex64, *ashldi3_cconly_rex64,
+ *ashlsi3_1, *ashlsi3_1_zext, *ashlsi3_cmp, **ashlsi3_cconly,
+ *ashlsi3_cmp_zext, *ashlhi3_1_lea, *ashlhi3_1, *ashlhi3_cmp,
+ *ashlhi3_cconly, *ashlqi3_1_lea, *ashlqi3_1, *ashlqi3_cmp,
+ *ashlqi3_cconly): Override length_immediate attribute to 0 if TYPE_ALU
+ or one operand TYPE_ISHIFT.
+ (*ashrdi3_1_one_bit_rex64, *ashrdi3_one_bit_cmp_rex64,
+ *ashrdi3_one_bit_cconly_rex64, *ashrsi3_1_one_bit,
+ *ashrsi3_1_one_bit_zext, *ashrsi3_one_bit_cmp,
+ *ashrsi3_one_bit_cconly, *ashrsi3_one_bit_cmp_zext,
+ *ashrhi3_1_one_bit, *ashrhi3_one_bit_cmp, *ashrhi3_one_bit_cconly,
+ *ashrqi3_1_one_bit, *ashrqi3_1_one_bit_slp, *ashrqi3_one_bit_cmp,
+ *ashrqi3_one_bit_cconly, *lshrdi3_1_one_bit_rex64,
+ *lshrdi3_cmp_one_bit_rex64, *lshrdi3_cconly_one_bit_rex64,
+ *lshrsi3_1_one_bit, *lshrsi3_1_one_bit_zext, *lshrsi3_one_bit_cmp,
+ *lshrsi3_one_bit_cconly, *lshrsi3_cmp_one_bit_zext,
+ *lshrhi3_1_one_bit, *lshrhi3_one_bit_cmp, *lshrhi3_one_bit_cconly,
+ *lshrqi3_1_one_bit, *lshrqi3_1_one_bit_slp, *lshrqi2_one_bit_cmp,
+ *lshrqi2_one_bit_cconly, *rotlsi3_1_one_bit_rex64, *rotlsi3_1_one_bit,
+ *rotlsi3_1_one_bit_zext, *rotlhi3_1_one_bit, *rotlqi3_1_one_bit_slp,
+ *rotlqi3_1_one_bit, *rotrdi3_1_one_bit_rex64, *rotrsi3_1_one_bit,
+ *rotrsi3_1_one_bit_zext, *rotrhi3_one_bit, *rotrqi3_1_one_bit,
+ *rotrqi3_1_one_bit_slp): Override length_immediate attribute to 0,
+ set mode attribute, don't override length attribute.
+ (*btsq, *btrq, *btcq, *btdi_rex64, *btsi): Set prefix_0f attribute
+ to 1.
+ (return_internal_long): Set length attribute to 2 instead of 1.
+ (*strmovqi_rex_1, *strsetqi_rex_1, *rep_stosqi_rex64,
+ *cmpstrnqi_nz_rex_1, *cmpstrnqi_rex_1, *strlenqi_rex_1): Clear
+ prefix_rex attribute.
+ * config/i386/predicates.md (ext_QIreg_operand, const128_operand):
+ New predicates.
+ (memory_displacement_only_operand): Always return 0 for TARGET_64BIT.
+
+2009-05-21 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * config/arm/thumb2.md (orsi_notsi_si): Fix typo in pattern.
+
+2009-05-20 Ian Lance Taylor <iant@google.com>
+
+ * tree.c (build_tree_list_vec_stat): New function.
+ (ctor_to_vec): New function.
+ (build_nt_call_vec): New function.
+ (build_call_array): Change args to be a const pointer.
+ (build_call_vec): New function.
+ * tree.h (build_nt_call_vec): Declare.
+ (build_tree_list_vec_stat): Declare.
+ (build_tree_list_vec): Define.
+ (build_call_array): Update declaration.
+ (build_call_vec): Declare.
+ (ctor_to_vec): Declare.
+ * c-common.c (tree_vector_cache): New static variable.
+ (make_tree_vector): New function.
+ (release_tree_vector): New function.
+ (make_tree_vector_single): New function.
+ (make_tree_vector_copy): New function.
+ * c-common.h (tree_vector_cache, make_tree_vector): Declare.
+ (make_tree_vector_single, make_tree_vector_copy): Declare.
+ * c-parser.c (cached_expr_list_1, cached_expr_list_2): Remove.
+ (c_parser_expr_list): Don't manage cache here, instead call
+ make_tree_vector.
+ (c_parser_release_expr_list): Remove static function.
+ (c_parser_vec_to_tree_list): Remove static function.
+ (c_parser_attributes): Call build_tree_list_vec instead of
+ c_parser_vec_to_tree_list. Call release_tree_vector instead of
+ c_parser_release_expr_list.
+ (c_parser_postfix_expression_after_primary): Likewise.
+ (c_parser_objc_keywordexpr): Likewise.
+
+2009-05-20 Sandra Loosemore <sandra@codesourcery.com>
+
+ * doc/tm.texi (Misc): Document TARGET_INVALID_PARAMETER_TYPE,
+ TARGET_INVALID_RETURN_TYPE, TARGET_PROMOTED_TYPE, and
+ TARGET_CONVERT_TO_TYPE.
+ * hooks.c (hook_tree_const_tree_null): Define.
+ * hooks.h (hook_tree_const_tree_null): Declare.
+ * target.h (struct gcc_target): Add invalid_parameter_type,
+ invalid_return_type, promoted_type, and convert_to_type fields.
+ * target-def.h: (TARGET_INVALID_PARAMETER_TYPE): Define.
+ (TARGET_INVALID_RETURN_TYPE): Define.
+ (TARGET_PROMOTED_TYPE): Define.
+ (TARGET_CONVERT_TO_TYPE): Define.
+ (TARGET_INITIALIZER): Update for new fields.
+ * c-decl.c (grokdeclarator): Check targetm.invalid_return_type.
+ (grokparms): Check targetm.invalid_parameter_type.
+ * c-typeck.c (default_conversion): Check targetm.promoted_type.
+ * c-convert.c (convert): Check targetm.convert_to_type.
+
+2009-05-20 Adam Nemet <anemet@caviumnetworks.com>
+
+ * config/mips/mips.md (*extenddi_truncate<mode>,
+ *extendsi_truncate<mode>): Emit exts if supported. Add attribute
+ defintions.
+ (*extendhi_truncateqi): New define_insn_and_sptit.
+
+2009-05-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40204
+ * fold-const.c (fold_binary) <case BIT_AND_EXPR>: Avoid infinite
+ recursion if build_int_cst_type returns the same INTEGER_CST as arg1.
+
+2009-05-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * fold-const.c (build_fold_addr_expr_with_type): Take the address of
+ the operand of VIEW_CONVERT_EXPR.
+
+2009-05-20 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/driver-i386.c (host_detect_local_cpu): Check
+ extended family and model for Intel processors. Support Intel
+ Atom.
+
+2009-05-20 Olivier Hainque <hainque@adacore.com>
+
+ * gstab.h (stab_code_type): Define, to be used instead of the
+ __stab_debug_code enum, made anonymous. Add 2009 to the copyright
+ notice.
+ * dbxout.c (STAB_CODE_TYPE): Remove #define and replace use
+ occurrences by stab_code_type.
+ * mips-tfile.c (STAB_CODE_TYPE): Remove #define, unused.
+
+2009-05-20 Martin Jambor <mjambor@suse.cz>
+
+ * tree-flow.h (insert_edge_copies_seq): Undeclare.
+ (sra_insert_before): Likewise.
+ (sra_insert_after): Likewise.
+ (sra_init_cache): Likewise.
+ (sra_type_can_be_decomposed_p): Likewise.
+ * tree-mudflap.c (insert_edge_copies_seq): Copied here from tree-sra.c
+ * tree-sra.c (sra_type_can_be_decomposed_p): Made static.
+ (sra_insert_before): Likewise.
+ (sra_insert_after): Likewise.
+ (sra_init_cache): Likewise.
+ (insert_edge_copies_seq): Made static and moved upwards.
+
+ * tree-complex.c (extract_component): Added VIEW_CONVERT_EXPR switch
+ case.
+
+ * tree-flow-inline.h (contains_view_convert_expr_p): New function.
+
+ * ipa-prop.c (get_ssa_def_if_simple_copy): New function.
+ (determine_cst_member_ptr): Call get_ssa_def_if_simple_copy to skip
+ simple copies.
+
+2009-05-20 Richard Guenther <rguenther@suse.de>
+
+ * expr.c (expand_expr_real_1): Avoid calling do_store_flag
+ with mismatched comparison modes.
+
+2009-05-20 Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>
+
+ * config/arm/arm.md (*arm_iorsi3): Refactored for only ARM.
+ (peephole ior (reg, int) -> mov, ior): Refactored for only ARM.
+ * config/arm/thumb2.md (*thumb_andsi_not_shiftsi_si): Allow bic
+ with shifts for Thumb2.
+ (orsi_notsi): New for orn.
+ (*thumb_orsi_notshiftsi_si): Allow orn with shifts.
+ (*thumb2_iorsi3): Rewrite support for iorsi for Thumb2.
+ * config/arm/arm.c (const_ok_for_op): Split case for IOR for Thumb2.
+ (arm_gen_constant): Set can_invert for IOR and Thumb2, Add comments.
+ Don't invert remainder for IOR.
+
+2009-05-19 Zdenek Dvorak <ook@ucw.cz>
+
+ PR tree-optimization/40087
+ * tree-ssa-loop-niter.c (number_of_iterations_ne_max,
+ number_of_iterations_ne): Rename never_infinite argument.
+ (number_of_iterations_lt_to_ne, number_of_iterations_lt,
+ number_of_iterations_le): Handle pointer-type ivs when
+ exit_must_be_taken is false.
+ (number_of_iterations_cond): Do not always assume that
+ exit_must_be_taken if the control variable is a pointer.
+
+2009-05-19 Andrew Pinski <andrew_pinski@playstation.sony.com>
+
+ * c-typeck.c (build_binary_op): Allow % on integal vectors.
+ * doc/extend.texi (Vector Extension): Document that % is allowed too.
+
+2009-05-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ * config/i386/i386.c (ix86_avoid_jump_mispredicts): Check
+ ASM_OUTPUT_MAX_SKIP_PAD instead of ASM_OUTPUT_MAX_SKIP_ALIGN.
+
+2009-05-19 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR c/40172
+ * c.opt (Wlogical-op): Disabled by default.
+ * c-opt (c_common_post_options): Do not enable Wlogical-op with
+ Wextra.
+ * doc/invoke.texi (Wlogical-op): Likewise.
+
+2009-05-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * tree-scalar-evolution.c (follow_ssa_edge_expr) <NOP_EXPR>: Turn
+ into CASE_CONVERT.
+ <PLUS_EXPR>: Strip useless type conversions instead of type nops.
+ Propagate the type of the first operand.
+ <ASSERT_EXPR>: Simplify.
+ (follow_ssa_edge_in_rhs): Use gimple_expr_type to get the type.
+ Rewrite using the RHS code as discriminant.
+ <NOP_EXPR>: Turn into CASE_CONVERT.
+ <PLUS_EXPR>: Propagate the type of the first operand.
+
+2009-05-19 Steve Ellcey <sje@cup.hp.com>
+
+ * config/ia64/ia64-protos.h (ia64_dconst_0_5): New.
+ (ia64_dconst_0_375): New.
+ * config/ia64/ia64.c (ia64_override_options): Remove
+ -minline-sqrt-min-latency warning.
+ (ia64_dconst_0_5_rtx, ia64_dconst_0_5): New.
+ (ia64_dconst_0_375_rtx, ia64_dconst_0_375): New
+ * config/ia64/ia64.md (*sqrt_approx): Remove.
+ (sqrtsf2): Remove #if 0.
+ (sqrtsf2_internal_thr): Rewrite and move to div.md.
+ (sqrtdf): Remove assert.
+ (sqrtdf2_internal_thr): Rewrite and move to div.md.
+ (sqrtxf2): Remove #if 0.
+ (sqrtxf2_internal_thr): Rewrite and move to div.md.
+ * div.md (sqrt_approx_rf): New.
+ (sqrtsf2_internal_thr): New implementation.
+ (sqrtsf2_internal_lat): New.
+ (sqrtdf2_internal_thr: New implementation.
+ (sqrtxf2_internal): New implementation.
+
+2009-05-19 Francois-Xavier Coudert <fxcoudert@gmail.com>
+ Hans-Peter Nilsson <hp@axis.com>
+
+ * defaults.h (UINT_FAST64_TYPE, INTPTR_TYPE, UINTPTR_TYPE)
+ (WCHAR_TYPE, MODIFIED_WCHAR_TYPE, PTRDIFF_TYPE, WINT_TYPE)
+ (INTMAX_TYPE, UINTMAX_TYPE, SIG_ATOMIC_TYPE, INT8_TYPE, INT16_TYPE)
+ (INT32_TYPE, INT64_TYPE, UINT8_TYPE, UINT16_TYPE, UINT32_TYPE)
+ (UINT64_TYPE, INT_LEAST8_TYPE, INT_LEAST16_TYPE, INT_LEAST32_TYPE)
+ (INT_LEAST64_TYPE, UINT_LEAST8_TYPE, UINT_LEAST16_TYPE)
+ (UINT_LEAST32_TYPE, UINT_LEAST64_TYPE, INT_FAST8_TYPE)
+ (INT_FAST16_TYPE, INT_FAST32_TYPE, INT_FAST64_TYPE)
+ (UINT_FAST8_TYPE, UINT_FAST16_TYPE, UINT_FAST32_TYPE)
+ (SIZE_TYPE, PID_TYPE, CHAR16_TYPE, CHAR32_TYPE): Move defaults here...
+ * c-common.c: ...from here.
+
+2009-05-19 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ * c-common.c (warn_logical_operator): Remove unnecessary
+ conditionals.
+
+2009-05-19 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
+
+ * builtins.c (do_mpc_arg1): Separate MPFR/MPC C rounding types.
+
+2009-05-19 Ben Elliston <bje@au.ibm.com>
+
+ * unwind-dw2-fde.c (fde_unencoded_compare): Replace type punning
+ assignments with memcpy calls.
+ (add_fdes): Likewise.
+ (binary_search_unencoded_fdes): Likewise.
+ (linear_search_fdes): Eliminate type puns.
+
+2009-05-19 Richard Guenther <rguenther@suse.de>
+
+ * tree-ssa-forwprop.c (forward_propagate_addr_expr_1): Do
+ not falsely claim to have propagated into all uses.
+
+2009-05-19 Ben Elliston <bje@au.ibm.com>
+
+ * doc/invoke.texi (C Dialect Options): Update OpenMP specification
+ version to v3.0.
+
+2009-05-18 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * config/sh/sh-protos.h (sh_legitimate_address_p): Remove.
+ * config/sh/sh.c (sh_legitimate_address_p): Make static.
+ (TARGET_LEGITIMATE_ADDRESS_P): New.
+ * config/sh/sh.h (GO_IF_LEGITIMATE_ADDRESS): Delete.
+ * config/sh/sh.md: Clean up references to GO_IF_LEGITIMATE_ADDRESS.
+
+2009-05-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR debug/40109
+ * dwarf2out.c (gen_type_die_with_usage): Generate the DIE as a
+ child of the containing namespace's DIE.
+
+2009-05-18 Adam Nemet <anemet@caviumnetworks.com>
+
+ * config/mips/mips.md (*zero_extend<GPR:mode>_trunc<SHORT:mode>,
+ *zero_extendhi_truncqi): Move after the zero_extend patterns.
+ (*extenddi_truncate<mode>, *extendsi_truncate<mode>): Move after the
+ extend patterns.
+
+2009-05-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR target/39942
+ * config/i386/i386.c (ix86_avoid_jump_misspredicts): Replace
+ gen_align with gen_pad.
+ (ix86_reorg): Check ASM_OUTPUT_MAX_SKIP_PAD instead of
+ #ifdef ASM_OUTPUT_MAX_SKIP_ALIGN.
+
+ * config/i386/i386.h (ASM_OUTPUT_MAX_SKIP_PAD): New.
+ * config/i386/x86-64.h (ASM_OUTPUT_MAX_SKIP_PAD): Likewise.
+
+ * config/i386/i386.md (align): Renamed to ...
+ (pad): This. Replace ASM_OUTPUT_MAX_SKIP_ALIGN with
+ ASM_OUTPUT_MAX_SKIP_PAD.
+
+2009-05-18 Andreas Schwab <schwab@linux-m68k.org>
+
+ * config.gcc: Fix variable syntax.
+
+ PR target/39531
+ * config/m68k/m68k.c (output_andsi3): Mask off sign bit copies
+ before calling exact_log2.
+ (output_iorsi3): Likewise.
+ (output_xorsi3): Likewise.
+
+2009-05-18 Kaz Kojima <kkojima@gcc.gnu.org>
+
+ * config/sh/sh.c (expand_cbranchdi4): Use a scratch register
+ for the none zero constant operand except for EQ and NE
+ comprisons even when the first operand is R0.
+
+2009-05-18 Andreas Krebbel <krebbel1@de.ibm.com>
+
+ * config/s390/2064.md: Remove trailing whitespaces.
+ * config/s390/2084.md: Likewise.
+ * config/s390/constraints.md: Likewise.
+ * config/s390/fixdfdi.h: Likewise.
+ * config/s390/libgcc-glibc.ver: Likewise.
+ * config/s390/s390-modes.def: Likewise.
+ * config/s390/s390-protos.h: Likewise.
+ * config/s390/s390.c: Likewise.
+ * config/s390/s390.h: Likewise.
+ * config/s390/s390.md: Likewise.
+ * config/s390/tpf-unwind.h: Likewise.
+
+2009-05-18 Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ * config/m68k/m68k.c (m68k_legitimize_address): Fix typo in signature.
+
+2009-05-18 Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ M68K TLS support.
+ * configure.ac (m68k-*-*): Check if binutils support TLS.
+ * configure: Regenerate.
+ * config/m68k/predicates.md (symbolic_operand): Extend comment.
+ * config/m68k/constraints.md (Cu): New constraint.
+ * config/m68k/m68k.md (UNSPEC_GOTOFF): Remove.
+ (UNSPEC_RELOC16, UNSPEC_RELOC32): New constants.
+ (movsi): Handle TLS symbols.
+ (addsi3_5200): Handle XTLS symbols, indent.
+ * config/m68k/m68k-protos.h (m68k_legitimize_tls_address): Declare.
+ (m68k_tls_reference_p): Declare.
+ (m68k_legitimize_address): Declare.
+ (m68k_unwrap_symbol): Declare.
+ * config/m68k/m68k.opt (mxtls): New option.
+ * config/m68k/m68k.c (ggc.h): Include.
+ (m68k_output_dwarf_dtprel): Implement hook.
+ (TARGET_HAVE_TLS, TARGET_ASM_OUTPUT_DWARF_DTPREL): Define.
+ (m68k_expand_prologue): Load GOT pointer when function needs it.
+ (m68k_illegitimate_symbolic_constant_p): Handle TLS symbols.
+ (m68k_legitimate_constant_address_p): Same.
+ (m68k_decompose_address): Handle TLS references.
+ (m68k_get_gp): New static function.
+ (enum m68k_reloc): New contants.
+ (TLS_RELOC_P): New macro.
+ (m68k_wrap_symbol): New static function.
+ (m68k_unwrap_symbol): New function.
+ (m68k_final_prescan_insn_1): New static function.
+ (m68k_final_prescan_insn): New function.
+ (m68k_move_to_reg, m68k_wrap_symbol_into_got_ref): New static
+ functions.
+ (legitimize_pic_address): Handle TLS references..
+ (m68k_tls_get_addr, m68k_get_tls_get_addr)
+ (m68k_libcall_value_in_a0_p)
+ (m68k_call_tls_get_addr, m68k_read_tp, m68k_get_m68k_read_tp)
+ (m68k_call_m68k_read_tp): Helper variables and functions for ...
+ (m68k_legitimize_tls_address): Handle TLS references.
+ (m68k_tls_symbol_p, m68k_tls_reference_p_1, m68k_tls_reference_p):
+ New functions.
+ (m68k_legitimize_address): Handle TLS symbols.
+ (m68k_get_reloc_decoration): New static function.
+ (m68k_output_addr_const_extra): Handle UNSPEC_RELOC16 and
+ UNSPEC_RELOC32.
+ (m68k_output_dwarf_dtprel): Implement hook.
+ (print_operand_address): Handle UNSPEC_RELOC16 adn UNSPEC_RELOC32.
+ (m68k_libcall_value): Return result in A0 instead of D0 when asked by
+ m68k_call_* routines.
+ (sched_attr_op_type): Handle TLS symbols.
+ (gt-m68k.h): Include.
+ * config/m68k/m68k.h (FINAL_PRESCAN_INSN): Define.
+ (LEGITIMATE_PIC_OPERAND_P): Support TLS.
+
+2009-05-18 Martin Jambor <mjambor@suse.cz>
+
+ * ipa-prop.c (ipa_check_stmt_modifications): Removed.
+ (visit_store_addr_for_mod_analysis): New function.
+ (ipa_detect_param_modifications): Use walk_stmt_load_store_addr_ops.
+ (determine_cst_member_ptr): Use gimple_assign_single_p.
+ (ipa_get_stmt_member_ptr_load_param): Use gimple_assign_single_p.
+ (ipa_analyze_call_uses): Use !gimple_assign_rhs2 rather than number of
+ operands. Don't check number of operands of a NOP_EXPR.
+
+2009-05-18 Eric Fisher <joefoxreal@gmail.com>
+
+ * doc/tree-ssa.texi (SSA Operands): Fix a mistake.
+
+2009-05-17 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR c/40172
+ * c-common.c (warn_logical_operator): Don't warn if one of
+ expression isn't always true or false.
+
+2009-05-17 Kai Tietz <kai.tietz@onevision.com>
+
+ * config/i386/biarch32.h: New file.
+ * config.gcc: Add for target i386-w64-* the biarch32.h to tm_file.
+
+2009-05-17 Adam Nemet <anemet@caviumnetworks.com>
+
+ * config/mips/mips.md (*zero_extend<mode>_trunchi,
+ *zero_extend<mode>_truncqi): Merge these into ...
+ (*zero_extend<GPR:mode>_trunc<SHORT:mode>): ... this new pattern.
+ Name the pattern following this as *zero_extendhi_truncqi.
+
+2009-05-16 Brad Lucier <lucier@math.purdue.edu>
+
+ PR middle-end/39301
+ * hwint.h: Add macro HOST_WIDEST_INT_PRINT.
+ * bitmap.c (bitmap_descriptor): Make fields HOST_WIDEST_INT.
+ (output_info): Make field HOST_WIDEST_INT.
+ (print_statistics): Use HOST_WIDEST_INT_PRINT.
+ (dump_bitmat_statistics): Same.
+
+2009-05-16 Francois-Xavier Coudert <fxcoudert@gmail.com>
+
+ * config.gcc (use_gcc_stdint): Set to wrap.
+ * config/darwin.h (SIG_ATOMIC_TYPE, INT8_TYPE, INT16_TYPE,
+ INT32_TYPE, INT64_TYPE, UINT8_TYPE, UINT16_TYPE, UINT32_TYPE,
+ UINT64_TYPE, INT_LEAST8_TYPE, INT_LEAST16_TYPE, INT_LEAST32_TYPE,
+ INT_LEAST64_TYPE, UINT_LEAST8_TYPE, UINT_LEAST16_TYPE,
+ UINT_LEAST32_TYPE, UINT_LEAST64_TYPE, INT_FAST8_TYPE,
+ INT_FAST16_TYPE, INT_FAST32_TYPE, INT_FAST64_TYPE,
+ UINT_FAST8_TYPE, UINT_FAST16_TYPE, UINT_FAST32_TYPE,
+ UINT_FAST64_TYPE, INTPTR_TYPE, UINTPTR_TYPE): Define.
+
+2009-05-16 Joseph Myers <joseph@codesourcery.com>
+
+ * config.gcc (mips*-*-*): Support arch_32, arch_64, tune_32 and
+ tune_64.
+ * config/mips/mips.h (MIPS_ABI_DEFAULT, MULTILIB_ABI_DEFAULT):
+ Move definitions earlier.
+ (OPT_ARCH64, OPT_ARCH32): Define.
+ (OPTION_DEFAULT_SPECS): Add entries for arch_32, arch_64, tune_32
+ and tune_64.
+
+2009-05-16 Richard Earnshaw <rearnsha@arm.com>
+
+ PR target/40153
+ * arm.md (cstoresi_nltu_thumb1): Use a neg of ltu as the pattern name
+ implies.
+
+2009-05-16 Richard Earnshaw <rearnsha@arm.com>
+
+ * arm.md (movdi2): Copy non-reg values to DImode registers.
+
+2009-05-16 Jakub Jelinek <jakub@redhat.com>
+
+ PR target/39942
+ * final.c (label_to_max_skip): New function.
+ (label_to_alignment): Only use LABEL_TO_ALIGNMENT if
+ CODE_LABEL_NUMBER <= max_labelno.
+ * output.h (label_to_max_skip): New prototype.
+ * config/i386/i386.c (ix86_avoid_jump_misspredicts): Renamed to...
+ (ix86_avoid_jump_mispredicts): ... this. Don't define if
+ ASM_OUTPUT_MAX_SKIP_ALIGN isn't defined. Update comment.
+ Handle CODE_LABELs with >= 16 byte alignment or with
+ max_skip == (1 << align) - 1.
+ (ix86_reorg): Don't call ix86_avoid_jump_mispredicts if
+ ASM_OUTPUT_MAX_SKIP_ALIGN isn't defined.
+
+ PR target/39942
+ * config/i386/x86-64.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Don't emit second
+ .p2align 3 if MAX_SKIP is smaller than 7.
+ * config/i386/linux.h (ASM_OUTPUT_MAX_SKIP_ALIGN): Likewise.
+
2009-05-15 Ian Lance Taylor <iant@google.com>
* alias.c (struct alias_set_entry_d): Rename from struct
@@ -16,10 +1421,8 @@
* graphite.h (struct name_tree_d): Rename from struct name_tree.
Change all uses.
(struct sese_d): Rename from struct sese. Change all uses.
- * omega.h (struct eqn_d): Rename from struct eqn. Change all
- uses.
- (struct omega_pb_d): Rename from struct omega_pb. Change all
- uses.
+ * omega.h (struct eqn_d): Rename from struct eqn. Change all uses.
+ (struct omega_pb_d): Rename from struct omega_pb. Change all uses.
* optabs.h (struct optab_d): Rename from struct optab. Change all
uses.
(struct convert_optab_d): Rename from struct convert_optab.
@@ -50,8 +1453,7 @@
2009-05-15 Manuel López-Ibáñez <manu@gcc.gnu.org>
- * ira-conflicts.c (add_insn_allocno_copies): Fix wrong
- conditional.
+ * ira-conflicts.c (add_insn_allocno_copies): Fix wrong conditional.
2009-05-15 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
@@ -69,8 +1471,7 @@
2009-05-15 Sandra Loosemore <sandra@codesourcery.com>
- * fold-const.c (fold_convert_const_real_from_real): Check for
- overflow.
+ * fold-const.c (fold_convert_const_real_from_real): Check for overflow.
2009-05-15 H.J. Lu <hongjiu.lu@intel.com>
@@ -130,7 +1531,7 @@
(ipcp_estimate_growth, ipcp_insert_stage): Likewise.
(ipcp_update_callgraph): Do not touch function bodies.
* ipa-inline.c: Include except.h
- MAX_TIME: New constant.
+ (MAX_TIME): New constant.
(overall_insns): Remove
(overall_size, max_benefit): New static variables.
(cgraph_estimate_time_after_inlining): New function.
@@ -142,9 +1543,11 @@
(cgraph_default_inline_p): Likewise.
(cgraph_edge_badness): Compute badness based on benefit and size cost.
(cgraph_decide_recursive_inlining): Check size.
- (cgraph_decide_inlining_of_small_function): Update size; dump sizes and times.
+ (cgraph_decide_inlining_of_small_function): Update size; dump sizes and
+ times.
(cgraph_decide_inlining): Likewise.
- (cgraph_decide_inlining_incrementally): Likewise; honor PARAM_EARLY_INLINING_INSNS.
+ (cgraph_decide_inlining_incrementally): Likewise; honor
+ PARAM_EARLY_INLINING_INSNS.
(likely_eliminated_by_inlining_p): New predicate.
(estimate_function_body_sizes): New function.
(compute_inline_parameters): Use it.
@@ -198,7 +1601,7 @@
(ipcp_estimate_growth, ipcp_insert_stage): Likewise.
(ipcp_update_callgraph): Do not touch function bodies.
* ipa-inline.c: Include except.h
- MAX_TIME: New constant.
+ (MAX_TIME): New constant.
(overall_insns): Remove
(overall_size, max_benefit): New static variables.
(cgraph_estimate_time_after_inlining): New function.
@@ -210,9 +1613,11 @@
(cgraph_default_inline_p): Likewise.
(cgraph_edge_badness): Compute badness based on benefit and size cost.
(cgraph_decide_recursive_inlining): Check size.
- (cgraph_decide_inlining_of_small_function): Update size; dump sizes and times.
+ (cgraph_decide_inlining_of_small_function): Update size; dump sizes and
+ times.
(cgraph_decide_inlining): Likewise.
- (cgraph_decide_inlining_incrementally): Likewise; honor PARAM_EARLY_INLINING_INSNS.
+ (cgraph_decide_inlining_incrementally): Likewise; honor
+ PARAM_EARLY_INLINING_INSNS.
(likely_eliminated_by_inlining_p): New predicate.
(estimate_function_body_sizes): New function.
(compute_inline_parameters): Use it.
@@ -262,35 +1667,35 @@
2009-05-15 Paolo Bonzini <bonzini@gnu.org>
- * config/frv/frv.h: Clean up references to GO_IF_LEGITIMATE_ADDRESS.
- * config/frv/frv.c: Likewise.
- * config/s390/s390.c: Likewise.
- * config/sparc/sparc.h: Likewise.
- * config/i386/i386.h: Likewise.
- * config/i386/i386.c: Likewise.
- * config/crx/crx.c: Likewise.
- * config/m68hc11/m68hc11.h: Likewise.
- * config/iq2000/iq2000.c: Likewise.
- * config/mn10300/mn10300.h: Likewise.
- * config/mn10300/mn10300.c: Likewise.
- * config/m68k/m68k.c: Likewise.
- * config/rs6000/rs6000.c: Likewise.
- * config/rs6000/xcoff.h: Likewise.
- * config/rs6000/linux64.h: Likewise.
- * config/rs6000/sysv4.h: Likewise.
- * config/score/score3.c: Likewise.
- * config/score/score7.c: Likewise.
- * config/score/score.c: Likewise.
- * config/arm/arm.md: Likewise.
- * config/mips/mips.c: Likewise.
- * config/mips/mips.md: Likewise.
- * config/bfin/bfin.h: Likewise.
- * config/pa/pa.c: Likewise.
- * config/pa/constraints.md: Likewise.
-
- * config/pdp11/pdp11-protos.h (legitimate_address_p): Delete.
- * config/pdp11/pdp11.c (legitimate_address_p): Delete.
- * config/pdp11/pdp11.h: Use memory_address_p instead.
+ * config/frv/frv.h: Clean up references to GO_IF_LEGITIMATE_ADDRESS.
+ * config/frv/frv.c: Likewise.
+ * config/s390/s390.c: Likewise.
+ * config/sparc/sparc.h: Likewise.
+ * config/i386/i386.h: Likewise.
+ * config/i386/i386.c: Likewise.
+ * config/crx/crx.c: Likewise.
+ * config/m68hc11/m68hc11.h: Likewise.
+ * config/iq2000/iq2000.c: Likewise.
+ * config/mn10300/mn10300.h: Likewise.
+ * config/mn10300/mn10300.c: Likewise.
+ * config/m68k/m68k.c: Likewise.
+ * config/rs6000/rs6000.c: Likewise.
+ * config/rs6000/xcoff.h: Likewise.
+ * config/rs6000/linux64.h: Likewise.
+ * config/rs6000/sysv4.h: Likewise.
+ * config/score/score3.c: Likewise.
+ * config/score/score7.c: Likewise.
+ * config/score/score.c: Likewise.
+ * config/arm/arm.md: Likewise.
+ * config/mips/mips.c: Likewise.
+ * config/mips/mips.md: Likewise.
+ * config/bfin/bfin.h: Likewise.
+ * config/pa/pa.c: Likewise.
+ * config/pa/constraints.md: Likewise.
+
+ * config/pdp11/pdp11-protos.h (legitimate_address_p): Delete.
+ * config/pdp11/pdp11.c (legitimate_address_p): Delete.
+ * config/pdp11/pdp11.h: Use memory_address_p instead.
2009-05-14 Ian Lance Taylor <iant@google.com>
@@ -428,10 +1833,8 @@
(TARGET_LEGITIMATE_ADDRESS_P): New.
* config/iq2000/iq2000.h (GO_IF_LEGITIMATE_ADDRESS): Delete.
- * config/iq2000/iq2000-protos.h (iq2000_legitimate_address_p):
- Remove.
- * config/iq2000/iq2000.c (iq2000_legitimate_address_p):
- Make static.
+ * config/iq2000/iq2000-protos.h (iq2000_legitimate_address_p): Remove.
+ * config/iq2000/iq2000.c (iq2000_legitimate_address_p): Make static.
(TARGET_LEGITIMATE_ADDRESS_P): New.
* config/mn10300/mn10300.h (GO_IF_LEGITIMATE_ADDRESS): Delete.
@@ -1463,8 +2866,7 @@
* config/arm/arm.c (arm_handle_fndecl_attribute,
arm_handle_isr_attribute): Likewise.
* config/avr/avr.c (avr_handle_progmem_attribute,
- avr_handle_fndecl_attribute, avr_handle_fntype_attribute):
- Likewise.
+ avr_handle_fndecl_attribute, avr_handle_fntype_attribute): Likewise.
* config/bfin/bfin.c (handle_int_attribute,
bfin_handle_longcall_attribute, bfin_handle_l1_text_attribute,
bfin_handle_l1_data_attribute, bfin_handle_longcall_attribute,
@@ -1476,8 +2878,7 @@
h8300_handle_eightbit_data_attribute,
h8300_handle_tiny_data_attribute): Likewise.
* config/i386/i386.c (ix86_handle_cconv_attribute,
- ix86_handle_abi_attribute, ix86_handle_struct_attribute):
- Likewise.
+ ix86_handle_abi_attribute, ix86_handle_struct_attribute): Likewise.
* config/i386/winnt.c (ix86_handle_shared_attribute,
ix86_handle_selectany_attribute): Likewise.
* config/ia64/ia64.c (ia64_handle_model_attribute): Likewise.
@@ -1506,8 +2907,7 @@
2009-05-10 Joseph Myers <joseph@codesourcery.com>
- * pretty-print.h (struct pretty_print_info): Add
- translate_identifiers.
+ * pretty-print.h (struct pretty_print_info): Add translate_identifiers.
(pp_translate_identifiers): New.
(pp_identifier): Only conditionally translate identifier to locale
character set.
diff --git a/gcc/DATESTAMP b/gcc/DATESTAMP
index 90693c241d3..00d4f4d14de 100644
--- a/gcc/DATESTAMP
+++ b/gcc/DATESTAMP
@@ -1 +1 @@
-20090516
+20090528
diff --git a/gcc/Makefile.in b/gcc/Makefile.in
index b36377f9809..ddc7ba3295a 100644
--- a/gcc/Makefile.in
+++ b/gcc/Makefile.in
@@ -205,6 +205,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 = $(CXX)
+COMPILER_FLAGS = $(CXXFLAGS)
+LINKER = $(CXX)
+LINKER_FLAGS = $(CXXFLAGS)
+
# -------------------------------------------
# Programs which operate on the build machine
# -------------------------------------------
@@ -607,7 +614,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)
@@ -706,6 +713,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)
@@ -800,7 +815,7 @@ endif
# Shorthand variables for dependency lists.
EXCEPT_H = except.h sbitmap.h vecprim.h
-TOPLEV_H = toplev.h input.h
+TOPLEV_H = toplev.h input.h bversion.h
TARGET_H = $(TM_H) target.h insn-modes.h
MACHMODE_H = machmode.h mode-classes.def insn-modes.h
HOOKS_H = hooks.h $(MACHMODE_H)
@@ -892,7 +907,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
#
@@ -919,6 +935,12 @@ ALL_CXXFLAGS = $(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_CXXFLAGS)
+
+# This is the variable to use when using $(LINKER).
+ALL_LINKERFLAGS = $(ALL_CXXFLAGS)
+
# Build and host support libraries.
LIBIBERTY = ../libiberty/libiberty.a
BUILD_LIBIBERTY = $(build_libobjdir)/libiberty/libiberty.a
@@ -965,7 +987,7 @@ INCLUDES = -I. -I$(@D) -I$(srcdir) -I$(srcdir)/$(@D) \
# [gcc-in-cxx] Keep the .c extension, but compile with C++.
.c.o:
- $(CXX) -x c++ -c $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $< $(OUTPUT_OPTION)
#
# Support for additional languages (other than C).
@@ -1640,16 +1662,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)
- $(CXX) $(ALL_CXXFLAGS) $(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)
- $(CXX) $(ALL_CXXFLAGS) $(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)
@@ -1665,8 +1687,8 @@ gcc-cross$(exeext): xgcc$(exeext)
dummy-checksum.o : dummy-checksum.c
cc1-dummy$(exeext): $(C_OBJS) dummy-checksum.o $(BACKEND) $(LIBDEPS)
- $(CXX) $(ALL_CXXFLAGS) $(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) > $@
@@ -1674,8 +1696,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)
- $(CXX) $(ALL_CXXFLAGS) $(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.
@@ -1891,13 +1913,13 @@ COLLECT2_OBJS = collect2.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.
- $(CXX) $(ALL_CXXFLAGS) $(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
- $(CXX) $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DTARGET_MACHINE=\"$(target_noncanonical)\" \
-c $(srcdir)/collect2.c $(OUTPUT_OPTION)
@@ -1924,15 +1946,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)
- $(CXX) -c $(ALL_CXXFLAGS) $(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
- $(CXX) -c $(ALL_CXXFLAGS) $(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.
@@ -1956,7 +1978,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
- $(CXX) -c $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DHOST_MACHINE=\"$(host)\" -DTARGET_MACHINE=\"$(target)\" \
$< $(OUTPUT_OPTION)
@@ -1982,13 +2004,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)'; \
- $(CXX) $(ALL_CXXFLAGS) $(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)'; \
- $(CXX) $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
$(DRIVER_DEFINES) \
-c $(srcdir)/gccspec.c $(OUTPUT_OPTION))
@@ -2023,7 +2045,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
- $(CXX) -c $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) $(OUTPUT_OPTION) -DGCC_DRIVER options.c
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(OUTPUT_OPTION) \
+ -DGCC_DRIVER options.c
dumpvers: dumpvers.c
@@ -2032,7 +2055,7 @@ version.o: version.c version.h $(REVISION) $(DATESTAMP) $(BASEVER) $(DEVPHASE)
else
version.o: version.c version.h $(DATESTAMP) $(BASEVER) $(DEVPHASE)
endif
- $(CXX) $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DBASEVER=$(BASEVER_s) -DDATESTAMP=$(DATESTAMP_s) \
-DREVISION=$(REVISION_s) \
-DDEVPHASE=$(DEVPHASE_s) -DPKGVERSION=$(PKGVERSION_s) \
@@ -2051,15 +2074,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)
@@ -2069,7 +2093,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)
- $(CXX) $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DPREFIX=\"$(prefix)\" -DBASEVER=$(BASEVER_s) \
-c $(srcdir)/prefix.c $(OUTPUT_OPTION)
@@ -2473,6 +2497,14 @@ targhooks.o : targhooks.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TREE_H) \
$(MACHMODE_H) $(TARGET_DEF_H) $(TARGET_H) $(GGC_H) gt-targhooks.h \
$(OPTABS_H) $(RECOG_H) reload.h
+bversion.h: s-bversion; @true
+s-bversion: BASE-VER
+ echo "#define BUILDING_GCC_MAJOR `echo $(BASEVER_c) | sed -e 's/^\([0-9]*\).*$$/\1/'`" > bversion.h
+ echo "#define BUILDING_GCC_MINOR `echo $(BASEVER_c) | sed -e 's/^[0-9]*\.\([0-9]*\).*$$/\1/'`" >> bversion.h
+ echo "#define BUILDING_GCC_PATCHLEVEL `echo $(BASEVER_c) | sed -e 's/^[0-9]*\.[0-9]*\.\([0-9]*\)$$/\1/'`" >> bversion.h
+ echo "#define BUILDING_GCC_VERSION (BUILDING_GCC_MAJOR * 1000 + BUILDING_GCC_MINOR)" >> bversion.h
+ $(STAMP) s-bversion
+
toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
version.h $(RTL_H) $(FUNCTION_H) $(FLAGS_H) xcoffout.h $(INPUT_H) \
$(INSN_ATTR_H) output.h $(DIAGNOSTIC_H) debug.h insn-config.h intl.h \
@@ -2483,7 +2515,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)
- $(CXX) $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DTARGET_NAME=\"$(target_noncanonical)\" \
-c $(srcdir)/toplev.c $(OUTPUT_OPTION)
@@ -2499,7 +2531,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)
@@ -3107,18 +3139,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)
- $(CXX) -c $(ALL_CXXFLAGS) $(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
@@ -3127,7 +3161,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
- $(CXX) $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DTARGET_NAME=\"$(target_noncanonical)\" \
-DLOCALEDIR=\"$(localedir)\" \
-c $(filter %.c,$^) -o $@ \
@@ -3398,7 +3432,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...
@@ -3476,13 +3511,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)).
@@ -3506,7 +3541,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
- $(CXX) $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
-DLOCALEDIR=\"$(localedir)\" \
-c $(srcdir)/intl.c $(OUTPUT_OPTION)
@@ -3528,7 +3563,7 @@ PREPROCESSOR_DEFINES = \
cppdefault.o: cppdefault.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
cppdefault.h Makefile
- $(CXX) $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) \
+ $(COMPILER) $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
$(PREPROCESSOR_DEFINES) \
-c $(srcdir)/cppdefault.c $(OUTPUT_OPTION)
@@ -3540,7 +3575,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)
@@ -3556,10 +3592,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)
- $(CXX) $(ALL_CXXFLAGS) $(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)
- $(CXX) $(ALL_CXXFLAGS) $(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
@@ -4024,8 +4061,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 0548b21cbcf..69aa6229e25 100644
--- a/gcc/ada/ChangeLog
+++ b/gcc/ada/ChangeLog
@@ -1,3 +1,47 @@
+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 ...
+ * switch.ads (Is_Internal_GCC_Switch, Switch_Last): New functions.
+ Add -auxbase variants to the list of recognized internal switches.
+ * back_end.adb (Scan_Back_End_Switches): Use the new functions and
+ adjust comments.
+ * lib.ads: Make comment on internal GCC switches more general.
+ * gcc-interface/lang-specs.h (specs for Ada): Pass -auxbase variants
+ as for C.
+
+2009-05-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/misc.c (gnat_get_subrange_bounds): Fix thinko.
+
+2009-05-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (set_rm_size): Bypass the check for packed array
+ types.
+
+2009-05-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <object>: Do not modify the
+ original type because of the alignment when there is an address clause.
+
+2009-05-20 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gcc-interface/decl.c (gnat_to_gnu_entity) <E_Record_Subtype>: When
+ discriminants affect the shape of the subtype, retrieve the GCC type
+ directly from the original field if the GNAT types for the field and
+ the original field are the same.
+
2009-05-15 Eric Botcazou <ebotcazou@adacore.com>
* gcc-interface/ada-tree.h (TYPE_GCC_MIN_VALUE, TYPE_GCC_MAX_VALUE):
diff --git a/gcc/ada/back_end.adb b/gcc/ada/back_end.adb
index baf3ffda37f..a15d9ecfc16 100644
--- a/gcc/ada/back_end.adb
+++ b/gcc/ada/back_end.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2008, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -158,12 +158,10 @@ package body Back_End is
-- entire string should consist of valid switch characters, except that
-- an optional terminating NUL character is allowed.
--
- -- Back end switches have already been checked and processed by GCC
- -- in toplev.c, so no errors can occur and control will always return.
- -- The switches must still be scanned to skip the arguments of the
- -- "-o" or the (undocumented) "-dumpbase" switch, by incrementing
- -- the Next_Arg variable. The "-dumpbase" switch is used to set the
- -- basename for GCC dumpfiles.
+ -- Back end switches have already been checked and processed by GCC in
+ -- toplev.c, so no errors can occur and control will always return. The
+ -- switches must still be scanned to skip "-o" or internal GCC switches
+ -- with their argument.
-------------
-- Len_Arg --
@@ -186,21 +184,13 @@ package body Back_End is
procedure Scan_Back_End_Switches (Switch_Chars : String) is
First : constant Positive := Switch_Chars'First + 1;
- Last : Natural := Switch_Chars'Last;
+ Last : constant Natural := Switch_Last (Switch_Chars);
begin
- if Last >= First
- and then Switch_Chars (Last) = ASCII.NUL
- then
- Last := Last - 1;
- end if;
-
- -- For switches -o, -dumpbase, --param, skip following argument and
- -- do not store either the switch or the following argument.
+ -- Skip -o or internal GCC switches together with their argument
- if Switch_Chars (First .. Last) = "o" or else
- Switch_Chars (First .. Last) = "dumpbase" or else
- Switch_Chars (First .. Last) = "-param"
+ if Switch_Chars (First .. Last) = "o"
+ or else Is_Internal_GCC_Switch (Switch_Chars)
then
Next_Arg := Next_Arg + 1;
diff --git a/gcc/ada/gcc-interface/Make-lang.in b/gcc/ada/gcc-interface/Make-lang.in
index 564919d793e..1f231aeadc3 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) \
+ $(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) \
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ADA_CFLAGS) \
$(ALL_CPPFLAGS) $(INCLUDES) $< $(OUTPUT_OPTION)
ada/initialize.o : ada/initialize.c
- $(CC) -c $(ALL_CFLAGS) $(ADA_CFLAGS) \
+ $(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) \
+ $(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/decl.c b/gcc/ada/gcc-interface/decl.c
index 46215daf4c9..e6f1d3a2463 100644
--- a/gcc/ada/gcc-interface/decl.c
+++ b/gcc/ada/gcc-interface/decl.c
@@ -608,17 +608,22 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
return error_mark_node;
}
- /* If an alignment is specified, use it if valid. Note that
- exceptions are objects but don't have alignments. We must do this
- before we validate the size, since the alignment can affect the
- size. */
+ /* If an alignment is specified, use it if valid. Note that exceptions
+ are objects but don't have an alignment. We must do this before we
+ validate the size, since the alignment can affect the size. */
if (kind != E_Exception && Known_Alignment (gnat_entity))
{
gcc_assert (Present (Alignment (gnat_entity)));
align = validate_alignment (Alignment (gnat_entity), gnat_entity,
TYPE_ALIGN (gnu_type));
- gnu_type = maybe_pad_type (gnu_type, NULL_TREE, align, gnat_entity,
- "PAD", false, definition, true);
+ /* No point in changing the type if there is an address clause
+ as the final type of the object will be a reference type. */
+ if (Present (Address_Clause (gnat_entity)))
+ align = 0;
+ else
+ gnu_type
+ = maybe_pad_type (gnu_type, NULL_TREE, align, gnat_entity,
+ "PAD", false, definition, true);
}
/* If we are defining the object, see if it has a Size value and
@@ -3124,21 +3129,27 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
|| !Is_Tagged_Type (gnat_base_type)))
{
tree gnu_old_field
- = gnat_to_gnu_field_decl (Original_Record_Component
- (gnat_field));
+ = gnat_to_gnu_field_decl
+ (Original_Record_Component (gnat_field));
tree gnu_offset
- = TREE_VALUE (purpose_member (gnu_old_field,
- gnu_pos_list));
+ = TREE_VALUE
+ (purpose_member (gnu_old_field, gnu_pos_list));
tree gnu_pos = TREE_PURPOSE (gnu_offset);
tree gnu_bitpos = TREE_VALUE (TREE_VALUE (gnu_offset));
- tree gnu_field_type
- = gnat_to_gnu_type (Etype (gnat_field));
- tree gnu_size = TYPE_SIZE (gnu_field_type);
- tree gnu_new_pos = NULL_TREE;
+ tree gnu_field, gnu_field_type, gnu_size, gnu_new_pos;
unsigned int offset_align
- = tree_low_cst (TREE_PURPOSE (TREE_VALUE (gnu_offset)),
- 1);
- tree gnu_field;
+ = tree_low_cst
+ (TREE_PURPOSE (TREE_VALUE (gnu_offset)), 1);
+
+ /* If the type is the same, retrieve the GCC type from the
+ old field to take into account possible adjustments. */
+ if (Etype (gnat_field)
+ == Etype (Original_Record_Component (gnat_field)))
+ gnu_field_type = TREE_TYPE (gnu_old_field);
+ else
+ gnu_field_type = gnat_to_gnu_type (Etype (gnat_field));
+
+ gnu_size = TYPE_SIZE (gnu_field_type);
/* If there was a component clause, the field types must be
the same for the type and subtype, so copy the data from
@@ -3197,6 +3208,8 @@ gnat_to_gnu_entity (Entity_Id gnat_entity, tree gnu_expr, int definition)
TYPE_SIZE (gnu_type)))
continue;
}
+ else
+ gnu_new_pos = NULL_TREE;
gnu_field
= create_field_decl
@@ -7378,11 +7391,18 @@ set_rm_size (Uint uint_size, tree gnu_type, Entity_Id gnat_entity)
if (CONTAINS_PLACEHOLDER_P (old_size))
old_size = max_size (old_size, true);
- /* If the size of the object is a constant, the new size must not be
- smaller (the front-end checks this for scalar types). */
+ /* If the size of the object is a constant, the new size must not be smaller
+ (the front-end has verified this for scalar and packed array types). */
if (TREE_CODE (old_size) != INTEGER_CST
|| TREE_OVERFLOW (old_size)
- || (AGGREGATE_TYPE_P (gnu_type) && tree_int_cst_lt (size, old_size)))
+ || (AGGREGATE_TYPE_P (gnu_type)
+ && !(TREE_CODE (gnu_type) == ARRAY_TYPE
+ && TYPE_PACKED_ARRAY_TYPE_P (gnu_type))
+ && !(TREE_CODE (gnu_type) == RECORD_TYPE
+ && TYPE_IS_PADDING_P (gnu_type)
+ && TREE_CODE (TREE_TYPE (TYPE_FIELDS (gnu_type))) == ARRAY_TYPE
+ && TYPE_PACKED_ARRAY_TYPE_P (TREE_TYPE (TYPE_FIELDS (gnu_type))))
+ && tree_int_cst_lt (size, old_size)))
{
if (Present (gnat_attr_node))
post_error_ne_tree
diff --git a/gcc/ada/gcc-interface/lang-specs.h b/gcc/ada/gcc-interface/lang-specs.h
index c07547fbdf6..1afba3706b4 100644
--- a/gcc/ada/gcc-interface/lang-specs.h
+++ b/gcc/ada/gcc-interface/lang-specs.h
@@ -35,6 +35,7 @@
gnat1 %{I*} %{k8:-gnatk8} %{Wall:-gnatwa} %{w:-gnatws} %{!Q:-quiet}\
%{nostdinc*} %{nostdlib*}\
-dumpbase %{.adb:%b.adb}%{.ads:%b.ads}%{!.adb:%{!.ads:%b.ada}}\
+ %{c|S:%{o*:-auxbase-strip %*}%{!o*:-auxbase %b}}%{!c:%{!S:-auxbase %b}} \
%{O*} %{W*} %{w} %{p} %{pg:-p} %{a} %{d*} %{f*}\
%{coverage:-fprofile-arcs -ftest-coverage} "
#if CONFIG_DUAL_EXCEPTIONS
diff --git a/gcc/ada/gcc-interface/misc.c b/gcc/ada/gcc-interface/misc.c
index bd6b51af118..6a601bbdd12 100644
--- a/gcc/ada/gcc-interface/misc.c
+++ b/gcc/ada/gcc-interface/misc.c
@@ -661,8 +661,12 @@ gnat_get_subrange_bounds (const_tree gnu_type, tree *lowval, tree *highval)
{
tree min = TYPE_MIN_VALUE (gnu_type);
tree max = TYPE_MAX_VALUE (gnu_type);
- *lowval = TREE_CONSTANT (min) ? min : TYPE_GCC_MIN_VALUE (gnu_type);
- *highval = TREE_CONSTANT (max) ? max : TYPE_GCC_MAX_VALUE (gnu_type);
+ /* If the bounds aren't constant, use non-representable constant values
+ to get the same effect on debug info without tree sharing issues. */
+ *lowval
+ = TREE_CONSTANT (min) ? min : build_int_cstu (integer_type_node, -1);
+ *highval
+ = TREE_CONSTANT (max) ? max : build_int_cstu (integer_type_node, -1);
}
/* GNU_TYPE is a type. Determine if it should be passed by reference by
diff --git a/gcc/ada/lib.ads b/gcc/ada/lib.ads
index 50be722e1f6..145d16dff08 100644
--- a/gcc/ada/lib.ads
+++ b/gcc/ada/lib.ads
@@ -734,9 +734,9 @@ private
Table_Name => "Linker_Option_Lines");
-- The following table records the compilation switches used to compile
- -- the main unit. The table includes only switches and excludes -quiet,
- -- -dumpbase, and -o switches, since the latter are typically artifacts
- -- of the gcc/gnat1 interface.
+ -- the main unit. The table includes only switches. It excludes -o
+ -- switches as well as artifacts of the gcc/gnat1 interface such as
+ -- -quiet, -dumpbase, or -auxbase.
-- This table is set as part of the compiler argument scanning in
-- Back_End. It can also be reset in -gnatc mode from the data in an
diff --git a/gcc/ada/switch.adb b/gcc/ada/switch.adb
index f318de7f191..cb5c4d11f49 100644
--- a/gcc/ada/switch.adb
+++ b/gcc/ada/switch.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 1992-2008, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -138,6 +138,22 @@ package body Switch is
and then Switch_Chars (Ptr + 2 .. Ptr + 4) = "RTS"));
end Is_Front_End_Switch;
+ ----------------------------
+ -- Is_Internal_GCC_Switch --
+ ----------------------------
+
+ function Is_Internal_GCC_Switch (Switch_Chars : String) return Boolean is
+ First : constant Natural := Switch_Chars'First + 1;
+ Last : constant Natural := Switch_Last (Switch_Chars);
+ begin
+ return Is_Switch (Switch_Chars)
+ and then
+ (Switch_Chars (First .. Last) = "-param" or else
+ Switch_Chars (First .. Last) = "dumpbase" or else
+ Switch_Chars (First .. Last) = "auxbase-strip" or else
+ Switch_Chars (First .. Last) = "auxbase");
+ end Is_Internal_GCC_Switch;
+
---------------
-- Is_Switch --
---------------
@@ -149,6 +165,22 @@ package body Switch is
end Is_Switch;
-----------------
+ -- Switch_last --
+ -----------------
+
+ function Switch_Last (Switch_Chars : String) return Natural is
+ Last : constant Natural := Switch_Chars'Last;
+ begin
+ if Last >= Switch_Chars'First
+ and then Switch_Chars (Last) = ASCII.NUL
+ then
+ return Last - 1;
+ else
+ return Last;
+ end if;
+ end Switch_Last;
+
+ -----------------
-- Nat_Present --
-----------------
diff --git a/gcc/ada/switch.ads b/gcc/ada/switch.ads
index 9b6c7ea4552..027bf835487 100644
--- a/gcc/ada/switch.ads
+++ b/gcc/ada/switch.ads
@@ -6,7 +6,7 @@
-- --
-- S p e c --
-- --
--- Copyright (C) 1992-2008, Free Software Foundation, Inc. --
+-- Copyright (C) 1992-2009, Free Software Foundation, Inc. --
-- --
-- GNAT is free software; you can redistribute it and/or modify it under --
-- terms of the GNU General Public License as published by the Free Soft- --
@@ -72,11 +72,21 @@ package Switch is
-- Returns True iff Switch_Chars represents a front-end switch, i.e. it
-- starts with -I, -gnat or -?RTS.
-private
+ function Is_Internal_GCC_Switch (Switch_Chars : String) return Boolean;
+ -- Returns True iff Switch_Chars represents an internal GCC switch to be
+ -- followed by a single argument, such as -dumpbase, --param or -auxbase.
+ -- Eventhough passed by the "gcc" driver, these need not be stored in ALI
+ -- files and may safely be ignored by non GCC back-ends.
+
+ function Switch_Last (Switch_Chars : String) return Natural;
+ -- Index in Switch_Chars of the last relevant character for later string
+ -- comparison purposes. This is typically 'Last, minus one if there is a
+ -- terminating ASCII.NUL.
+private
-- This section contains some common routines used by the tool dependent
- -- child packages (there is one such child package for each tool that
- -- uses Switches to scan switches - Compiler/gnatbind/gnatmake/.
+ -- child packages (there is one such child package for each tool that uses
+ -- Switches to scan switches - Compiler/gnatbind/gnatmake/.
Switch_Max_Value : constant := 999_999;
-- Maximum value permitted in switches that take a value
diff --git a/gcc/alias.c b/gcc/alias.c
index 18d5b747cb0..4d42778a644 100644
--- a/gcc/alias.c
+++ b/gcc/alias.c
@@ -2373,9 +2373,6 @@ write_dependence_p (const_rtx mem, const_rtx x, int writep)
|| MEM_ALIAS_SET (mem) == ALIAS_SET_MEMORY_BARRIER)
return 1;
- if (DIFFERENT_ALIAS_SETS_P (x, mem))
- return 0;
-
/* A read from read-only memory can't conflict with read-write memory. */
if (!writep && MEM_READONLY_P (mem))
return 0;
diff --git a/gcc/bitmap.c b/gcc/bitmap.c
index 7a63eecea69..61a40ee352d 100644
--- a/gcc/bitmap.c
+++ b/gcc/bitmap.c
@@ -37,10 +37,10 @@ struct bitmap_descriptor
const char *function;
const char *file;
int line;
- int allocated;
int created;
- int peak;
- int current;
+ HOST_WIDEST_INT allocated;
+ HOST_WIDEST_INT peak;
+ HOST_WIDEST_INT current;
int nsearches;
};
@@ -2013,8 +2013,8 @@ bitmap_print (FILE *file, const_bitmap head, const char *prefix, const char *suf
/* Used to accumulate statistics about bitmap sizes. */
struct output_info
{
+ HOST_WIDEST_INT size;
int count;
- int size;
};
/* Called via htab_traverse. Output bitmap descriptor pointed out by SLOT
@@ -2034,8 +2034,9 @@ print_statistics (void **slot, void *b)
s1 = s2 + 4;
sprintf (s, "%s:%i (%s)", s1, d->line, d->function);
s[41] = 0;
- fprintf (stderr, "%-41s %6d %10d %10d %10d %10d\n", s,
- d->created, d->allocated, d->peak, d->current, d->nsearches);
+ fprintf (stderr, "%-41s %8d %15"HOST_WIDEST_INT_PRINT"d %15"
+ HOST_WIDEST_INT_PRINT"d %15"HOST_WIDEST_INT_PRINT"d %10d\n",
+ s, d->created, d->allocated, d->peak, d->current, d->nsearches);
i->size += d->allocated;
i->count += d->created;
}
@@ -2053,14 +2054,14 @@ dump_bitmap_statistics (void)
return;
fprintf (stderr, "\nBitmap Overall "
- "Allocated Peak Leak searched "
+ " Allocated Peak Leak searched "
" per search\n");
fprintf (stderr, "---------------------------------------------------------------------------------\n");
info.count = 0;
info.size = 0;
htab_traverse (bitmap_desc_hash, print_statistics, &info);
fprintf (stderr, "---------------------------------------------------------------------------------\n");
- fprintf (stderr, "%-40s %7d %10d\n",
+ fprintf (stderr, "%-40s %9d %15"HOST_WIDEST_INT_PRINT"d\n",
"Total", info.count, info.size);
fprintf (stderr, "---------------------------------------------------------------------------------\n");
#endif
diff --git a/gcc/builtins.c b/gcc/builtins.c
index 2164492d653..49aa9040f2d 100644
--- a/gcc/builtins.c
+++ b/gcc/builtins.c
@@ -13671,6 +13671,7 @@ do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
const int prec = fmt->p;
const mp_rnd_t rnd = fmt->round_towards_zero ? GMP_RNDZ : GMP_RNDN;
+ const mpc_rnd_t crnd = fmt->round_towards_zero ? MPC_RNDZZ : MPC_RNDNN;
int inexact;
mpc_t m;
@@ -13678,7 +13679,7 @@ do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
mpfr_from_real (MPC_RE(m), re, rnd);
mpfr_from_real (MPC_IM(m), im, rnd);
mpfr_clear_flags ();
- inexact = func (m, m, rnd);
+ inexact = func (m, m, crnd);
result = do_mpc_ckconv (m, type, inexact);
mpc_clear (m);
}
diff --git a/gcc/c-common.c b/gcc/c-common.c
index e5c3d0d2eee..45b4192d446 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -55,180 +55,6 @@ along with GCC; see the file COPYING3. If not see
cpp_reader *parse_in; /* Declared in c-pragma.h. */
-/* We let tm.h override the types used here, to handle trivial differences
- such as the choice of unsigned int or long unsigned int for size_t.
- When machines start needing nontrivial differences in the size type,
- it would be best to do something here to figure out automatically
- from other information what type to use. */
-
-#ifndef SIZE_TYPE
-#define SIZE_TYPE "long unsigned int"
-#endif
-
-#ifndef PID_TYPE
-#define PID_TYPE "int"
-#endif
-
-/* If GCC knows the exact uint_least16_t and uint_least32_t types from
- <stdint.h>, use them for char16_t and char32_t. Otherwise, use
- these guesses; getting the wrong type of a given width will not
- affect C++ name mangling because in C++ these are distinct types
- not typedefs. */
-
-#ifdef UINT_LEAST16_TYPE
-#define CHAR16_TYPE UINT_LEAST16_TYPE
-#else
-#define CHAR16_TYPE "short unsigned int"
-#endif
-
-#ifdef UINT_LEAST32_TYPE
-#define CHAR32_TYPE UINT_LEAST32_TYPE
-#else
-#define CHAR32_TYPE "unsigned int"
-#endif
-
-#ifndef WCHAR_TYPE
-#define WCHAR_TYPE "int"
-#endif
-
-/* WCHAR_TYPE gets overridden by -fshort-wchar. */
-#define MODIFIED_WCHAR_TYPE \
- (flag_short_wchar ? "short unsigned int" : WCHAR_TYPE)
-
-#ifndef PTRDIFF_TYPE
-#define PTRDIFF_TYPE "long int"
-#endif
-
-#ifndef WINT_TYPE
-#define WINT_TYPE "unsigned int"
-#endif
-
-#ifndef INTMAX_TYPE
-#define INTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
- ? "int" \
- : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
- ? "long int" \
- : "long long int"))
-#endif
-
-#ifndef UINTMAX_TYPE
-#define UINTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
- ? "unsigned int" \
- : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
- ? "long unsigned int" \
- : "long long unsigned int"))
-#endif
-
-/* There are no default definitions of these <stdint.h> types. */
-
-#ifndef SIG_ATOMIC_TYPE
-#define SIG_ATOMIC_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT8_TYPE
-#define INT8_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT16_TYPE
-#define INT16_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT32_TYPE
-#define INT32_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT64_TYPE
-#define INT64_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT8_TYPE
-#define UINT8_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT16_TYPE
-#define UINT16_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT32_TYPE
-#define UINT32_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT64_TYPE
-#define UINT64_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT_LEAST8_TYPE
-#define INT_LEAST8_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT_LEAST16_TYPE
-#define INT_LEAST16_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT_LEAST32_TYPE
-#define INT_LEAST32_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT_LEAST64_TYPE
-#define INT_LEAST64_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT_LEAST8_TYPE
-#define UINT_LEAST8_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT_LEAST16_TYPE
-#define UINT_LEAST16_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT_LEAST32_TYPE
-#define UINT_LEAST32_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT_LEAST64_TYPE
-#define UINT_LEAST64_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT_FAST8_TYPE
-#define INT_FAST8_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT_FAST16_TYPE
-#define INT_FAST16_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT_FAST32_TYPE
-#define INT_FAST32_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INT_FAST64_TYPE
-#define INT_FAST64_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT_FAST8_TYPE
-#define UINT_FAST8_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT_FAST16_TYPE
-#define UINT_FAST16_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT_FAST32_TYPE
-#define UINT_FAST32_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINT_FAST64_TYPE
-#define UINT_FAST64_TYPE ((const char *) NULL)
-#endif
-
-#ifndef INTPTR_TYPE
-#define INTPTR_TYPE ((const char *) NULL)
-#endif
-
-#ifndef UINTPTR_TYPE
-#define UINTPTR_TYPE ((const char *) NULL)
-#endif
-
/* The following symbols are subsumed in the c_global_trees array, and
listed here individually for documentation purposes.
@@ -1784,16 +1610,11 @@ warn_logical_operator (location_t location, enum tree_code code, tree type,
in0_p = !in0_p, in1_p = !in1_p;
/* If both expressions are the same, if we can merge the ranges, and we
- can build the range test, return it or it inverted. If one of the
- ranges is always true or always false, consider it to be the same
- expression as the other. */
- if ((lhs == 0 || rhs == 0 || operand_equal_p (lhs, rhs, 0))
+ can build the range test, return it or it inverted. */
+ if (lhs && rhs && operand_equal_p (lhs, rhs, 0)
&& merge_ranges (&in_p, &low, &high, in0_p, low0, high0,
in1_p, low1, high1)
- && 0 != (tem = build_range_check (type,
- lhs != 0 ? lhs
- : rhs != 0 ? rhs : integer_zero_node,
- in_p, low, high)))
+ && 0 != (tem = build_range_check (type, lhs, in_p, low, high)))
{
if (TREE_CODE (tem) != INTEGER_CST)
return;
@@ -9311,4 +9132,69 @@ is_typedef_decl (tree x)
&& DECL_ORIGINAL_TYPE (x) != NULL_TREE);
}
+/* The C and C++ parsers both use vectors to hold function arguments.
+ For efficiency, we keep a cache of unused vectors. This is the
+ cache. */
+
+typedef VEC(tree,gc)* tree_gc_vec;
+DEF_VEC_P(tree_gc_vec);
+DEF_VEC_ALLOC_P(tree_gc_vec,gc);
+static GTY((deletable)) VEC(tree_gc_vec,gc) *tree_vector_cache;
+
+/* Return a new vector from the cache. If the cache is empty,
+ allocate a new vector. These vectors are GC'ed, so it is OK if the
+ pointer is not released.. */
+
+VEC(tree,gc) *
+make_tree_vector (void)
+{
+ if (!VEC_empty (tree_gc_vec, tree_vector_cache))
+ return VEC_pop (tree_gc_vec, tree_vector_cache);
+ else
+ {
+ /* Passing 0 to VEC_alloc returns NULL, and our callers require
+ that we always return a non-NULL value. The vector code uses
+ 4 when growing a NULL vector, so we do too. */
+ return VEC_alloc (tree, gc, 4);
+ }
+}
+
+/* Release a vector of trees back to the cache. */
+
+void
+release_tree_vector (VEC(tree,gc) *vec)
+{
+ if (vec != NULL)
+ {
+ VEC_truncate (tree, vec, 0);
+ VEC_safe_push (tree_gc_vec, gc, tree_vector_cache, vec);
+ }
+}
+
+/* Get a new tree vector holding a single tree. */
+
+VEC(tree,gc) *
+make_tree_vector_single (tree t)
+{
+ VEC(tree,gc) *ret = make_tree_vector ();
+ VEC_quick_push (tree, ret, t);
+ return ret;
+}
+
+/* Get a new tree vector which is a copy of an existing one. */
+
+VEC(tree,gc) *
+make_tree_vector_copy (const VEC(tree,gc) *orig)
+{
+ VEC(tree,gc) *ret;
+ unsigned int ix;
+ tree t;
+
+ ret = make_tree_vector ();
+ VEC_reserve (tree, gc, ret, VEC_length (tree, orig));
+ for (ix = 0; VEC_iterate (tree, orig, ix, t); ++ix)
+ VEC_quick_push (tree, ret, t);
+ return ret;
+}
+
#include "gt-c-common.h"
diff --git a/gcc/c-common.h b/gcc/c-common.h
index c4fba4d9b0f..b17020a027e 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -1013,6 +1013,10 @@ extern void warn_for_sign_compare (location_t,
enum tree_code resultcode);
extern void set_underlying_type (tree x);
extern bool is_typedef_decl (tree x);
+extern VEC(tree,gc) *make_tree_vector (void);
+extern void release_tree_vector (VEC(tree,gc) *);
+extern VEC(tree,gc) *make_tree_vector_single (tree);
+extern VEC(tree,gc) *make_tree_vector_copy (const VEC(tree,gc) *);
/* In c-gimplify.c */
extern void c_genericize (tree);
diff --git a/gcc/c-convert.c b/gcc/c-convert.c
index 4fb680063ad..5349d7a77e8 100644
--- a/gcc/c-convert.c
+++ b/gcc/c-convert.c
@@ -86,6 +86,9 @@ convert (tree type, tree expr)
if (type == TREE_TYPE (expr))
return expr;
+ ret = targetm.convert_to_type (type, expr);
+ if (ret)
+ return ret;
STRIP_TYPE_NOPS (e);
diff --git a/gcc/c-decl.c b/gcc/c-decl.c
index c2e4533e113..eba106d6c21 100644
--- a/gcc/c-decl.c
+++ b/gcc/c-decl.c
@@ -4202,6 +4202,7 @@ grokdeclarator (const struct c_declarator *declarator,
bool bitfield = width != NULL;
tree element_type;
struct c_arg_info *arg_info = 0;
+ const char *errmsg;
tree expr_dummy;
bool expr_const_operands_dummy;
@@ -4835,6 +4836,12 @@ grokdeclarator (const struct c_declarator *declarator,
error ("type name declared as function returning an array");
type = integer_type_node;
}
+ errmsg = targetm.invalid_return_type (type);
+ if (errmsg)
+ {
+ error (errmsg);
+ type = integer_type_node;
+ }
/* Construct the function type and go to the next
inner layer of declarator. */
@@ -5381,6 +5388,7 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
{
tree parm, type, typelt;
unsigned int parmno;
+ const char *errmsg;
/* If there is a parameter of incomplete type in a definition,
this is an error. In a declaration this is valid, and a
@@ -5424,6 +5432,14 @@ grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
}
}
+ errmsg = targetm.invalid_parameter_type (type);
+ if (errmsg)
+ {
+ error (errmsg);
+ TREE_VALUE (typelt) = error_mark_node;
+ TREE_TYPE (parm) = error_mark_node;
+ }
+
if (DECL_NAME (parm) && TREE_USED (parm))
warn_if_shadowing (parm);
}
diff --git a/gcc/c-format.c b/gcc/c-format.c
index f64cb21b459..3c73564edfa 100644
--- a/gcc/c-format.c
+++ b/gcc/c-format.c
@@ -2865,7 +2865,7 @@ handle_format_attribute (tree *node, tree ARG_UNUSED (name), tree args,
}
/* If this is a custom GCC-internal format type, we have to
- initialize certain bits a runtime. */
+ initialize certain bits at runtime. */
if (info.format_type == asm_fprintf_format_type
|| info.format_type == gcc_gfc_format_type
|| info.format_type == gcc_diag_format_type
diff --git a/gcc/c-opts.c b/gcc/c-opts.c
index 967be5200a7..df6fdadf1fb 100644
--- a/gcc/c-opts.c
+++ b/gcc/c-opts.c
@@ -1073,8 +1073,6 @@ c_common_post_options (const char **pfilename)
warn_override_init = extra_warnings;
if (warn_ignored_qualifiers == -1)
warn_ignored_qualifiers = extra_warnings;
- if (warn_logical_op == -1)
- warn_logical_op = extra_warnings;
/* -Wpointer-sign is disabled by default, but it is enabled if any
of -Wall or -pedantic are given. */
diff --git a/gcc/c-parser.c b/gcc/c-parser.c
index beda817c202..0320feece40 100644
--- a/gcc/c-parser.c
+++ b/gcc/c-parser.c
@@ -921,8 +921,6 @@ static struct c_expr c_parser_expression (c_parser *);
static struct c_expr c_parser_expression_conv (c_parser *);
static VEC(tree,gc) *c_parser_expr_list (c_parser *, bool, bool,
VEC(tree,gc) **);
-static void c_parser_release_expr_list (VEC(tree,gc) *);
-static tree c_parser_vec_to_tree_list (VEC(tree,gc) *);
static void c_parser_omp_construct (c_parser *);
static void c_parser_omp_threadprivate (c_parser *);
static void c_parser_omp_barrier (c_parser *);
@@ -2889,9 +2887,9 @@ c_parser_attributes (c_parser *parser)
tree tree_list;
c_parser_consume_token (parser);
expr_list = c_parser_expr_list (parser, false, true, NULL);
- tree_list = c_parser_vec_to_tree_list (expr_list);
+ tree_list = build_tree_list_vec (expr_list);
attr_args = tree_cons (NULL_TREE, arg1, tree_list);
- c_parser_release_expr_list (expr_list);
+ release_tree_vector (expr_list);
}
}
else
@@ -2901,8 +2899,8 @@ c_parser_attributes (c_parser *parser)
else
{
expr_list = c_parser_expr_list (parser, false, true, NULL);
- attr_args = c_parser_vec_to_tree_list (expr_list);
- c_parser_release_expr_list (expr_list);
+ attr_args = build_tree_list_vec (expr_list);
+ release_tree_vector (expr_list);
}
}
attr = build_tree_list (attr_name, attr_args);
@@ -5719,8 +5717,8 @@ c_parser_postfix_expression_after_primary (c_parser *parser,
expr.original_type = NULL;
if (exprlist != NULL)
{
- c_parser_release_expr_list (exprlist);
- c_parser_release_expr_list (origtypes);
+ release_tree_vector (exprlist);
+ release_tree_vector (origtypes);
}
break;
case CPP_DOT:
@@ -5853,10 +5851,6 @@ c_parser_expression_conv (c_parser *parser)
nonempty-expr-list , assignment-expression
*/
-/* We cache two vectors, to save most allocation and deallocation. */
-static GTY((deletable)) VEC(tree,gc) *cached_expr_list_1;
-static GTY((deletable)) VEC(tree,gc) *cached_expr_list_2;
-
static VEC(tree,gc) *
c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
VEC(tree,gc) **p_orig_types)
@@ -5865,34 +5859,11 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
VEC(tree,gc) *orig_types;
struct c_expr expr;
- if (cached_expr_list_1 != NULL)
- {
- ret = cached_expr_list_1;
- cached_expr_list_1 = NULL;
- VEC_truncate (tree, ret, 0);
- }
- else if (cached_expr_list_2 != NULL)
- {
- ret = cached_expr_list_2;
- cached_expr_list_2 = NULL;
- VEC_truncate (tree, ret, 0);
- }
- else
- ret = VEC_alloc (tree, gc, 16);
-
+ ret = make_tree_vector ();
if (p_orig_types == NULL)
orig_types = NULL;
else
- {
- if (cached_expr_list_2 != NULL)
- {
- orig_types = cached_expr_list_2;
- cached_expr_list_2 = NULL;
- VEC_truncate (tree, orig_types, 0);
- }
- else
- orig_types = VEC_alloc (tree, gc, 16);
- }
+ orig_types = make_tree_vector ();
expr = c_parser_expr_no_commas (parser, NULL);
if (convert_p)
@@ -5918,37 +5889,6 @@ c_parser_expr_list (c_parser *parser, bool convert_p, bool fold_p,
*p_orig_types = orig_types;
return ret;
}
-
-/* Release a vector returned by c_parser_expr_list. */
-
-static void
-c_parser_release_expr_list (VEC(tree,gc) *vec)
-{
- if (cached_expr_list_1 == NULL)
- cached_expr_list_1 = vec;
- else if (cached_expr_list_2 == NULL)
- cached_expr_list_2 = vec;
- else
- VEC_free (tree, gc, vec);
-}
-
-/* Convert a vector, as returned by c_parser_expr_list, to a
- tree_list. */
-
-static tree
-c_parser_vec_to_tree_list (VEC(tree,gc) *vec)
-{
- tree ret = NULL_TREE;
- tree *pp = &ret;
- unsigned int i;
- tree t;
- for (i = 0; VEC_iterate (tree, vec, i, t); ++i)
- {
- *pp = build_tree_list (NULL, t);
- pp = &TREE_CHAIN (*pp);
- }
- return ret;
-}
/* Parse Objective-C-specific constructs. */
@@ -6830,9 +6770,9 @@ c_parser_objc_keywordexpr (c_parser *parser)
else
{
/* We have a comma expression, we will collapse later. */
- ret = c_parser_vec_to_tree_list (expr_list);
+ ret = build_tree_list_vec (expr_list);
}
- c_parser_release_expr_list (expr_list);
+ release_tree_vector (expr_list);
return ret;
}
diff --git a/gcc/c-typeck.c b/gcc/c-typeck.c
index 62b5ee913af..1a1b009398c 100644
--- a/gcc/c-typeck.c
+++ b/gcc/c-typeck.c
@@ -1766,6 +1766,7 @@ default_conversion (tree exp)
tree orig_exp;
tree type = TREE_TYPE (exp);
enum tree_code code = TREE_CODE (type);
+ tree promoted_type;
/* Functions and arrays have been converted during parsing. */
gcc_assert (code != FUNCTION_TYPE);
@@ -1793,6 +1794,10 @@ default_conversion (tree exp)
if (exp == error_mark_node)
return error_mark_node;
+ promoted_type = targetm.promoted_type (type);
+ if (promoted_type)
+ return convert (promoted_type, exp);
+
if (INTEGRAL_TYPE_P (type))
return perform_integral_promotions (exp);
@@ -8988,7 +8993,11 @@ build_binary_op (location_t location, enum tree_code code,
case FLOOR_MOD_EXPR:
warn_for_div_by_zero (location, op1);
- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+ if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+ common = 1;
+ else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
/* Although it would be tempting to shorten always here, that loses
on some targets, since the modulo instruction is undefined if the
diff --git a/gcc/c.opt b/gcc/c.opt
index fc34ff57f78..da1de00d23e 100644
--- a/gcc/c.opt
+++ b/gcc/c.opt
@@ -285,7 +285,7 @@ C ObjC C++ ObjC++ Warning
Warn about PCH files that are found but not used
Wlogical-op
-C ObjC C++ ObjC++ Var(warn_logical_op) Init(-1) Warning
+C ObjC C++ ObjC++ Var(warn_logical_op) Init(0) Warning
Warn when a logical operator is suspiciously always evaluating to true or false
Wlong-long
diff --git a/gcc/cfgexpand.c b/gcc/cfgexpand.c
index ab9464fdcb5..65a13de8a3d 100644
--- a/gcc/cfgexpand.c
+++ b/gcc/cfgexpand.c
@@ -2100,7 +2100,7 @@ expand_gimple_basic_block (basic_block bb)
return new_bb;
}
}
- else if (gimple_code (stmt) != GIMPLE_CHANGE_DYNAMIC_TYPE)
+ else
{
def_operand_p def_p;
tree stmt_tree;
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index 60ff1685dc9..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),
@@ -1393,11 +1394,18 @@ dump_cgraph_node (FILE *f, struct cgraph_node *node)
if (node->count)
fprintf (f, " executed "HOST_WIDEST_INT_PRINT_DEC"x",
(HOST_WIDEST_INT)node->count);
- if (node->local.inline_summary.self_insns)
- fprintf (f, " %i insns", node->local.inline_summary.self_insns);
- if (node->global.insns && node->global.insns
- != node->local.inline_summary.self_insns)
- fprintf (f, " (%i after inlining)", node->global.insns);
+ if (node->local.inline_summary.self_time)
+ fprintf (f, " %i time, %i benefit", node->local.inline_summary.self_time,
+ node->local.inline_summary.time_inlining_benefit);
+ if (node->global.time && node->global.time
+ != node->local.inline_summary.self_time)
+ fprintf (f, " (%i after inlining)", node->global.time);
+ if (node->local.inline_summary.self_size)
+ fprintf (f, " %i size, %i benefit", node->local.inline_summary.self_size,
+ node->local.inline_summary.size_inlining_benefit);
+ if (node->global.size && node->global.size
+ != node->local.inline_summary.self_size)
+ fprintf (f, " (%i after inlining)", node->global.size);
if (node->local.inline_summary.estimated_self_stack_size)
fprintf (f, " %i bytes stack usage", (int)node->local.inline_summary.estimated_self_stack_size);
if (node->global.estimated_stack_size != node->local.inline_summary.estimated_self_stack_size)
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 6f1e052756f..1f05eedf698 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -55,8 +55,14 @@ struct GTY(()) inline_summary
/* Estimated stack frame consumption by the function. */
HOST_WIDE_INT estimated_self_stack_size;
- /* Size of the function before inlining. */
- int self_insns;
+ /* Size of the function body. */
+ int self_size;
+ /* How many instructions are likely going to disappear after inlining. */
+ int size_inlining_benefit;
+ /* Estimated time spent executing the function body. */
+ int self_time;
+ /* How much time is going to be saved by inlining. */
+ int time_inlining_benefit;
};
/* Information about the function collected locally.
@@ -108,7 +114,8 @@ struct GTY(()) cgraph_global_info {
struct cgraph_node *inlined_to;
/* Estimated size of the function after inlining. */
- int insns;
+ int time;
+ int size;
/* Estimated growth after inlining. INT_MIN if not computed. */
int estimated_growth;
@@ -213,11 +220,6 @@ struct GTY((chain_next ("%h.next"), chain_prev ("%h.previous"))) cgraph_node {
unsigned alias : 1;
/* Set for nodes that was constructed and finalized by frontend. */
unsigned finalized_by_frontend : 1;
-
- /* In non-unit-at-a-time mode the function body of inline candidates is saved
- into clone before compiling so the function in original form can be
- inlined later. This pointer points to the clone. */
- tree inline_decl;
};
typedef struct cgraph_node *cgraph_node_ptr;
diff --git a/gcc/common.opt b/gcc/common.opt
index d29b0c1752e..c70639ec42d 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -1330,6 +1330,10 @@ ftree-vectorize
Common Report Var(flag_tree_vectorize) Optimization
Enable loop vectorization on trees
+ftree-slp-vectorize
+Common Report Var(flag_tree_slp_vectorize) Init(2) Optimization
+Enable basic block vectorization (SLP) on trees
+
fvect-cost-model
Common Report Var(flag_vect_cost_model) Optimization
Enable use of cost model in vectorization
diff --git a/gcc/config.gcc b/gcc/config.gcc
index 503babea088..3763bd9ed32 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -371,6 +371,12 @@ then
fi
case ${target} in
+i[34567]86-w64-*)
+ tm_file="i386/biarch32.h ${tm_file}"
+ ;;
+esac
+
+case ${target} in
i[34567]86-*-*)
if test "x$enable_cld" = xyes; then
tm_defines="${tm_defines} USE_IX86_CLD=1"
@@ -413,6 +419,7 @@ case ${target} in
extra_objs="darwin.o"
extra_gcc_objs="darwin-driver.o"
default_use_cxa_atexit=yes
+ use_gcc_stdint=wrap
case ${enable_threads} in
"" | yes | posix) thread_file='posix' ;;
esac
@@ -2869,7 +2876,7 @@ case "${target}" in
;;
mips*-*-*)
- supported_defaults="abi arch float tune divide llsc mips-plt"
+ supported_defaults="abi arch arch_32 arch_64 float tune tune_32 tune_64 divide llsc mips-plt"
case ${with_float} in
"" | soft | hard)
diff --git a/gcc/config.in b/gcc/config.in
index 76a7810f3d4..9f53173e7c9 100644
--- a/gcc/config.in
+++ b/gcc/config.in
@@ -844,6 +844,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
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 8579ce4d336..eda5ceaace9 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -2008,7 +2008,11 @@ const_ok_for_op (HOST_WIDE_INT i, enum rtx_code code)
case MINUS: /* Should only occur with (MINUS I reg) => rsb */
case XOR:
+ return 0;
+
case IOR:
+ if (TARGET_THUMB2)
+ return const_ok_for_arm (ARM_SIGN_EXTEND (~i));
return 0;
case AND:
@@ -2185,15 +2189,20 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
GEN_INT (ARM_SIGN_EXTEND (val))));
return 1;
}
+
if (remainder == 0)
{
if (reload_completed && rtx_equal_p (target, source))
return 0;
+
if (generate)
emit_constant_insn (cond,
gen_rtx_SET (VOIDmode, target, source));
return 1;
}
+
+ if (TARGET_THUMB2)
+ can_invert = 1;
break;
case AND:
@@ -2281,6 +2290,7 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
/* Calculate a few attributes that may be useful for specific
optimizations. */
+ /* Count number of leading zeros. */
for (i = 31; i >= 0; i--)
{
if ((remainder & (1 << i)) == 0)
@@ -2289,6 +2299,7 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
break;
}
+ /* Count number of leading 1's. */
for (i = 31; i >= 0; i--)
{
if ((remainder & (1 << i)) != 0)
@@ -2297,6 +2308,7 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
break;
}
+ /* Count number of trailing zero's. */
for (i = 0; i <= 31; i++)
{
if ((remainder & (1 << i)) == 0)
@@ -2305,6 +2317,7 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
break;
}
+ /* Count number of trailing 1's. */
for (i = 0; i <= 31; i++)
{
if ((remainder & (1 << i)) != 0)
@@ -2492,6 +2505,17 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
if (code == XOR)
break;
+ /* Convert.
+ x = y | constant ( which is composed of set_sign_bit_copies of leading 1s
+ and the remainder 0s for e.g. 0xfff00000)
+ x = ~(~(y ashift set_sign_bit_copies) lshiftrt set_sign_bit_copies)
+
+ This can be done in 2 instructions by using shifts with mov or mvn.
+ e.g. for
+ x = x | 0xfff00000;
+ we generate.
+ mvn r0, r0, asl #12
+ mvn r0, r0, lsr #12 */
if (set_sign_bit_copies > 8
&& (val & (-1 << (32 - set_sign_bit_copies))) == val)
{
@@ -2517,6 +2541,16 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
return 2;
}
+ /* Convert
+ x = y | constant (which has set_zero_bit_copies number of trailing ones).
+ to
+ x = ~((~y lshiftrt set_zero_bit_copies) ashift set_zero_bit_copies).
+
+ For eg. r0 = r0 | 0xfff
+ mvn r0, r0, lsr #12
+ mvn r0, r0, asl #12
+
+ */
if (set_zero_bit_copies > 8
&& (remainder & ((1 << set_zero_bit_copies) - 1)) == remainder)
{
@@ -2542,6 +2576,13 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
return 2;
}
+ /* This will never be reached for Thumb2 because orn is a valid
+ instruction. This is for Thumb1 and the ARM 32 bit cases.
+
+ x = y | constant (such that ~constant is a valid constant)
+ Transform this to
+ x = ~(~y & ~constant).
+ */
if (const_ok_for_arm (temp1 = ARM_SIGN_EXTEND (~val)))
{
if (generate)
@@ -2651,7 +2692,8 @@ arm_gen_constant (enum rtx_code code, enum machine_mode mode, rtx cond,
if (remainder & (1 << i))
num_bits_set++;
- if (code == AND || (can_invert && num_bits_set > 16))
+ if ((code == AND)
+ || (code != IOR && can_invert && num_bits_set > 16))
remainder = (~remainder) & 0xffffffff;
else if (code == PLUS && num_bits_set > 16)
remainder = (-remainder) & 0xffffffff;
diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md
index 6f4f64cf6c1..de78d2866f8 100644
--- a/gcc/config/arm/arm.md
+++ b/gcc/config/arm/arm.md
@@ -472,9 +472,9 @@
if (TARGET_THUMB1)
{
if (GET_CODE (operands[1]) != REG)
- operands[1] = force_reg (SImode, operands[1]);
+ operands[1] = force_reg (DImode, operands[1]);
if (GET_CODE (operands[2]) != REG)
- operands[2] = force_reg (SImode, operands[2]);
+ operands[2] = force_reg (DImode, operands[2]);
}
"
)
@@ -2615,11 +2615,11 @@
[(set (match_operand:SI 0 "s_register_operand" "=r,r")
(ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
(match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
- "TARGET_32BIT"
+ "TARGET_ARM"
"@
orr%?\\t%0, %1, %2
#"
- "TARGET_32BIT
+ "TARGET_ARM
&& GET_CODE (operands[2]) == CONST_INT
&& !const_ok_for_arm (INTVAL (operands[2]))"
[(clobber (const_int 0))]
@@ -2646,7 +2646,7 @@
(set (match_operand:SI 0 "arm_general_register_operand" "")
(ior:SI (match_operand:SI 1 "arm_general_register_operand" "")
(match_operand:SI 2 "const_int_operand" "")))]
- "TARGET_32BIT
+ "TARGET_ARM
&& !const_ok_for_arm (INTVAL (operands[2]))
&& const_ok_for_arm (~INTVAL (operands[2]))"
[(set (match_dup 3) (match_dup 2))
@@ -7977,7 +7977,7 @@
(define_insn "cstoresi_nltu_thumb1"
[(set (match_operand:SI 0 "s_register_operand" "=l,l")
- (neg:SI (gtu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
+ (neg:SI (ltu:SI (match_operand:SI 1 "s_register_operand" "l,*h")
(match_operand:SI 2 "thumb1_cmp_operand" "lI*h,*r"))))]
"TARGET_THUMB1"
"cmp\\t%1, %2\;sbc\\t%0, %0, %0"
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/neon.md b/gcc/config/arm/neon.md
index f4ba7e7349c..ebd2a45156f 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -862,6 +862,50 @@
(const_string "neon_mul_qqq_8_16_32_ddd_32")))))]
)
+(define_insn "*mul<mode>3add<mode>_neon"
+ [(set (match_operand:VDQ 0 "s_register_operand" "=w")
+ (plus:VDQ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
+ (match_operand:VDQ 3 "s_register_operand" "w"))
+ (match_operand:VDQ 1 "s_register_operand" "0")))]
+ "TARGET_NEON"
+ "vmla.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
+ [(set (attr "neon_type")
+ (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
+ (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
+ (const_string "neon_fp_vmla_ddd")
+ (const_string "neon_fp_vmla_qqq"))
+ (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
+ (if_then_else
+ (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
+ (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
+ (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
+ (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
+ (const_string "neon_mla_qqq_8_16")
+ (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
+)
+
+(define_insn "*mul<mode>3neg<mode>add<mode>_neon"
+ [(set (match_operand:VDQ 0 "s_register_operand" "=w")
+ (minus:VDQ (match_operand:VDQ 1 "s_register_operand" "0")
+ (mult:VDQ (match_operand:VDQ 2 "s_register_operand" "w")
+ (match_operand:VDQ 3 "s_register_operand" "w"))))]
+ "TARGET_NEON"
+ "vmls.<V_if_elem>\t%<V_reg>0, %<V_reg>2, %<V_reg>3"
+ [(set (attr "neon_type")
+ (if_then_else (ne (symbol_ref "<Is_float_mode>") (const_int 0))
+ (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
+ (const_string "neon_fp_vmla_ddd")
+ (const_string "neon_fp_vmla_qqq"))
+ (if_then_else (ne (symbol_ref "<Is_d_reg>") (const_int 0))
+ (if_then_else
+ (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
+ (const_string "neon_mla_ddd_8_16_qdd_16_8_long_32_16_long")
+ (const_string "neon_mla_ddd_32_qqd_16_ddd_32_scalar_qdd_64_32_long_scalar_qdd_64_32_long"))
+ (if_then_else (ne (symbol_ref "<Scalar_mul_8_16>") (const_int 0))
+ (const_string "neon_mla_qqq_8_16")
+ (const_string "neon_mla_qqq_32_qqd_32_scalar")))))]
+)
+
(define_insn "ior<mode>3"
[(set (match_operand:VDQ 0 "s_register_operand" "=w,w")
(ior:VDQ (match_operand:VDQ 1 "s_register_operand" "w,0")
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 14b52d0af84..eada5ca7479 100644
--- a/gcc/config/arm/thumb2.md
+++ b/gcc/config/arm/thumb2.md
@@ -57,7 +57,7 @@
[(match_operand:SI 2 "s_register_operand" "r")
(match_operand:SI 3 "const_int_operand" "M")]))
(match_operand:SI 1 "s_register_operand" "r")))]
- "TARGET_ARM"
+ "TARGET_THUMB2"
"bic%?\\t%0, %1, %2%S4"
[(set_attr "predicable" "yes")
(set_attr "shift" "2")
@@ -849,30 +849,44 @@
;; 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_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")
@@ -1162,6 +1176,71 @@
(set_attr "length" "2")]
)
+;; 16-bit encodings of "muls" and "mul<c>". We only use these when
+;; optimizing for size since "muls" is slow on all known
+;; implementations and since "mul<c>" will be generated by
+;; "*arm_mulsi3_v6" anyhow. The assembler will use a 16-bit encoding
+;; for "mul<c>" whenever possible anyhow.
+(define_peephole2
+ [(set (match_operand:SI 0 "low_register_operand" "")
+ (mult:SI (match_operand:SI 1 "low_register_operand" "")
+ (match_dup 0)))]
+ "TARGET_THUMB2 && optimize_size && peep2_regno_dead_p (0, CC_REGNUM)"
+ [(parallel
+ [(set (match_dup 0)
+ (mult:SI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+)
+
+(define_peephole2
+ [(set (match_operand:SI 0 "low_register_operand" "")
+ (mult:SI (match_dup 0)
+ (match_operand:SI 1 "low_register_operand" "")))]
+ "TARGET_THUMB2 && optimize_size && peep2_regno_dead_p (0, CC_REGNUM)"
+ [(parallel
+ [(set (match_dup 0)
+ (mult:SI (match_dup 0) (match_dup 1)))
+ (clobber (reg:CC CC_REGNUM))])]
+ ""
+)
+
+(define_insn "*thumb2_mulsi_short"
+ [(set (match_operand:SI 0 "low_register_operand" "=l")
+ (mult:SI (match_operand:SI 1 "low_register_operand" "%0")
+ (match_operand:SI 2 "low_register_operand" "l")))
+ (clobber (reg:CC CC_REGNUM))]
+ "TARGET_THUMB2 && optimize_size && reload_completed"
+ "mul%!\\t%0, %2, %0"
+ [(set_attr "predicable" "yes")
+ (set_attr "length" "2")
+ (set_attr "insn" "muls")])
+
+(define_insn "*thumb2_mulsi_short_compare0"
+ [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV
+ (mult:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "register_operand" "l"))
+ (const_int 0)))
+ (set (match_operand:SI 0 "register_operand" "=l")
+ (mult:SI (match_dup 1) (match_dup 2)))]
+ "TARGET_THUMB2 && optimize_size"
+ "muls\\t%0, %2, %0"
+ [(set_attr "length" "2")
+ (set_attr "insn" "muls")])
+
+(define_insn "*thumb2_mulsi_short_compare0_scratch"
+ [(set (reg:CC_NOOV CC_REGNUM)
+ (compare:CC_NOOV
+ (mult:SI (match_operand:SI 1 "register_operand" "%0")
+ (match_operand:SI 2 "register_operand" "l"))
+ (const_int 0)))
+ (clobber (match_scratch:SI 0 "=r"))]
+ "TARGET_THUMB2 && optimize_size"
+ "muls\\t%0, %2, %0"
+ [(set_attr "length" "2")
+ (set_attr "insn" "muls")])
+
(define_insn "*thumb2_cbz"
[(set (pc) (if_then_else
(eq (match_operand:SI 0 "s_register_operand" "l,?r")
@@ -1252,3 +1331,47 @@
(set_attr "length" "2")]
)
+(define_insn "orsi_notsi_si"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (ior:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
+ (match_operand:SI 1 "s_register_operand" "r")))]
+ "TARGET_THUMB2"
+ "orn%?\\t%0, %1, %2"
+ [(set_attr "predicable" "yes")]
+)
+
+(define_insn "*thumb_orsi_not_shiftsi_si"
+ [(set (match_operand:SI 0 "s_register_operand" "=r")
+ (ior:SI (not:SI (match_operator:SI 4 "shift_operator"
+ [(match_operand:SI 2 "s_register_operand" "r")
+ (match_operand:SI 3 "const_int_operand" "M")]))
+ (match_operand:SI 1 "s_register_operand" "r")))]
+ "TARGET_THUMB2"
+ "orn%?\\t%0, %1, %2%S4"
+ [(set_attr "predicable" "yes")
+ (set_attr "shift" "2")
+ (set_attr "type" "alu_shift")]
+)
+
+(define_insn_and_split "*thumb2_iorsi3"
+ [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
+ (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
+ (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
+ "TARGET_THUMB2"
+ "@
+ orr%?\\t%0, %1, %2
+ orn%?\\t%0, %1, #%B2
+ #"
+ "TARGET_THUMB2
+ && GET_CODE (operands[2]) == CONST_INT
+ && !(const_ok_for_arm (INTVAL (operands[2]))
+ || const_ok_for_arm (~INTVAL (operands[2])))"
+ [(clobber (const_int 0))]
+ "
+ arm_split_constant (IOR, SImode, curr_insn,
+ INTVAL (operands[2]), operands[0], operands[1], 0);
+ DONE;
+ "
+ [(set_attr "length" "4,4,16")
+ (set_attr "predicable" "yes")]
+)
diff --git a/gcc/config/avr/avr-protos.h b/gcc/config/avr/avr-protos.h
index 03b84c00049..82ef981e49d 100644
--- a/gcc/config/avr/avr-protos.h
+++ b/gcc/config/avr/avr-protos.h
@@ -2,7 +2,7 @@
Copyright (C) 2000, 2001, 2002, 2003, 2004, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
- Contributed by Denis Chertykov (denisc@overta.ru)
+ Contributed by Denis Chertykov (chertykov@gmail.com)
This file is part of GCC.
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index ed668b67495..26ba216b4e1 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -1,7 +1,7 @@
/* Subroutines for insn-output.c for ATMEL AVR micro controllers
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008,
2009 Free Software Foundation, Inc.
- Contributed by Denis Chertykov (denisc@overta.ru)
+ Contributed by Denis Chertykov (chertykov@gmail.com)
This file is part of GCC.
diff --git a/gcc/config/avr/avr.h b/gcc/config/avr/avr.h
index d431790a647..6e85bba7f6c 100644
--- a/gcc/config/avr/avr.h
+++ b/gcc/config/avr/avr.h
@@ -2,7 +2,7 @@
for ATMEL AVR at90s8515, ATmega103/103L, ATmega603/603L microcontrollers.
Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
2008, 2009 Free Software Foundation, Inc.
- Contributed by Denis Chertykov (denisc@overta.ru)
+ Contributed by Denis Chertykov (chertykov@gmail.com)
This file is part of GCC.
diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md
index 86a217dc23c..b861730287a 100644
--- a/gcc/config/avr/avr.md
+++ b/gcc/config/avr/avr.md
@@ -3,7 +3,7 @@
;; for ATMEL AVR micro controllers.
;; Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008
;; Free Software Foundation, Inc.
-;; Contributed by Denis Chertykov (denisc@overta.ru)
+;; Contributed by Denis Chertykov (chertykov@gmail.com)
;; This file is part of GCC.
diff --git a/gcc/config/avr/libgcc.S b/gcc/config/avr/libgcc.S
index b6262b338dd..07a50b20e31 100644
--- a/gcc/config/avr/libgcc.S
+++ b/gcc/config/avr/libgcc.S
@@ -1,7 +1,7 @@
/* -*- Mode: Asm -*- */
/* Copyright (C) 1998, 1999, 2000, 2007, 2008, 2009
Free Software Foundation, Inc.
- Contributed by Denis Chertykov <denisc@overta.ru>
+ Contributed by Denis Chertykov <chertykov@gmail.com>
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
diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h
index 050773fb130..f8557531454 100644
--- a/gcc/config/darwin.h
+++ b/gcc/config/darwin.h
@@ -76,6 +76,38 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#undef WCHAR_TYPE_SIZE
#define WCHAR_TYPE_SIZE 32
+#define INT8_TYPE "signed char"
+#define INT16_TYPE "short int"
+#define INT32_TYPE "int"
+#define INT64_TYPE "long long int"
+#define UINT8_TYPE "unsigned char"
+#define UINT16_TYPE "short unsigned int"
+#define UINT32_TYPE "unsigned int"
+#define UINT64_TYPE "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 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 long unsigned int"
+
+#define INT_FAST8_TYPE "signed char"
+#define INT_FAST16_TYPE "short int"
+#define INT_FAST32_TYPE "int"
+#define INT_FAST64_TYPE "long long int"
+#define UINT_FAST8_TYPE "unsigned char"
+#define UINT_FAST16_TYPE "short unsigned int"
+#define UINT_FAST32_TYPE "unsigned int"
+#define UINT_FAST64_TYPE "long long unsigned int"
+
+#define INTPTR_TYPE "long int"
+#define UINTPTR_TYPE "long unsigned int"
+
+#define SIG_ATOMIC_TYPE "int"
+
/* Default to using the NeXT-style runtime, since that's what is
pre-installed on Darwin systems. */
diff --git a/gcc/config/i386/biarch32.h b/gcc/config/i386/biarch32.h
new file mode 100644
index 00000000000..d4f186d6cb7
--- /dev/null
+++ b/gcc/config/i386/biarch32.h
@@ -0,0 +1,29 @@
+/* Make configure files to produce biarch compiler defaulting to 32bit mode.
+ This file must be included very first, while the OS specific file later
+ to overwrite otherwise wrong defaults.
+ Copyright (C) 2009 Free Software Foundation, Inc.
+ Contributed by Kai Tietz <kai.tietz@onevision.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 TARGET_64BIT_DEFAULT 0
+#define TARGET_BI_ARCH 1
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index b5258652ed2..2d0916fb36a 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -29,6 +29,7 @@
#define bit_CMPXCHG16B (1 << 13)
#define bit_SSE4_1 (1 << 19)
#define bit_SSE4_2 (1 << 20)
+#define bit_MOVBE (1 << 22)
#define bit_POPCNT (1 << 23)
#define bit_AES (1 << 25)
#define bit_XSAVE (1 << 26)
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 cb669378a43..0364beaebf4 100644
--- a/gcc/config/i386/driver-i386.c
+++ b/gcc/config/i386/driver-i386.c
@@ -378,6 +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, 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;
@@ -395,13 +398,33 @@ const char *host_detect_local_cpu (int argc, const char **argv)
__cpuid (1, eax, ebx, ecx, edx);
- /* We don't care for extended family. */
model = (eax >> 4) & 0x0f;
family = (eax >> 8) & 0x0f;
+ if (vendor == SIG_INTEL)
+ {
+ unsigned int extended_model, extended_family;
+
+ extended_model = (eax >> 12) & 0xf0;
+ extended_family = (eax >> 20) & 0xff;
+ if (family == 0x0f)
+ {
+ family += extended_family;
+ model += extended_model;
+ }
+ else if (family == 0x06)
+ model += extended_model;
+ }
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;
@@ -496,8 +519,8 @@ const char *host_detect_local_cpu (int argc, const char **argv)
break;
case PROCESSOR_PENTIUMPRO:
if (has_longmode)
- /* It is Core 2 Duo. */
- cpu = "core2";
+ /* It is Core 2 or Atom. */
+ cpu = (model == 28) ? "atom" : "core2";
else if (arch)
{
if (has_sse3)
@@ -588,6 +611,20 @@ const char *host_detect_local_cpu (int argc, const char **argv)
options = concat (options, "-mcx16 ", NULL);
if (has_lahf_lm)
options = concat (options, "-msahf ", NULL);
+ if (has_movbe)
+ 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 26c9fb8905b..841f97c4031 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1965,9 +1965,11 @@ static int ix86_isa_flags_explicit;
#define OPTION_MASK_ISA_ABM_SET \
(OPTION_MASK_ISA_ABM | OPTION_MASK_ISA_POPCNT)
+
#define OPTION_MASK_ISA_POPCNT_SET OPTION_MASK_ISA_POPCNT
#define OPTION_MASK_ISA_CX16_SET OPTION_MASK_ISA_CX16
#define OPTION_MASK_ISA_SAHF_SET OPTION_MASK_ISA_SAHF
+#define OPTION_MASK_ISA_MOVBE_SET OPTION_MASK_ISA_MOVBE
/* Define a set of ISAs which aren't available when a given ISA is
disabled. MMX and SSE ISAs are handled separately. */
@@ -2009,6 +2011,7 @@ static int ix86_isa_flags_explicit;
#define OPTION_MASK_ISA_POPCNT_UNSET OPTION_MASK_ISA_POPCNT
#define OPTION_MASK_ISA_CX16_UNSET OPTION_MASK_ISA_CX16
#define OPTION_MASK_ISA_SAHF_UNSET OPTION_MASK_ISA_SAHF
+#define OPTION_MASK_ISA_MOVBE_UNSET OPTION_MASK_ISA_MOVBE
/* Vectorization library interface and handlers. */
tree (*ix86_veclib_handler)(enum built_in_function, tree, tree) = NULL;
@@ -2299,6 +2302,19 @@ ix86_handle_option (size_t code, const char *arg ATTRIBUTE_UNUSED, int value)
}
return true;
+ case OPT_mmovbe:
+ if (value)
+ {
+ ix86_isa_flags |= OPTION_MASK_ISA_MOVBE_SET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_SET;
+ }
+ else
+ {
+ ix86_isa_flags &= ~OPTION_MASK_ISA_MOVBE_UNSET;
+ ix86_isa_flags_explicit |= OPTION_MASK_ISA_MOVBE_UNSET;
+ }
+ return true;
+
case OPT_maes:
if (value)
{
@@ -2361,6 +2377,7 @@ ix86_target_string (int isa, int flags, const char *arch, const char *tune,
{ "-mmmx", OPTION_MASK_ISA_MMX },
{ "-mabm", OPTION_MASK_ISA_ABM },
{ "-mpopcnt", OPTION_MASK_ISA_POPCNT },
+ { "-mmovbe", OPTION_MASK_ISA_MOVBE },
{ "-maes", OPTION_MASK_ISA_AES },
{ "-mpclmul", OPTION_MASK_ISA_PCLMUL },
};
@@ -2577,7 +2594,8 @@ override_options (bool main_args_p)
PTA_AES = 1 << 17,
PTA_PCLMUL = 1 << 18,
PTA_AVX = 1 << 19,
- PTA_FMA = 1 << 20
+ PTA_FMA = 1 << 20,
+ PTA_MOVBE = 1 << 21
};
static struct pta
@@ -2621,7 +2639,7 @@ override_options (bool main_args_p)
| PTA_SSSE3 | PTA_CX16},
{"atom", PROCESSOR_ATOM, CPU_ATOM,
PTA_64BIT | PTA_MMX | PTA_SSE | PTA_SSE2 | PTA_SSE3
- | PTA_SSSE3 | PTA_CX16},
+ | PTA_SSSE3 | PTA_CX16 | PTA_MOVBE},
{"geode", PROCESSOR_GEODE, CPU_GEODE,
PTA_MMX | PTA_3DNOW | PTA_3DNOW_A |PTA_PREFETCH_SSE},
{"k6", PROCESSOR_K6, CPU_K6, PTA_MMX},
@@ -2935,6 +2953,9 @@ override_options (bool main_args_p)
if (!(TARGET_64BIT && (processor_alias_table[i].flags & PTA_NO_SAHF))
&& !(ix86_isa_flags_explicit & OPTION_MASK_ISA_SAHF))
ix86_isa_flags |= OPTION_MASK_ISA_SAHF;
+ if (processor_alias_table[i].flags & PTA_MOVBE
+ && !(ix86_isa_flags_explicit & OPTION_MASK_ISA_MOVBE))
+ ix86_isa_flags |= OPTION_MASK_ISA_MOVBE;
if (processor_alias_table[i].flags & PTA_AES
&& !(ix86_isa_flags_explicit & OPTION_MASK_ISA_AES))
ix86_isa_flags |= OPTION_MASK_ISA_AES;
@@ -7408,10 +7429,12 @@ ix86_setup_frame_addresses (void)
cfun->machine->accesses_prev_frame = 1;
}
-#if (defined(HAVE_GAS_HIDDEN) && (SUPPORTS_ONE_ONLY - 0)) || TARGET_MACHO
-# define USE_HIDDEN_LINKONCE 1
-#else
-# define USE_HIDDEN_LINKONCE 0
+#ifndef USE_HIDDEN_LINKONCE
+# if (defined(HAVE_GAS_HIDDEN) && (SUPPORTS_ONE_ONLY - 0)) || TARGET_MACHO
+# define USE_HIDDEN_LINKONCE 1
+# else
+# define USE_HIDDEN_LINKONCE 0
+# endif
#endif
static int pic_labels_used;
@@ -17209,7 +17232,7 @@ counter_mode (rtx count_exp)
{
if (GET_MODE (count_exp) != VOIDmode)
return GET_MODE (count_exp);
- if (GET_CODE (count_exp) != CONST_INT)
+ if (!CONST_INT_P (count_exp))
return Pmode;
if (TARGET_64BIT && (INTVAL (count_exp) & ~0xffffffff))
return DImode;
@@ -19121,7 +19144,7 @@ ix86_expand_call (rtx retval, rtx fnaddr, rtx callarg1,
}
if (ix86_cmodel == CM_LARGE_PIC
- && GET_CODE (fnaddr) == MEM
+ && MEM_P (fnaddr)
&& GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
&& !local_symbolic_operand (XEXP (fnaddr, 0), VOIDmode))
fnaddr = gen_rtx_MEM (QImode, construct_plt_address (XEXP (fnaddr, 0)));
@@ -19304,17 +19327,23 @@ memory_address_length (rtx addr)
/* Rule of thumb:
- esp as the base always wants an index,
- - ebp as the base always wants a displacement. */
+ - ebp as the base always wants a displacement,
+ - r12 as the base always wants an index,
+ - r13 as the base always wants a displacement. */
/* Register Indirect. */
if (base && !index && !disp)
{
/* esp (for its index) and ebp (for its displacement) need
- the two-byte modrm form. */
- if (addr == stack_pointer_rtx
- || addr == arg_pointer_rtx
- || addr == frame_pointer_rtx
- || addr == hard_frame_pointer_rtx)
+ the two-byte modrm form. Similarly for r12 and r13 in 64-bit
+ code. */
+ if (REG_P (addr)
+ && (addr == arg_pointer_rtx
+ || addr == frame_pointer_rtx
+ || REGNO (addr) == SP_REG
+ || REGNO (addr) == BP_REG
+ || REGNO (addr) == R12_REG
+ || REGNO (addr) == R13_REG))
len = 1;
}
@@ -19332,16 +19361,18 @@ memory_address_length (rtx addr)
else
len = 4;
}
- /* ebp always wants a displacement. */
- else if (base == hard_frame_pointer_rtx)
+ /* ebp always wants a displacement. Similarly r13. */
+ else if (REG_P (base)
+ && (REGNO (base) == BP_REG || REGNO (base) == R13_REG))
len = 1;
/* An index requires the two-byte modrm form.... */
if (index
- /* ...like esp, which always wants an index. */
- || base == stack_pointer_rtx
+ /* ...like esp (or r12), which always wants an index. */
|| base == arg_pointer_rtx
- || base == frame_pointer_rtx)
+ || base == frame_pointer_rtx
+ || (REG_P (base)
+ && (REGNO (base) == SP_REG || REGNO (base) == R12_REG)))
len += 1;
}
@@ -19394,14 +19425,23 @@ ix86_attr_length_address_default (rtx insn)
if (get_attr_type (insn) == TYPE_LEA)
{
- rtx set = PATTERN (insn);
+ rtx set = PATTERN (insn), addr;
if (GET_CODE (set) == PARALLEL)
set = XVECEXP (set, 0, 0);
gcc_assert (GET_CODE (set) == SET);
- return memory_address_length (SET_SRC (set));
+ addr = SET_SRC (set);
+ if (TARGET_64BIT && get_attr_mode (insn) == MODE_SI)
+ {
+ if (GET_CODE (addr) == ZERO_EXTEND)
+ addr = XEXP (addr, 0);
+ if (GET_CODE (addr) == SUBREG)
+ addr = SUBREG_REG (addr);
+ }
+
+ return memory_address_length (addr);
}
extract_insn_cached (insn);
@@ -24042,7 +24082,7 @@ ix86_expand_multi_arg_builtin (enum insn_code icode, tree exp, rtx target,
if (last_arg_constant && i == nargs-1)
{
- if (GET_CODE (op) != CONST_INT)
+ if (!CONST_INT_P (op))
{
error ("last argument must be an immediate");
return gen_reg_rtx (tmode);
@@ -27187,6 +27227,7 @@ x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
}
}
+#ifdef ASM_OUTPUT_MAX_SKIP_PAD
/* We don't have exact information about the insn sizes, but we may assume
quite safely that we are informed about all 1 byte insns and memory
address sizes. This is enough to eliminate unnecessary padding in
@@ -27204,9 +27245,7 @@ min_insn_size (rtx insn)
if (GET_CODE (PATTERN (insn)) == UNSPEC_VOLATILE
&& XINT (PATTERN (insn), 1) == UNSPECV_ALIGN)
return 0;
- if (JUMP_P (insn)
- && (GET_CODE (PATTERN (insn)) == ADDR_VEC
- || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC))
+ if (JUMP_TABLE_DATA_P(insn))
return 0;
/* Important case - calls are always 5 bytes.
@@ -27237,7 +27276,7 @@ min_insn_size (rtx insn)
window. */
static void
-ix86_avoid_jump_misspredicts (void)
+ix86_avoid_jump_mispredicts (void)
{
rtx insn, start = get_insns ();
int nbytes = 0, njumps = 0;
@@ -27251,15 +27290,52 @@ ix86_avoid_jump_misspredicts (void)
The smallest offset in the page INSN can start is the case where START
ends on the offset 0. Offset of INSN is then NBYTES - sizeof (INSN).
- We add p2align to 16byte window with maxskip 17 - NBYTES + sizeof (INSN).
+ We add p2align to 16byte window with maxskip 15 - NBYTES + sizeof (INSN).
*/
- for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
+ for (insn = start; insn; insn = NEXT_INSN (insn))
{
+ int min_size;
+
+ if (LABEL_P (insn))
+ {
+ int align = label_to_alignment (insn);
+ int max_skip = label_to_max_skip (insn);
- nbytes += min_insn_size (insn);
+ if (max_skip > 15)
+ max_skip = 15;
+ /* If align > 3, only up to 16 - max_skip - 1 bytes can be
+ already in the current 16 byte page, because otherwise
+ ASM_OUTPUT_MAX_SKIP_ALIGN could skip max_skip or fewer
+ bytes to reach 16 byte boundary. */
+ if (align <= 0
+ || (align <= 3 && max_skip != (1 << align) - 1))
+ max_skip = 0;
+ if (dump_file)
+ fprintf (dump_file, "Label %i with max_skip %i\n",
+ INSN_UID (insn), max_skip);
+ if (max_skip)
+ {
+ while (nbytes + max_skip >= 16)
+ {
+ start = NEXT_INSN (start);
+ if ((JUMP_P (start)
+ && GET_CODE (PATTERN (start)) != ADDR_VEC
+ && GET_CODE (PATTERN (start)) != ADDR_DIFF_VEC)
+ || CALL_P (start))
+ njumps--, isjump = 1;
+ else
+ isjump = 0;
+ nbytes -= min_insn_size (start);
+ }
+ }
+ continue;
+ }
+
+ min_size = min_insn_size (insn);
+ nbytes += min_size;
if (dump_file)
- fprintf(dump_file, "Insn %i estimated to %i bytes\n",
- INSN_UID (insn), min_insn_size (insn));
+ fprintf (dump_file, "Insn %i estimated to %i bytes\n",
+ INSN_UID (insn), min_size);
if ((JUMP_P (insn)
&& GET_CODE (PATTERN (insn)) != ADDR_VEC
&& GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
@@ -27283,7 +27359,7 @@ ix86_avoid_jump_misspredicts (void)
gcc_assert (njumps >= 0);
if (dump_file)
fprintf (dump_file, "Interval %i to %i has %i bytes\n",
- INSN_UID (start), INSN_UID (insn), nbytes);
+ INSN_UID (start), INSN_UID (insn), nbytes);
if (njumps == 3 && isjump && nbytes < 16)
{
@@ -27292,10 +27368,11 @@ ix86_avoid_jump_misspredicts (void)
if (dump_file)
fprintf (dump_file, "Padding insn %i by %i bytes!\n",
INSN_UID (insn), padsize);
- emit_insn_before (gen_align (GEN_INT (padsize)), insn);
+ emit_insn_before (gen_pad (GEN_INT (padsize)), insn);
}
}
}
+#endif
/* AMD Athlon works faster
when RET is not destination of conditional jump or directly preceded
@@ -27359,8 +27436,10 @@ ix86_reorg (void)
{
if (TARGET_PAD_RETURNS)
ix86_pad_returns ();
+#ifdef ASM_OUTPUT_MAX_SKIP_PAD
if (TARGET_FOUR_JUMP_LIMIT)
- ix86_avoid_jump_misspredicts ();
+ ix86_avoid_jump_mispredicts ();
+#endif
}
}
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index f41ed7db665..1d7acf66efb 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -59,6 +59,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define TARGET_ABM OPTION_ISA_ABM
#define TARGET_POPCNT OPTION_ISA_POPCNT
#define TARGET_SAHF OPTION_ISA_SAHF
+#define TARGET_MOVBE OPTION_ISA_MOVBE
#define TARGET_AES OPTION_ISA_AES
#define TARGET_PCLMUL OPTION_ISA_PCLMUL
#define TARGET_CMPXCHG16B OPTION_ISA_CX16
@@ -2175,6 +2176,22 @@ do { \
#define ASM_OUTPUT_OPCODE(STREAM, PTR) \
ASM_OUTPUT_AVX_PREFIX ((STREAM), (PTR))
+/* A C statement to output to the stdio stream FILE an assembler
+ command to pad the location counter to a multiple of 1<<LOG
+ bytes if it is within MAX_SKIP bytes. */
+
+#ifdef HAVE_GAS_MAX_SKIP_P2ALIGN
+#undef ASM_OUTPUT_MAX_SKIP_PAD
+#define ASM_OUTPUT_MAX_SKIP_PAD(FILE, LOG, MAX_SKIP) \
+ if ((LOG) != 0) \
+ { \
+ if ((MAX_SKIP) == 0) \
+ fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else \
+ fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ }
+#endif
+
/* Under some conditions we need jump tables in the text section,
because the assembler cannot handle label differences between
sections. This is the case for x86_64 on Mach-O for example. */
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 198b59d2e47..dbe781deb84 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -312,6 +312,7 @@
(R9_REG 38)
(R10_REG 39)
(R11_REG 40)
+ (R12_REG 41)
(R13_REG 42)
(XMM8_REG 45)
(XMM9_REG 46)
@@ -416,7 +417,7 @@
;; 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")))
+ (and (eq_attr "unit" "sse") (eq_attr "mode" "V2DF,TI")))
(const_int 1)
(const_int 0)))
@@ -436,7 +437,9 @@
;; Set when REX opcode prefix is used.
(define_attr "prefix_rex" ""
- (cond [(and (eq_attr "mode" "DI")
+ (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"))
(const_int 1)
(and (eq_attr "mode" "QI")
@@ -446,6 +449,9 @@
(ne (symbol_ref "x86_extended_reg_mentioned_p (insn)")
(const_int 0))
(const_int 1)
+ (and (eq_attr "type" "imovx")
+ (match_operand:QI 1 "ext_QIreg_operand" ""))
+ (const_int 1)
]
(const_int 0)))
@@ -491,12 +497,13 @@
(not (match_operand 0 "memory_operand" "")))
(const_int 0)
(and (eq_attr "type" "imov")
- (ior (and (match_operand 0 "register_operand" "")
- (match_operand 1 "immediate_operand" ""))
- (ior (and (match_operand 0 "ax_reg_operand" "")
- (match_operand 1 "memory_displacement_only_operand" ""))
- (and (match_operand 0 "memory_displacement_only_operand" "")
- (match_operand 1 "ax_reg_operand" "")))))
+ (and (not (eq_attr "mode" "DI"))
+ (ior (and (match_operand 0 "register_operand" "")
+ (match_operand 1 "immediate_operand" ""))
+ (ior (and (match_operand 0 "ax_reg_operand" "")
+ (match_operand 1 "memory_displacement_only_operand" ""))
+ (and (match_operand 0 "memory_displacement_only_operand" "")
+ (match_operand 1 "ax_reg_operand" ""))))))
(const_int 0)
(and (eq_attr "type" "call")
(match_operand 0 "constant_call_address_operand" ""))
@@ -504,6 +511,9 @@
(and (eq_attr "type" "callv")
(match_operand 1 "constant_call_address_operand" ""))
(const_int 0)
+ (and (eq_attr "type" "alu,alu1,icmp,test")
+ (match_operand 0 "ax_reg_operand" ""))
+ (symbol_ref "(get_attr_length_immediate (insn) <= (get_attr_mode (insn) != MODE_QI))")
]
(const_int 1)))
@@ -2283,7 +2293,7 @@
"TARGET_64BIT"
"movz{bl|x}\t{%h1, %k0|%k0, %h1}"
[(set_attr "type" "imovx")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "SI")])
(define_insn "*movsi_extzv_1"
[(set (match_operand:SI 0 "register_operand" "=R")
@@ -2631,8 +2641,16 @@
(const_string "lea")
]
(const_string "imov")))
- (set_attr "modrm" "*,0,0,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")
- (set_attr "length_immediate" "*,4,8,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*")
+ (set (attr "modrm")
+ (if_then_else
+ (and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
+ (const_string "0")
+ (const_string "*")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "alternative" "2") (eq_attr "type" "imov"))
+ (const_string "8")
+ (const_string "*")))
(set (attr "prefix")
(if_then_else (eq_attr "alternative" "11,12,13,14,15,16")
(const_string "maybe_vex")
@@ -4101,6 +4119,7 @@
%vmovd\t{%1, %0|%0, %1}"
[(set_attr "type" "imovx,imov,mmxmov,mmxmov,ssemov,ssemov")
(set_attr "prefix" "orig,*,orig,orig,maybe_vex,maybe_vex")
+ (set_attr "prefix_0f" "0,*,*,*,*,*")
(set_attr "mode" "SI,DI,DI,DI,TI,TI")])
(define_split
@@ -4135,7 +4154,7 @@
"TARGET_64BIT"
"movz{wl|x}\t{%1, %k0|%k0, %1}"
[(set_attr "type" "imovx")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "SI")])
(define_insn "zero_extendqidi2"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -4143,7 +4162,7 @@
"TARGET_64BIT"
"movz{bl|x}\t{%1, %k0|%k0, %1}"
[(set_attr "type" "imovx")
- (set_attr "mode" "DI")])
+ (set_attr "mode" "SI")])
;; Sign extension instructions
@@ -5488,6 +5507,12 @@
[(set_attr "type" "fmov,sseicvt,sseicvt")
(set_attr "prefix" "orig,maybe_vex,maybe_vex")
(set_attr "mode" "<MODEF:MODE>")
+ (set (attr "prefix_rex")
+ (if_then_else
+ (and (eq_attr "prefix" "maybe_vex")
+ (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0)))
+ (const_string "1")
+ (const_string "*")))
(set_attr "unit" "i387,*,*")
(set_attr "athlon_decode" "*,double,direct")
(set_attr "amdfam10_decode" "*,vector,double")
@@ -5506,6 +5531,12 @@
[(set_attr "type" "fmov,sseicvt")
(set_attr "prefix" "orig,maybe_vex")
(set_attr "mode" "<MODEF:MODE>")
+ (set (attr "prefix_rex")
+ (if_then_else
+ (and (eq_attr "prefix" "maybe_vex")
+ (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0)))
+ (const_string "1")
+ (const_string "*")))
(set_attr "athlon_decode" "*,direct")
(set_attr "amdfam10_decode" "*,double")
(set_attr "fp_int_src" "true")])
@@ -5682,6 +5713,12 @@
[(set_attr "type" "sseicvt")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<MODEF:MODE>")
+ (set (attr "prefix_rex")
+ (if_then_else
+ (and (eq_attr "prefix" "maybe_vex")
+ (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0)))
+ (const_string "1")
+ (const_string "*")))
(set_attr "athlon_decode" "double,direct")
(set_attr "amdfam10_decode" "vector,double")
(set_attr "fp_int_src" "true")])
@@ -5711,6 +5748,12 @@
[(set_attr "type" "sseicvt")
(set_attr "prefix" "maybe_vex")
(set_attr "mode" "<MODEF:MODE>")
+ (set (attr "prefix_rex")
+ (if_then_else
+ (and (eq_attr "prefix" "maybe_vex")
+ (ne (symbol_ref "<SSEMODEI24:MODE>mode == DImode") (const_int 0)))
+ (const_string "1")
+ (const_string "*")))
(set_attr "athlon_decode" "direct")
(set_attr "amdfam10_decode" "double")
(set_attr "fp_int_src" "true")])
@@ -6430,6 +6473,11 @@
(const_string "incdec")
]
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "DI")])
;; Convert lea to the lea pattern to avoid flags dependency.
@@ -6494,6 +6542,11 @@
(if_then_else (match_operand:DI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "DI")])
(define_insn "*adddi_3_rex64"
@@ -6543,6 +6596,11 @@
(if_then_else (match_operand:DI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "DI")])
; For comparisons against 1, -1 and 128, we may generate better code
@@ -6590,6 +6648,11 @@
(if_then_else (match_operand:DI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "constm128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "DI")])
(define_insn "*adddi_5_rex64"
@@ -6639,6 +6702,11 @@
(if_then_else (match_operand:DI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "DI")])
@@ -6699,6 +6767,11 @@
(const_string "incdec")
]
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "SI")])
;; Convert lea to the lea pattern to avoid flags dependency.
@@ -6779,6 +6852,11 @@
(const_string "incdec")
]
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "SI")])
;; Convert lea to the lea pattern to avoid flags dependency.
@@ -6842,6 +6920,11 @@
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "SI")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
@@ -6888,6 +6971,11 @@
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "SI")])
(define_insn "*addsi_3"
@@ -6932,6 +7020,11 @@
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "SI")])
;; See comment for addsi_1_zext why we do use nonimmediate_operand
@@ -6976,6 +7069,11 @@
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "SI")])
; For comparisons against 1, -1 and 128, we may generate better code
@@ -7021,6 +7119,11 @@
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "constm128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "SI")])
(define_insn "*addsi_5"
@@ -7067,6 +7170,11 @@
(if_then_else (match_operand:SI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "SI")])
(define_expand "addhi3"
@@ -7121,6 +7229,11 @@
(if_then_else (match_operand:HI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu"))))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "HI,HI,SI")])
(define_insn "*addhi_1"
@@ -7160,6 +7273,11 @@
(if_then_else (match_operand:HI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "HI")])
(define_insn "*addhi_2"
@@ -7202,6 +7320,11 @@
(if_then_else (match_operand:HI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "HI")])
(define_insn "*addhi_3"
@@ -7241,6 +7364,11 @@
(if_then_else (match_operand:HI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "HI")])
; See comments above addsi_4 for details.
@@ -7279,6 +7407,11 @@
(if_then_else (match_operand:HI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "constm128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "SI")])
@@ -7321,6 +7454,11 @@
(if_then_else (match_operand:HI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "HI")])
(define_expand "addqi3"
@@ -7379,6 +7517,11 @@
(if_then_else (match_operand:QI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu"))))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "QI,QI,SI,SI")])
(define_insn "*addqi_1"
@@ -7425,6 +7568,11 @@
(if_then_else (match_operand:QI 2 "incdec_operand" "")
(const_string "incdec")
(const_string "alu")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (and (eq_attr "type" "alu") (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ (const_string "*")))
(set_attr "mode" "QI,QI,SI")])
(define_insn "*addqi_1_slp"
@@ -11513,6 +11661,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "DI")])
;; Convert lea to the lea pattern to avoid flags dependency.
@@ -11572,6 +11729,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "DI")])
(define_insn "*ashldi3_cconly_rex64"
@@ -11614,6 +11780,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "DI")])
(define_insn "*ashldi3_1"
@@ -11753,6 +11928,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "SI")])
;; Convert lea to the lea pattern to avoid flags dependency.
@@ -11837,6 +12021,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "SI")])
;; Convert lea to the lea pattern to avoid flags dependency.
@@ -11898,6 +12091,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "SI")])
(define_insn "*ashlsi3_cconly"
@@ -11939,6 +12141,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "SI")])
(define_insn "*ashlsi3_cmp_zext"
@@ -11981,6 +12192,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "SI")])
(define_expand "ashlhi3"
@@ -12026,6 +12246,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "HI,SI")])
(define_insn "*ashlhi3_1"
@@ -12060,6 +12289,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "HI")])
;; This pattern can't accept a variable shift count, since shifts by
@@ -12105,6 +12343,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "HI")])
(define_insn "*ashlhi3_cconly"
@@ -12146,6 +12393,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "HI")])
(define_expand "ashlqi3"
@@ -12211,6 +12467,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "QI,SI,SI")])
(define_insn "*ashlqi3_1"
@@ -12263,6 +12528,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "QI,SI")])
;; This pattern can't accept a variable shift count, since shifts by
@@ -12308,6 +12582,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "QI")])
(define_insn "*ashlqi3_cconly"
@@ -12349,6 +12632,15 @@
(const_string "alu")
]
(const_string "ishift")))
+ (set (attr "length_immediate")
+ (if_then_else
+ (ior (eq_attr "type" "alu")
+ (and (eq_attr "type" "ishift")
+ (and (match_operand 2 "const1_operand" "")
+ (ne (symbol_ref "TARGET_SHIFT1 || optimize_function_for_size_p (cfun)")
+ (const_int 0)))))
+ (const_string "0")
+ (const_string "*")))
(set_attr "mode" "QI")])
;; See comment above `ashldi3' about how this works.
@@ -12467,10 +12759,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
"sar{q}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand:DI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "DI")])
(define_insn "*ashrdi3_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
@@ -12501,10 +12791,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
"sar{q}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand:DI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "DI")])
(define_insn "*ashrdi3_one_bit_cconly_rex64"
[(set (reg FLAGS_REG)
@@ -12519,7 +12807,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, DImode, operands)"
"sar{q}\t%0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "DI")])
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
@@ -12687,10 +12976,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
"sar{l}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand:SI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*ashrsi3_1_one_bit_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -12702,7 +12989,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
"sar{l}\t%k0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*ashrsi3_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
@@ -12744,10 +13032,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
"sar{l}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand:SI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*ashrsi3_one_bit_cconly"
[(set (reg FLAGS_REG)
@@ -12761,7 +13047,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
"sar{l}\t%0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*ashrsi3_one_bit_cmp_zext"
[(set (reg FLAGS_REG)
@@ -12777,7 +13064,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, SImode, operands)"
"sar{l}\t%k0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
@@ -12843,10 +13131,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
"sar{w}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "HI")])
(define_insn "*ashrhi3_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
@@ -12876,10 +13162,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
"sar{w}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "HI")])
(define_insn "*ashrhi3_one_bit_cconly"
[(set (reg FLAGS_REG)
@@ -12893,7 +13177,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, HImode, operands)"
"sar{w}\t%0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "HI")])
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
@@ -12943,10 +13228,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
"sar{b}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
(define_insn "*ashrqi3_1_one_bit_slp"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
@@ -12958,10 +13241,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
"sar{b}\t%0"
[(set_attr "type" "ishift1")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
(define_insn "*ashrqi3_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
@@ -13004,10 +13285,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
"sar{b}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
(define_insn "*ashrqi3_one_bit_cconly"
[(set (reg FLAGS_REG)
@@ -13021,7 +13300,8 @@
&& ix86_binary_operator_ok (ASHIFTRT, QImode, operands)"
"sar{b}\t%0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
@@ -13143,10 +13423,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{q}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand:DI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "DI")])
(define_insn "*lshrdi3_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
@@ -13177,10 +13455,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{q}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand:DI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "DI")])
(define_insn "*lshrdi3_cconly_one_bit_rex64"
[(set (reg FLAGS_REG)
@@ -13195,7 +13471,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{q}\t%0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "DI")])
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
@@ -13280,10 +13557,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{l}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand:SI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*lshrsi3_1_one_bit_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -13295,7 +13570,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{l}\t%k0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*lshrsi3_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
@@ -13338,10 +13614,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{l}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand:SI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*lshrsi3_one_bit_cconly"
[(set (reg FLAGS_REG)
@@ -13355,7 +13629,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{l}\t%0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*lshrsi3_cmp_one_bit_zext"
[(set (reg FLAGS_REG)
@@ -13371,7 +13646,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{l}\t%k0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
@@ -13437,10 +13713,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{w}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "HI")])
(define_insn "*lshrhi3_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
@@ -13470,10 +13744,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{w}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand:SI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "HI")])
(define_insn "*lshrhi3_one_bit_cconly"
[(set (reg FLAGS_REG)
@@ -13487,7 +13759,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, HImode, operands)"
"shr{w}\t%0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "HI")])
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
@@ -13537,10 +13810,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
"shr{b}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
(define_insn "*lshrqi3_1_one_bit_slp"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
@@ -13551,10 +13822,8 @@
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))"
"shr{b}\t%0"
[(set_attr "type" "ishift1")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
(define_insn "*lshrqi3_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
@@ -13597,10 +13866,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
"shr{b}\t%0"
[(set_attr "type" "ishift")
- (set (attr "length")
- (if_then_else (match_operand:SI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
(define_insn "*lshrqi2_one_bit_cconly"
[(set (reg FLAGS_REG)
@@ -13614,7 +13881,8 @@
&& ix86_binary_operator_ok (LSHIFTRT, QImode, operands)"
"shr{b}\t%0"
[(set_attr "type" "ishift")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
;; This pattern can't accept a variable shift count, since shifts by
;; zero don't affect the flags. We assume that shifts by constant
@@ -13703,10 +13971,8 @@
&& ix86_binary_operator_ok (ROTATE, DImode, operands)"
"rol{q}\t%0"
[(set_attr "type" "rotate")
- (set (attr "length")
- (if_then_else (match_operand:DI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "DI")])
(define_insn "*rotldi3_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
@@ -13736,10 +14002,8 @@
&& ix86_binary_operator_ok (ROTATE, SImode, operands)"
"rol{l}\t%0"
[(set_attr "type" "rotate")
- (set (attr "length")
- (if_then_else (match_operand:SI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*rotlsi3_1_one_bit_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -13752,7 +14016,8 @@
&& ix86_binary_operator_ok (ROTATE, SImode, operands)"
"rol{l}\t%k0"
[(set_attr "type" "rotate")
- (set_attr "length" "2")])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*rotlsi3_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
@@ -13795,10 +14060,8 @@
&& ix86_binary_operator_ok (ROTATE, HImode, operands)"
"rol{w}\t%0"
[(set_attr "type" "rotate")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "HI")])
(define_insn "*rotlhi3_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
@@ -13838,10 +14101,8 @@
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))"
"rol{b}\t%0"
[(set_attr "type" "rotate1")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
(define_insn "*rotlqi3_1_one_bit"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
@@ -13852,10 +14113,8 @@
&& ix86_binary_operator_ok (ROTATE, QImode, operands)"
"rol{b}\t%0"
[(set_attr "type" "rotate")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
(define_insn "*rotlqi3_1_slp"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,qm"))
@@ -13935,10 +14194,8 @@
&& ix86_binary_operator_ok (ROTATERT, DImode, operands)"
"ror{q}\t%0"
[(set_attr "type" "rotate")
- (set (attr "length")
- (if_then_else (match_operand:DI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "DI")])
(define_insn "*rotrdi3_1_rex64"
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm,rm")
@@ -13968,10 +14225,8 @@
&& ix86_binary_operator_ok (ROTATERT, SImode, operands)"
"ror{l}\t%0"
[(set_attr "type" "rotate")
- (set (attr "length")
- (if_then_else (match_operand:SI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*rotrsi3_1_one_bit_zext"
[(set (match_operand:DI 0 "register_operand" "=r")
@@ -13984,10 +14239,8 @@
&& ix86_binary_operator_ok (ROTATERT, SImode, operands)"
"ror{l}\t%k0"
[(set_attr "type" "rotate")
- (set (attr "length")
- (if_then_else (match_operand:SI 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "SI")])
(define_insn "*rotrsi3_1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
@@ -14030,10 +14283,8 @@
&& ix86_binary_operator_ok (ROTATERT, HImode, operands)"
"ror{w}\t%0"
[(set_attr "type" "rotate")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "HI")])
(define_insn "*rotrhi3_1"
[(set (match_operand:HI 0 "nonimmediate_operand" "=rm,rm")
@@ -14073,10 +14324,8 @@
&& ix86_binary_operator_ok (ROTATERT, QImode, operands)"
"ror{b}\t%0"
[(set_attr "type" "rotate")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
(define_insn "*rotrqi3_1_one_bit_slp"
[(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm"))
@@ -14087,10 +14336,8 @@
&& (TARGET_SHIFT1 || optimize_function_for_size_p (cfun))"
"ror{b}\t%0"
[(set_attr "type" "rotate1")
- (set (attr "length")
- (if_then_else (match_operand 0 "register_operand" "")
- (const_string "2")
- (const_string "*")))])
+ (set_attr "length_immediate" "0")
+ (set_attr "mode" "QI")])
(define_insn "*rotrqi3_1"
[(set (match_operand:QI 0 "nonimmediate_operand" "=qm,qm")
@@ -14198,7 +14445,8 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
"bts{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "alu1")])
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")])
(define_insn "*btrq"
[(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
@@ -14208,7 +14456,8 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
"btr{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "alu1")])
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")])
(define_insn "*btcq"
[(set (zero_extract:DI (match_operand:DI 0 "register_operand" "+r")
@@ -14218,7 +14467,8 @@
(clobber (reg:CC FLAGS_REG))]
"TARGET_64BIT && (TARGET_USE_BT || reload_completed)"
"btc{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "alu1")])
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")])
;; Allow Nocona to avoid these instructions if a register is available.
@@ -14329,7 +14579,8 @@
(const_int 0)))]
"TARGET_64BIT && (TARGET_USE_BT || optimize_function_for_size_p (cfun))"
"bt{q}\t{%1, %0|%0, %1}"
- [(set_attr "type" "alu1")])
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")])
(define_insn "*btsi"
[(set (reg:CCC FLAGS_REG)
@@ -14341,7 +14592,8 @@
(const_int 0)))]
"TARGET_USE_BT || optimize_function_for_size_p (cfun)"
"bt{l}\t{%1, %0|%0, %1}"
- [(set_attr "type" "alu1")])
+ [(set_attr "type" "alu1")
+ (set_attr "prefix_0f" "1")])
;; Store-flag instructions.
@@ -15487,7 +15739,7 @@
(unspec [(const_int 0)] UNSPEC_REP)]
"reload_completed"
"rep\;ret"
- [(set_attr "length" "1")
+ [(set_attr "length" "2")
(set_attr "atom_unit" "jeu")
(set_attr "length_immediate" "0")
(set_attr "prefix_rep" "1")
@@ -15519,16 +15771,16 @@
(set_attr "length_immediate" "0")
(set_attr "modrm" "0")])
-;; Align to 16-byte boundary, max skip in op0. Used to avoid
+;; Pad to 16-byte boundary, max skip in op0. Used to avoid
;; branch prediction penalty for the third jump in a 16-byte
;; block on K8.
-(define_insn "align"
+(define_insn "pad"
[(unspec_volatile [(match_operand 0 "" "")] UNSPECV_ALIGN)]
""
{
-#ifdef ASM_OUTPUT_MAX_SKIP_ALIGN
- ASM_OUTPUT_MAX_SKIP_ALIGN (asm_out_file, 4, (int)INTVAL (operands[0]));
+#ifdef ASM_OUTPUT_MAX_SKIP_PAD
+ ASM_OUTPUT_MAX_SKIP_PAD (asm_out_file, 4, (int)INTVAL (operands[0]));
#else
/* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that.
The align insn is used to avoid 3 jump instructions in the row to improve
@@ -15853,7 +16105,7 @@
(bswap:SI (match_operand:SI 1 "register_operand" "")))]
""
{
- if (!TARGET_BSWAP)
+ if (!(TARGET_BSWAP || TARGET_MOVBE))
{
rtx x = operands[0];
@@ -15865,6 +16117,21 @@
}
})
+(define_insn "*bswapsi_movbe"
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,m")
+ (bswap:SI (match_operand:SI 1 "nonimmediate_operand" "0,m,r")))]
+ "TARGET_MOVBE && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ bswap\t%0
+ movbe\t{%1, %0|%0, %1}
+ movbe\t{%1, %0|%0, %1}"
+ [(set_attr "type" "*,imov,imov")
+ (set_attr "modrm" "*,1,1")
+ (set_attr "prefix_0f" "1")
+ (set_attr "prefix_extra" "*,1,1")
+ (set_attr "length" "2,*,*")
+ (set_attr "mode" "SI")])
+
(define_insn "*bswapsi_1"
[(set (match_operand:SI 0 "register_operand" "=r")
(bswap:SI (match_operand:SI 1 "register_operand" "0")))]
@@ -15893,7 +16160,29 @@
[(set_attr "length" "4")
(set_attr "mode" "HI")])
-(define_insn "bswapdi2"
+(define_expand "bswapdi2"
+ [(set (match_operand:DI 0 "register_operand" "")
+ (bswap:DI (match_operand:DI 1 "register_operand" "")))]
+ "TARGET_64BIT"
+ "")
+
+(define_insn "*bswapdi_movbe"
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,m")
+ (bswap:DI (match_operand:DI 1 "nonimmediate_operand" "0,m,r")))]
+ "TARGET_64BIT && TARGET_MOVBE
+ && !(MEM_P (operands[0]) && MEM_P (operands[1]))"
+ "@
+ bswap\t%0
+ movbe\t{%1, %0|%0, %1}
+ movbe\t{%1, %0|%0, %1}"
+ [(set_attr "type" "*,imov,imov")
+ (set_attr "modrm" "*,1,1")
+ (set_attr "prefix_0f" "1")
+ (set_attr "prefix_extra" "*,1,1")
+ (set_attr "length" "3,*,*")
+ (set_attr "mode" "DI")])
+
+(define_insn "*bswapdi_1"
[(set (match_operand:DI 0 "register_operand" "=r")
(bswap:DI (match_operand:DI 1 "register_operand" "0")))]
"TARGET_64BIT"
@@ -19365,6 +19654,7 @@
"movsb"
[(set_attr "type" "str")
(set_attr "memory" "both")
+ (set_attr "prefix_rex" "0")
(set_attr "mode" "QI")])
(define_expand "rep_mov"
@@ -19621,6 +19911,7 @@
"stosb"
[(set_attr "type" "str")
(set_attr "memory" "store")
+ (set_attr "prefix_rex" "0")
(set_attr "mode" "QI")])
(define_expand "rep_stos"
@@ -19714,6 +20005,7 @@
[(set_attr "type" "str")
(set_attr "prefix_rep" "1")
(set_attr "memory" "store")
+ (set_attr "prefix_rex" "0")
(set_attr "mode" "QI")])
(define_expand "cmpstrnsi"
@@ -19840,6 +20132,7 @@
"repz cmpsb"
[(set_attr "type" "str")
(set_attr "mode" "QI")
+ (set_attr "prefix_rex" "0")
(set_attr "prefix_rep" "1")])
;; The same, but the count is not known to not be zero.
@@ -19893,6 +20186,7 @@
"repz cmpsb"
[(set_attr "type" "str")
(set_attr "mode" "QI")
+ (set_attr "prefix_rex" "0")
(set_attr "prefix_rep" "1")])
(define_expand "strlensi"
@@ -19954,6 +20248,7 @@
"repnz scasb"
[(set_attr "type" "str")
(set_attr "mode" "QI")
+ (set_attr "prefix_rex" "0")
(set_attr "prefix_rep" "1")])
;; Peephole optimizations to clean up after cmpstrn*. This should be
@@ -20474,6 +20769,14 @@
(const_string "imov")
]
(const_string "lea")))
+ (set (attr "length_immediate")
+ (cond [(eq_attr "type" "imov")
+ (const_string "0")
+ (and (eq_attr "type" "alu")
+ (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ ]
+ (const_string "*")))
(set_attr "mode" "SI")])
(define_insn "pro_epilogue_adjust_stack_rex64"
@@ -20518,6 +20821,14 @@
(const_string "imov")
]
(const_string "lea")))
+ (set (attr "length_immediate")
+ (cond [(eq_attr "type" "imov")
+ (const_string "0")
+ (and (eq_attr "type" "alu")
+ (match_operand 2 "const128_operand" ""))
+ (const_string "1")
+ ]
+ (const_string "*")))
(set_attr "mode" "DI")])
(define_insn "pro_epilogue_adjust_stack_rex64_2"
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 6fd218f8ede..e9be268e005 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -339,6 +339,10 @@ msahf
Target Report Mask(ISA_SAHF) Var(ix86_isa_flags) VarExists Save
Support code generation of sahf instruction in 64bit x86-64 code.
+mmovbe
+Target Report Mask(ISA_MOVBE) Var(ix86_isa_flags) VarExists Save
+Support code generation of movbe instruction.
+
maes
Target Report Mask(ISA_AES) Var(ix86_isa_flags) VarExists Save
Support AES built-in functions and code generation
diff --git a/gcc/config/i386/linux.h b/gcc/config/i386/linux.h
index 229316867fd..9742b9b5ccf 100644
--- a/gcc/config/i386/linux.h
+++ b/gcc/config/i386/linux.h
@@ -1,6 +1,6 @@
/* Definitions for Intel 386 running Linux-based GNU systems with ELF format.
Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2001, 2002, 2004, 2005,
- 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Eric Youngdale.
Modified for stabs-in-ELF by H.J. Lu.
@@ -153,7 +153,9 @@ along with GCC; see the file COPYING3. If not see
fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
/* Make sure that we have at least 8 byte alignment if > 8 byte \
alignment is preferred. */ \
- if ((LOG) > 3 && (1 << (LOG)) > ((MAX_SKIP) + 1)) \
+ if ((LOG) > 3 \
+ && (1 << (LOG)) > ((MAX_SKIP) + 1) \
+ && (MAX_SKIP) >= 7) \
fprintf ((FILE), "\t.p2align 3\n"); \
} \
} \
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index 785ff5d6033..4feb86144a9 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -76,16 +76,24 @@
(and (match_code "reg")
(match_test "REGNO (op) == FLAGS_REG")))
+;; Return true if op is a QImode register operand other than
+;; %[abcd][hl].
+(define_predicate "ext_QIreg_operand"
+ (and (match_code "reg")
+ (match_test "TARGET_64BIT
+ && GET_MODE (op) == QImode
+ && REGNO (op) > BX_REG")))
+
;; Return true if op is not xmm0 register.
(define_predicate "reg_not_xmm0_operand"
(and (match_operand 0 "register_operand")
- (match_test "GET_CODE (op) != REG
+ (match_test "!REG_P (op)
|| REGNO (op) != FIRST_SSE_REG")))
;; As above, but allow nonimmediate operands.
(define_predicate "nonimm_not_xmm0_operand"
(and (match_operand 0 "nonimmediate_operand")
- (match_test "GET_CODE (op) != REG
+ (match_test "!REG_P (op)
|| REGNO (op) != FIRST_SSE_REG")))
;; Return 1 if VALUE can be stored in a sign extended immediate field.
@@ -574,6 +582,16 @@
(and (match_code "const_int")
(match_test "INTVAL (op) == 8")))
+;; Match exactly 128.
+(define_predicate "const128_operand"
+ (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")
@@ -811,7 +829,7 @@
int ok;
/* Registers and immediate operands are always "aligned". */
- if (GET_CODE (op) != MEM)
+ if (!MEM_P (op))
return 1;
/* All patterns using aligned_operand on memory operands ends up
@@ -878,6 +896,9 @@
struct ix86_address parts;
int ok;
+ if (TARGET_64BIT)
+ return 0;
+
ok = ix86_decompose_address (XEXP (op, 0), &parts);
gcc_assert (ok);
diff --git a/gcc/config/i386/sol2.h b/gcc/config/i386/sol2.h
index 1d21cd9c043..4c2dfe975cf 100644
--- a/gcc/config/i386/sol2.h
+++ b/gcc/config/i386/sol2.h
@@ -1,6 +1,6 @@
/* Target definitions for GCC for Intel 80386 running Solaris 2
Copyright (C) 1993, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
- 2004, 2007, 2008 Free Software Foundation, Inc.
+ 2004, 2007, 2008, 2009 Free Software Foundation, Inc.
Contributed by Fred Fish (fnf@cygnus.com).
This file is part of GCC.
@@ -112,3 +112,9 @@ along with GCC; see the file COPYING3. If not see
/* We do not need NT_VERSION notes. */
#undef X86_FILE_START_VERSION_DIRECTIVE
#define X86_FILE_START_VERSION_DIRECTIVE false
+
+/* Only recent versions of Solaris 11 ld properly support hidden .gnu.linkonce
+ sections, so don't use them. */
+#ifndef TARGET_GNU_LD
+#define USE_HIDDEN_LINKONCE 0
+#endif
diff --git a/gcc/config/i386/sse.md b/gcc/config/i386/sse.md
index ae23746e2a0..d705fa11cc5 100644
--- a/gcc/config/i386/sse.md
+++ b/gcc/config/i386/sse.md
@@ -11201,7 +11201,7 @@
rtx par = gen_rtx_PARALLEL (V16QImode, vs);
rtx reg = gen_reg_rtx (V16QImode);
int i;
- rtx ele = ((GET_CODE (operands[2]) == CONST_INT)
+ rtx ele = ((CONST_INT_P (operands[2]))
? GEN_INT (- INTVAL (operands[2]))
: operands[2]);
@@ -11210,7 +11210,7 @@
emit_insn (gen_vec_initv16qi (reg, par));
- if (GET_CODE (operands[2]) != CONST_INT)
+ if (!CONST_INT_P (operands[2]))
{
rtx neg = gen_reg_rtx (V16QImode);
emit_insn (gen_negv16qi2 (neg, reg));
@@ -11233,7 +11233,7 @@
rtx reg = gen_reg_rtx (V2DImode);
rtx ele;
- if (GET_CODE (operands[2]) == CONST_INT)
+ if (CONST_INT_P (operands[2]))
ele = GEN_INT (- INTVAL (operands[2]));
else if (GET_MODE (operands[2]) != DImode)
{
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-i386 b/gcc/config/i386/t-i386
index 2ecea07ab6f..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)
- $(CXX) -c $(ALL_CXXFLAGS) $(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 530ba9fe6b9..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
- $(CXX) -c $(ALL_CXXFLAGS) $(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 bff97207bc7..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
- $(CXX) -c $(ALL_CXXFLAGS) $(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/i386/x86-64.h b/gcc/config/i386/x86-64.h
index 46dcad156f8..5d6958cc4ad 100644
--- a/gcc/config/i386/x86-64.h
+++ b/gcc/config/i386/x86-64.h
@@ -74,11 +74,22 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
/* Make sure that we have at least 8 byte alignment if > 8 byte \
alignment is preferred. */ \
- if ((LOG) > 3 && (1 << (LOG)) > ((MAX_SKIP) + 1)) \
+ if ((LOG) > 3 \
+ && (1 << (LOG)) > ((MAX_SKIP) + 1) \
+ && (MAX_SKIP) >= 7) \
fprintf ((FILE), "\t.p2align 3\n"); \
} \
} \
} while (0)
+#undef ASM_OUTPUT_MAX_SKIP_PAD
+#define ASM_OUTPUT_MAX_SKIP_PAD(FILE, LOG, MAX_SKIP) \
+ if ((LOG) != 0) \
+ { \
+ if ((MAX_SKIP) == 0) \
+ fprintf ((FILE), "\t.p2align %d\n", (LOG)); \
+ else \
+ fprintf ((FILE), "\t.p2align %d,,%d\n", (LOG), (MAX_SKIP)); \
+ }
#endif
diff --git a/gcc/config/ia64/div.md b/gcc/config/ia64/div.md
index 5f9d005b3f6..583e9e3dbee 100644
--- a/gcc/config/ia64/div.md
+++ b/gcc/config/ia64/div.md
@@ -518,3 +518,281 @@
emit_insn (gen_truncrfxf2 (operands[0], q_res));
DONE;
})
+
+
+;; SQRT operations
+
+
+(define_insn "sqrt_approx_rf"
+ [(set (match_operand:RF 0 "fr_register_operand" "=f")
+ (unspec:RF [(match_operand:RF 1 "fr_reg_or_fp01_operand" "fG")]
+ UNSPEC_FR_SQRT_RECIP_APPROX_RES))
+ (set (match_operand:BI 2 "register_operand" "=c")
+ (unspec:BI [(match_dup 1)] UNSPEC_FR_SQRT_RECIP_APPROX))
+ (use (match_operand:SI 3 "const_int_operand" ""))]
+ ""
+ "frsqrta.s%3 %0, %2 = %F1"
+ [(set_attr "itanium_class" "fmisc")
+ (set_attr "predicable" "no")])
+
+(define_expand "sqrtsf2_internal_thr"
+ [(set (match_operand:SF 0 "fr_register_operand" "")
+ (sqrt:SF (match_operand:SF 1 "fr_register_operand" "")))]
+ "TARGET_INLINE_SQRT"
+{
+ rtx y = gen_reg_rtx (RFmode);
+ rtx b = gen_reg_rtx (RFmode);
+ rtx g = gen_reg_rtx (RFmode);
+ rtx e = gen_reg_rtx (RFmode);
+ rtx s = gen_reg_rtx (RFmode);
+ rtx f = gen_reg_rtx (RFmode);
+ rtx y1 = gen_reg_rtx (RFmode);
+ rtx g1 = gen_reg_rtx (RFmode);
+ rtx h = gen_reg_rtx (RFmode);
+ rtx d = gen_reg_rtx (RFmode);
+ rtx g2 = gen_reg_rtx (RFmode);
+ rtx cond = gen_reg_rtx (BImode);
+ rtx zero = CONST0_RTX (RFmode);
+ rtx one = CONST1_RTX (RFmode);
+ rtx c1 = ia64_dconst_0_5();
+ rtx c2 = ia64_dconst_0_375();
+ rtx reg_df_c1 = gen_reg_rtx (DFmode);
+ rtx reg_df_c2 = gen_reg_rtx (DFmode);
+ rtx reg_rf_c1 = gen_reg_rtx (RFmode);
+ rtx reg_rf_c2 = gen_reg_rtx (RFmode);
+ rtx status0 = CONST0_RTX (SImode);
+ rtx status1 = CONST1_RTX (SImode);
+ rtx trunc_sgl = CONST0_RTX (SImode);
+ rtx trunc_off = CONST2_RTX (SImode);
+
+ /* Put needed constants into registers. */
+ emit_insn (gen_movdf (reg_df_c1, c1));
+ emit_insn (gen_movdf (reg_df_c2, c2));
+ emit_insn (gen_extenddfrf2 (reg_rf_c1, reg_df_c1));
+ emit_insn (gen_extenddfrf2 (reg_rf_c2, reg_df_c2));
+ /* Empty conversion to put input into RFmode. */
+ emit_insn (gen_extendsfrf2 (b, operands[1]));
+ /* y = sqrt (1 / b) */
+ emit_insn (gen_sqrt_approx_rf (y, b, cond, status0));
+ /* g = b * y */
+ emit_insn (gen_mulrf3_cond (g, cond, b, y, zero, status1, trunc_off));
+ /* e = 1 - (g * y) */
+ emit_insn (gen_m2subrf4_cond (e, cond, one, g, y, zero, status1, trunc_off));
+ /* s = 0.5 + (0.375 * e) */
+ emit_insn (gen_m2addrf4_cond (s, cond, reg_rf_c1, reg_rf_c2, e, zero, status1, trunc_off));
+ /* f = y * e */
+ emit_insn (gen_mulrf3_cond (f, cond, y, e, zero, status1, trunc_off));
+ /* y1 = y + (f * s) */
+ emit_insn (gen_m2addrf4_cond (y1, cond, y, f, s, zero, status1, trunc_off));
+ /* g1 = single (b * y1) */
+ emit_insn (gen_mulrf3_cond (g1, cond, b, y1, zero, status1, trunc_sgl));
+ /* h = 0.5 * y1 */
+ emit_insn (gen_mulrf3_cond (h, cond, reg_rf_c1, y1, zero, status1, trunc_off));
+ /* d = b - g1 * g1 */
+ emit_insn (gen_m2subrf4_cond (d, cond, b, g1, g1, zero, status1, trunc_off));
+ /* g2 = single(g1 + (d * h)) */
+ emit_insn (gen_m2addrf4_cond (g2, cond, g1, d, h, y, status0, trunc_sgl));
+ /* Conversion back into SFmode. */
+ emit_insn (gen_truncrfsf2 (operands[0], g2));
+ DONE;
+})
+
+(define_expand "sqrtsf2_internal_lat"
+ [(set (match_operand:SF 0 "fr_register_operand" "")
+ (sqrt:SF (match_operand:SF 1 "fr_register_operand" "")))]
+ "TARGET_INLINE_SQRT"
+{
+ rtx y = gen_reg_rtx (RFmode);
+ rtx b = gen_reg_rtx (RFmode);
+ rtx g = gen_reg_rtx (RFmode);
+ rtx g1 = gen_reg_rtx (RFmode);
+ rtx g2 = gen_reg_rtx (RFmode);
+ rtx e = gen_reg_rtx (RFmode);
+ rtx s = gen_reg_rtx (RFmode);
+ rtx f = gen_reg_rtx (RFmode);
+ rtx f1 = gen_reg_rtx (RFmode);
+ rtx h = gen_reg_rtx (RFmode);
+ rtx h1 = gen_reg_rtx (RFmode);
+ rtx d = gen_reg_rtx (RFmode);
+ rtx cond = gen_reg_rtx (BImode);
+ rtx zero = CONST0_RTX (RFmode);
+ rtx one = CONST1_RTX (RFmode);
+ rtx c1 = ia64_dconst_0_5();
+ rtx c2 = ia64_dconst_0_375();
+ rtx reg_df_c1 = gen_reg_rtx (DFmode);
+ rtx reg_df_c2 = gen_reg_rtx (DFmode);
+ rtx reg_rf_c1 = gen_reg_rtx (RFmode);
+ rtx reg_rf_c2 = gen_reg_rtx (RFmode);
+ rtx status0 = CONST0_RTX (SImode);
+ rtx status1 = CONST1_RTX (SImode);
+ rtx trunc_sgl = CONST0_RTX (SImode);
+ rtx trunc_off = CONST2_RTX (SImode);
+
+ /* Put needed constants into registers. */
+ emit_insn (gen_movdf (reg_df_c1, c1));
+ emit_insn (gen_movdf (reg_df_c2, c2));
+ emit_insn (gen_extenddfrf2 (reg_rf_c1, reg_df_c1));
+ emit_insn (gen_extenddfrf2 (reg_rf_c2, reg_df_c2));
+ /* Empty conversion to put input into RFmode. */
+ emit_insn (gen_extendsfrf2 (b, operands[1]));
+ /* y = sqrt (1 / b) */
+ emit_insn (gen_sqrt_approx_rf (y, b, cond, status0));
+ /* g = b * y */
+ emit_insn (gen_mulrf3_cond (g, cond, b, y, zero, status1, trunc_off));
+ /* e = 1 - (g * y) */
+ emit_insn (gen_m2subrf4_cond (e, cond, one, g, y, zero, status1, trunc_off));
+ /* h = 0.5 * y */
+ emit_insn (gen_mulrf3_cond (h, cond, reg_rf_c1, y, zero, status1, trunc_off));
+ /* s = 0.5 + (0.375 * e) */
+ emit_insn (gen_m2addrf4_cond (s, cond, reg_rf_c1, reg_rf_c2, e, zero, status1, trunc_off));
+ /* f = e * g */
+ emit_insn (gen_mulrf3_cond (f, cond, e, g, zero, status1, trunc_off));
+ /* g1 = single (g + (f * s)) */
+ emit_insn (gen_m2addrf4_cond (g1, cond, g, f, s, zero, status1, trunc_sgl));
+ /* f1 = e * h */
+ emit_insn (gen_mulrf3_cond (f1, cond, e, h, zero, status1, trunc_off));
+ /* d = b - g1 * g1 */
+ emit_insn (gen_m2subrf4_cond (d, cond, b, g1, g1, zero, status1, trunc_off));
+ /* h1 = h + (f1 * s) */
+ emit_insn (gen_m2addrf4_cond (h1, cond, h, f1, s, zero, status1, trunc_off));
+ /* g2 = single(g1 + (d * h1)) */
+ emit_insn (gen_m2addrf4_cond (g2, cond, g1, d, h1, y, status0, trunc_sgl));
+ /* Conversion back into SFmode. */
+ emit_insn (gen_truncrfsf2 (operands[0], g2));
+ DONE;
+})
+
+(define_expand "sqrtdf2_internal_thr"
+ [(set (match_operand:DF 0 "fr_register_operand" "")
+ (sqrt:DF (match_operand:DF 1 "fr_register_operand" "")))]
+ "TARGET_INLINE_SQRT"
+{
+ rtx y = gen_reg_rtx (RFmode);
+ rtx b = gen_reg_rtx (RFmode);
+ rtx g = gen_reg_rtx (RFmode);
+ rtx g1 = gen_reg_rtx (RFmode);
+ rtx g2 = gen_reg_rtx (RFmode);
+ rtx g3 = gen_reg_rtx (RFmode);
+ rtx g4 = gen_reg_rtx (RFmode);
+ rtx r = gen_reg_rtx (RFmode);
+ rtx r1 = gen_reg_rtx (RFmode);
+ rtx h = gen_reg_rtx (RFmode);
+ rtx h1 = gen_reg_rtx (RFmode);
+ rtx h2 = gen_reg_rtx (RFmode);
+ rtx d = gen_reg_rtx (RFmode);
+ rtx d1 = gen_reg_rtx (RFmode);
+ rtx cond = gen_reg_rtx (BImode);
+ rtx zero = CONST0_RTX (RFmode);
+ rtx c1 = ia64_dconst_0_5();
+ rtx reg_df_c1 = gen_reg_rtx (DFmode);
+ rtx reg_rf_c1 = gen_reg_rtx (RFmode);
+ rtx status0 = CONST0_RTX (SImode);
+ rtx status1 = CONST1_RTX (SImode);
+ rtx trunc_dbl = CONST1_RTX (SImode);
+ rtx trunc_off = CONST2_RTX (SImode);
+
+ /* Put needed constants into registers. */
+ emit_insn (gen_movdf (reg_df_c1, c1));
+ emit_insn (gen_extenddfrf2 (reg_rf_c1, reg_df_c1));
+ /* Empty conversion to put input into RFmode. */
+ emit_insn (gen_extenddfrf2 (b, operands[1]));
+ /* y = sqrt (1 / b) */
+ emit_insn (gen_sqrt_approx_rf (y, b, cond, status0));
+ /* g = b * y */
+ emit_insn (gen_mulrf3_cond (g, cond, b, y, zero, status1, trunc_off));
+ /* h = 0.5 * y */
+ emit_insn (gen_mulrf3_cond (h, cond, reg_rf_c1, y, zero, status1, trunc_off));
+ /* r = 0.5 - (g * h) */
+ emit_insn (gen_m2subrf4_cond (r, cond, reg_rf_c1, g, h, zero, status1, trunc_off));
+ /* g1 = g + (g * r) */
+ emit_insn (gen_m2addrf4_cond (g1, cond, g, g, r, zero, status1, trunc_off));
+ /* h1 = h + (h * r) */
+ emit_insn (gen_m2addrf4_cond (h1, cond, h, h, r, zero, status1, trunc_off));
+ /* r1 = 0.5 - (g1 * h1) */
+ emit_insn (gen_m2subrf4_cond (r1, cond, reg_rf_c1, g1, h1, zero, status1, trunc_off));
+ /* g2 = g1 + (g1 * r1) */
+ emit_insn (gen_m2addrf4_cond (g2, cond, g1, g1, r1, zero, status1, trunc_off));
+ /* h2 = h1 + (h1 * r1) */
+ emit_insn (gen_m2addrf4_cond (h2, cond, h1, h1, r1, zero, status1, trunc_off));
+ /* d = b - (g2 * g2) */
+ emit_insn (gen_m2subrf4_cond (d, cond, b, g2, g2, zero, status1, trunc_off));
+ /* g3 = g2 + (d * h2) */
+ emit_insn (gen_m2addrf4_cond (g3, cond, g2, d, h2, zero, status1, trunc_off));
+ /* d1 = b - (g3 * g3) */
+ emit_insn (gen_m2subrf4_cond (d1, cond, b, g3, g3, zero, status1, trunc_off));
+ /* g4 = g3 + (d1 * h2) */
+ emit_insn (gen_m2addrf4_cond (g4, cond, g3, d1, h2, y, status1, trunc_dbl));
+ /* Conversion back into SFmode. */
+ emit_insn (gen_truncrfdf2 (operands[0], g4));
+ DONE;
+})
+
+(define_expand "sqrtxf2_internal"
+ [(set (match_operand:XF 0 "fr_register_operand" "")
+ (sqrt:XF (match_operand:XF 1 "fr_register_operand" "")))]
+ "TARGET_INLINE_SQRT"
+{
+ rtx y = gen_reg_rtx (RFmode);
+ rtx b = gen_reg_rtx (RFmode);
+ rtx g = gen_reg_rtx (RFmode);
+ rtx g1 = gen_reg_rtx (RFmode);
+ rtx g2 = gen_reg_rtx (RFmode);
+ rtx g3 = gen_reg_rtx (RFmode);
+ rtx g4 = gen_reg_rtx (RFmode);
+ rtx e = gen_reg_rtx (RFmode);
+ rtx e1 = gen_reg_rtx (RFmode);
+ rtx e2 = gen_reg_rtx (RFmode);
+ rtx h = gen_reg_rtx (RFmode);
+ rtx h1 = gen_reg_rtx (RFmode);
+ rtx h2 = gen_reg_rtx (RFmode);
+ rtx h3 = gen_reg_rtx (RFmode);
+ rtx d = gen_reg_rtx (RFmode);
+ rtx d1 = gen_reg_rtx (RFmode);
+ rtx cond = gen_reg_rtx (BImode);
+ rtx zero = CONST0_RTX (RFmode);
+ rtx c1 = ia64_dconst_0_5();
+ rtx reg_df_c1 = gen_reg_rtx (DFmode);
+ rtx reg_rf_c1 = gen_reg_rtx (RFmode);
+ rtx status0 = CONST0_RTX (SImode);
+ rtx status1 = CONST1_RTX (SImode);
+ rtx trunc_off = CONST2_RTX (SImode);
+
+ /* Put needed constants into registers. */
+ emit_insn (gen_movdf (reg_df_c1, c1));
+ emit_insn (gen_extenddfrf2 (reg_rf_c1, reg_df_c1));
+ /* Empty conversion to put input into RFmode. */
+ emit_insn (gen_extendxfrf2 (b, operands[1]));
+ /* y = sqrt (1 / b) */
+ emit_insn (gen_sqrt_approx_rf (y, b, cond, status0));
+ /* g = b * y */
+ emit_insn (gen_mulrf3_cond (g, cond, b, y, zero, status1, trunc_off));
+ /* h = 0.5 * y */
+ emit_insn (gen_mulrf3_cond (h, cond, reg_rf_c1, y, zero, status1, trunc_off));
+ /* e = 0.5 - (g * h) */
+ emit_insn (gen_m2subrf4_cond (e, cond, reg_rf_c1, g, h, zero, status1, trunc_off));
+ /* g1 = g + (g * e) */
+ emit_insn (gen_m2addrf4_cond (g1, cond, g, g, e, zero, status1, trunc_off));
+ /* h1 = h + (h * e) */
+ emit_insn (gen_m2addrf4_cond (h1, cond, h, h, e, zero, status1, trunc_off));
+ /* e1 = 0.5 - (g1 * h1) */
+ emit_insn (gen_m2subrf4_cond (e1, cond, reg_rf_c1, g1, h1, zero, status1, trunc_off));
+ /* g2 = g1 + (g1 * e1) */
+ emit_insn (gen_m2addrf4_cond (g2, cond, g1, g1, e1, zero, status1, trunc_off));
+ /* h2 = h1 + (h1 * e1) */
+ emit_insn (gen_m2addrf4_cond (h2, cond, h1, h1, e1, zero, status1, trunc_off));
+ /* d = b - (g2 * g2) */
+ emit_insn (gen_m2subrf4_cond (d, cond, b, g2, g2, zero, status1, trunc_off));
+ /* e2 = 0.5 - (g2 * h2) */
+ emit_insn (gen_m2subrf4_cond (e2, cond, reg_rf_c1, g2, h2, zero, status1, trunc_off));
+ /* g3 = g2 + (d * h2) */
+ emit_insn (gen_m2addrf4_cond (g3, cond, g2, d, h2, zero, status1, trunc_off));
+ /* h3 = h2 + (e2 * h2) */
+ emit_insn (gen_m2addrf4_cond (h3, cond, h2, e2, h2, zero, status1, trunc_off));
+ /* d1 = b - (g3 * g3) */
+ emit_insn (gen_m2subrf4_cond (d1, cond, b, g3, g3, zero, status1, trunc_off));
+ /* g4 = g3 + (d1 * h3) */
+ emit_insn (gen_m2addrf4_cond (g4, cond, g3, d1, h3, y, status1, trunc_off));
+ /* Conversion back into SFmode. */
+ emit_insn (gen_truncrfxf2 (operands[0], g4));
+ DONE;
+})
diff --git a/gcc/config/ia64/hpux.h b/gcc/config/ia64/hpux.h
index f7918d21aa4..e91d1340e8a 100644
--- a/gcc/config/ia64/hpux.h
+++ b/gcc/config/ia64/hpux.h
@@ -106,7 +106,7 @@ do { \
#undef TARGET_DEFAULT
#define TARGET_DEFAULT \
- (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32)
+ (MASK_DWARF2_ASM | MASK_BIG_ENDIAN | MASK_ILP32 | MASK_FUSED_MADD)
/* ??? Might not be needed anymore. */
#define MEMBER_TYPE_FORCES_BLK(FIELD, MODE) ((MODE) == TFmode)
diff --git a/gcc/config/ia64/ia64-protos.h b/gcc/config/ia64/ia64-protos.h
index 0859c7f53af..5a68854296f 100644
--- a/gcc/config/ia64/ia64-protos.h
+++ b/gcc/config/ia64/ia64-protos.h
@@ -102,3 +102,6 @@ extern void ia64_profile_hook (int);
extern void ia64_optimization_options (int, int);
extern void ia64_init_expanders (void);
+
+extern rtx ia64_dconst_0_5 (void);
+extern rtx ia64_dconst_0_375 (void);
diff --git a/gcc/config/ia64/ia64.c b/gcc/config/ia64/ia64.c
index b44f53087f3..f9b84606964 100644
--- a/gcc/config/ia64/ia64.c
+++ b/gcc/config/ia64/ia64.c
@@ -5280,12 +5280,6 @@ ia64_override_options (void)
if (TARGET_AUTO_PIC)
target_flags |= MASK_CONST_GP;
- if (TARGET_INLINE_SQRT == INL_MIN_LAT)
- {
- warning (0, "not yet implemented: latency-optimized inline square root");
- TARGET_INLINE_SQRT = INL_MAX_THR;
- }
-
ia64_flag_schedule_insns2 = flag_schedule_insns_after_reload;
flag_schedule_insns_after_reload = 0;
@@ -10571,4 +10565,33 @@ ia64_c_mode_for_suffix (char suffix)
return VOIDmode;
}
+static GTY(()) rtx ia64_dconst_0_5_rtx;
+
+rtx
+ia64_dconst_0_5 (void)
+{
+ if (! ia64_dconst_0_5_rtx)
+ {
+ REAL_VALUE_TYPE rv;
+ real_from_string (&rv, "0.5");
+ ia64_dconst_0_5_rtx = const_double_from_real_value (rv, DFmode);
+ }
+ return ia64_dconst_0_5_rtx;
+}
+
+static GTY(()) rtx ia64_dconst_0_375_rtx;
+
+rtx
+ia64_dconst_0_375 (void)
+{
+ if (! ia64_dconst_0_375_rtx)
+ {
+ REAL_VALUE_TYPE rv;
+ real_from_string (&rv, "0.375");
+ ia64_dconst_0_375_rtx = const_double_from_real_value (rv, DFmode);
+ }
+ return ia64_dconst_0_375_rtx;
+}
+
+
#include "gt-ia64.h"
diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h
index 05957ea12db..ff02f754caa 100644
--- a/gcc/config/ia64/ia64.h
+++ b/gcc/config/ia64/ia64.h
@@ -94,7 +94,7 @@ enum ia64_inline_type
/* Default target_flags if no switches are specified */
#ifndef TARGET_DEFAULT
-#define TARGET_DEFAULT (MASK_DWARF2_ASM)
+#define TARGET_DEFAULT (MASK_DWARF2_ASM | MASK_FUSED_MADD)
#endif
#ifndef TARGET_CPU_DEFAULT
diff --git a/gcc/config/ia64/ia64.md b/gcc/config/ia64/ia64.md
index e5a6d81730c..d20ae6948cf 100644
--- a/gcc/config/ia64/ia64.md
+++ b/gcc/config/ia64/ia64.md
@@ -3106,7 +3106,7 @@
(plus:SF (mult:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG"))
(match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))]
- ""
+ "TARGET_FUSED_MADD"
"fma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3115,7 +3115,7 @@
(minus:SF (mult:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:SF 2 "fr_reg_or_fp01_operand" "fG"))
(match_operand:SF 3 "fr_reg_or_fp01_operand" "fG")))]
- ""
+ "TARGET_FUSED_MADD"
"fms.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3132,7 +3132,7 @@
(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"))))]
- ""
+ "TARGET_FUSED_MADD"
"fnma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3161,21 +3161,6 @@
DONE;
})
-;; Inline square root.
-
-(define_insn "*sqrt_approx"
- [(set (match_operand:XF 0 "fr_register_operand" "=f")
- (div:XF (const_int 1)
- (unspec:XF [(match_operand:XF 2 "fr_reg_or_fp01_operand" "fG")]
- UNSPEC_FR_SQRT_RECIP_APPROX_RES)))
- (set (match_operand:BI 1 "register_operand" "=c")
- (unspec:BI [(match_dup 2)] UNSPEC_FR_SQRT_RECIP_APPROX))
- (use (match_operand:SI 3 "const_int_operand" "")) ]
- ""
- "frsqrta.s%3 %0, %1 = %2"
- [(set_attr "itanium_class" "fmisc")
- (set_attr "predicable" "no")])
-
(define_insn "setf_exp_xf"
[(set (match_operand:XF 0 "fr_register_operand" "=f")
(unspec:XF [(match_operand:DI 1 "register_operand" "r")]
@@ -3184,133 +3169,22 @@
"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 0
if (TARGET_INLINE_SQRT == INL_MIN_LAT)
insn = gen_sqrtsf2_internal_lat (operands[0], operands[1]);
else
-#else
- gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT);
-#endif
- insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
+ insn = gen_sqrtsf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
-
-;; Latency-optimized square root.
-;; FIXME: Implement.
-
-;; Throughput-optimized square root.
-
-(define_insn_and_split "sqrtsf2_internal_thr"
- [(set (match_operand:SF 0 "fr_register_operand" "=&f")
- (sqrt:SF (match_operand:SF 1 "fr_reg_or_fp01_operand" "fG")))
- ;; Register r2 in optimization guide.
- (clobber (match_scratch:DI 2 "=r"))
- ;; Register f8 in optimization guide
- (clobber (match_scratch:XF 3 "=&f"))
- ;; Register f9 in optimization guide
- (clobber (match_scratch:XF 4 "=&f"))
- ;; Register f10 in optimization guide
- (clobber (match_scratch:XF 5 "=&f"))
- ;; Register p6 in optimization guide.
- (clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_SQRT == INL_MAX_THR"
- "#"
- "&& reload_completed"
- [ ;; exponent of +1/2 in r2
- (set (match_dup 2) (const_int 65534))
- ;; +1/2 in f8
- (set (match_dup 3)
- (unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP))
- ;; Step 1
- ;; y0 = 1/sqrt(a) in f7
- (parallel [(set (match_dup 7)
- (div:XF (const_int 1)
- (unspec:XF [(match_dup 8)]
- UNSPEC_FR_SQRT_RECIP_APPROX_RES)))
- (set (match_dup 6)
- (unspec:BI [(match_dup 8)]
- UNSPEC_FR_SQRT_RECIP_APPROX))
- (use (const_int 0))])
- ;; Step 2
- ;; H0 = 1/2 * y0 in f9
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4)
- (plus:XF (mult:XF (match_dup 3) (match_dup 7))
- (match_dup 9)))
- (use (const_int 1))]))
- ;; Step 3
- ;; S0 = a * y0 in f7
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 7)
- (plus:XF (mult:XF (match_dup 8) (match_dup 7))
- (match_dup 9)))
- (use (const_int 1))]))
- ;; Step 4
- ;; d = 1/2 - S0 * H0 in f10
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 5)
- (minus:XF (match_dup 3)
- (mult:XF (match_dup 7) (match_dup 4))))
- (use (const_int 1))]))
- ;; Step 5
- ;; d' = d + 1/2 * d in f8
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 3)
- (plus:XF (mult:XF (match_dup 3) (match_dup 5))
- (match_dup 5)))
- (use (const_int 1))]))
- ;; Step 6
- ;; e = d + d * d' in f8
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 3)
- (plus:XF (mult:XF (match_dup 5) (match_dup 3))
- (match_dup 5)))
- (use (const_int 1))]))
- ;; Step 7
- ;; S1 = S0 + e * S0 in f7
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 0)
- (float_truncate:SF
- (plus:XF (mult:XF (match_dup 3) (match_dup 7))
- (match_dup 7))))
- (use (const_int 1))]))
- ;; Step 8
- ;; H1 = H0 + e * H0 in f8
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 3)
- (plus:XF (mult:XF (match_dup 3) (match_dup 4))
- (match_dup 4)))
- (use (const_int 1))]))
- ;; Step 9
- ;; d1 = a - S1 * S1 in f9
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4)
- (minus:XF (match_dup 8)
- (mult:XF (match_dup 7) (match_dup 7))))
- (use (const_int 1))]))
- ;; Step 10
- ;; S = S1 + d1 * H1 in f7
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 0)
- (float_truncate:SF
- (plus:XF (mult:XF (match_dup 4) (match_dup 3))
- (match_dup 7))))
- (use (const_int 0))]))]
-{
- /* Generate 82-bit versions of the input and output operands. */
- operands[7] = gen_rtx_REG (XFmode, REGNO (operands[0]));
- operands[8] = gen_rtx_REG (XFmode, REGNO (operands[1]));
- /* Generate required floating-point constants. */
- operands[9] = CONST0_RTX (XFmode);
-}
- [(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
@@ -3429,7 +3303,7 @@
(plus:DF (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))]
- ""
+ "TARGET_FUSED_MADD"
"fma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3439,7 +3313,7 @@
(plus:DF (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
- ""
+ "TARGET_FUSED_MADD"
"fma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3448,7 +3322,7 @@
(minus:DF (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG")))]
- ""
+ "TARGET_FUSED_MADD"
"fms.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3458,7 +3332,7 @@
(minus:DF (mult:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")
(match_operand:DF 2 "fr_reg_or_fp01_operand" "fG"))
(match_operand:DF 3 "fr_reg_or_fp01_operand" "fG"))))]
- ""
+ "TARGET_FUSED_MADD"
"fms.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3484,7 +3358,7 @@
(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"))))]
- ""
+ "TARGET_FUSED_MADD"
"fnma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3504,7 +3378,7 @@
(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")))))]
- ""
+ "TARGET_FUSED_MADD"
"fnma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3546,143 +3420,11 @@
if (TARGET_INLINE_SQRT == INL_MIN_LAT)
insn = gen_sqrtdf2_internal_lat (operands[0], operands[1]);
else
-#else
- gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT);
#endif
insn = gen_sqrtdf2_internal_thr (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
-
-;; Latency-optimized square root.
-;; FIXME: Implement.
-
-;; Throughput-optimized square root.
-
-(define_insn_and_split "sqrtdf2_internal_thr"
- [(set (match_operand:DF 0 "fr_register_operand" "=&f")
- (sqrt:DF (match_operand:DF 1 "fr_reg_or_fp01_operand" "fG")))
- ;; Register r2 in optimization guide.
- (clobber (match_scratch:DI 2 "=r"))
- ;; Register f8 in optimization guide
- (clobber (match_scratch:XF 3 "=&f"))
- ;; Register f9 in optimization guide
- (clobber (match_scratch:XF 4 "=&f"))
- ;; Register f10 in optimization guide
- (clobber (match_scratch:XF 5 "=&f"))
- ;; Register p6 in optimization guide.
- (clobber (match_scratch:BI 6 "=c"))]
- "TARGET_INLINE_SQRT == INL_MAX_THR"
- "#"
- "&& reload_completed"
- [ ;; exponent of +1/2 in r2
- (set (match_dup 2) (const_int 65534))
- ;; +1/2 in f10
- (set (match_dup 5)
- (unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP))
- ;; Step 1
- ;; y0 = 1/sqrt(a) in f7
- (parallel [(set (match_dup 7)
- (div:XF (const_int 1)
- (unspec:XF [(match_dup 8)]
- UNSPEC_FR_SQRT_RECIP_APPROX_RES)))
- (set (match_dup 6)
- (unspec:BI [(match_dup 8)]
- UNSPEC_FR_SQRT_RECIP_APPROX))
- (use (const_int 0))])
- ;; Step 2
- ;; H0 = 1/2 * y0 in f8
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 3)
- (plus:XF (mult:XF (match_dup 5) (match_dup 7))
- (match_dup 9)))
- (use (const_int 1))]))
- ;; Step 3
- ;; G0 = a * y0 in f7
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 7)
- (plus:XF (mult:XF (match_dup 8) (match_dup 7))
- (match_dup 9)))
- (use (const_int 1))]))
- ;; Step 4
- ;; r0 = 1/2 - G0 * H0 in f9
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4)
- (minus:XF (match_dup 5)
- (mult:XF (match_dup 7) (match_dup 3))))
- (use (const_int 1))]))
- ;; Step 5
- ;; H1 = H0 + r0 * H0 in f8
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 3)
- (plus:XF (mult:XF (match_dup 4) (match_dup 3))
- (match_dup 3)))
- (use (const_int 1))]))
- ;; Step 6
- ;; G1 = G0 + r0 * G0 in f7
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 7)
- (plus:XF (mult:XF (match_dup 4) (match_dup 7))
- (match_dup 7)))
- (use (const_int 1))]))
- ;; Step 7
- ;; r1 = 1/2 - G1 * H1 in f9
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4)
- (minus:XF (match_dup 5)
- (mult:XF (match_dup 7) (match_dup 3))))
- (use (const_int 1))]))
- ;; Step 8
- ;; H2 = H1 + r1 * H1 in f8
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 3)
- (plus:XF (mult:XF (match_dup 4) (match_dup 3))
- (match_dup 3)))
- (use (const_int 1))]))
- ;; Step 9
- ;; G2 = G1 + r1 * G1 in f7
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 7)
- (plus:XF (mult:XF (match_dup 4) (match_dup 7))
- (match_dup 7)))
- (use (const_int 1))]))
- ;; Step 10
- ;; d2 = a - G2 * G2 in f9
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4)
- (minus:XF (match_dup 8)
- (mult:XF (match_dup 7) (match_dup 7))))
- (use (const_int 1))]))
- ;; Step 11
- ;; G3 = G2 + d2 * H2 in f7
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 7)
- (plus:XF (mult:XF (match_dup 4) (match_dup 3))
- (match_dup 7)))
- (use (const_int 1))]))
- ;; Step 12
- ;; d3 = a - G3 * G3 in f9
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 4)
- (minus:XF (match_dup 8)
- (mult:XF (match_dup 7) (match_dup 7))))
- (use (const_int 1))]))
- ;; Step 13
- ;; S = G3 + d3 * H2 in f7
- (cond_exec (ne (match_dup 6) (const_int 0))
- (parallel [(set (match_dup 0)
- (float_truncate:DF
- (plus:XF (mult:XF (match_dup 4) (match_dup 3))
- (match_dup 7))))
- (use (const_int 0))]))]
-{
- /* Generate 82-bit versions of the input and output operands. */
- operands[7] = gen_rtx_REG (XFmode, REGNO (operands[0]));
- operands[8] = gen_rtx_REG (XFmode, REGNO (operands[1]));
- /* Generate required floating-point constants. */
- operands[9] = CONST0_RTX (XFmode);
-}
- [(set_attr "predicable" "no")])
;; ::::::::::::::::::::
;; ::
@@ -3857,7 +3599,7 @@
(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")))]
- ""
+ "TARGET_FUSED_MADD"
"fma %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3867,7 +3609,7 @@
(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"))))]
- ""
+ "TARGET_FUSED_MADD"
"fma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3877,7 +3619,7 @@
(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"))))]
- ""
+ "TARGET_FUSED_MADD"
"fma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3918,7 +3660,7 @@
(minus: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")))]
- ""
+ "TARGET_FUSED_MADD"
"fms %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3928,7 +3670,7 @@
(minus: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"))))]
- ""
+ "TARGET_FUSED_MADD"
"fms.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3938,7 +3680,7 @@
(minus: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"))))]
- ""
+ "TARGET_FUSED_MADD"
"fms.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3976,7 +3718,7 @@
(mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
)))]
- ""
+ "TARGET_FUSED_MADD"
"fnma %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3987,7 +3729,7 @@
(mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
))))]
- ""
+ "TARGET_FUSED_MADD"
"fnma.s %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -3998,7 +3740,7 @@
(mult:XF (match_operand:XF 1 "xfreg_or_fp01_operand" "fG")
(match_operand:XF 2 "xfreg_or_fp01_operand" "fG")
))))]
- ""
+ "TARGET_FUSED_MADD"
"fnma.d %0 = %F1, %F2, %F3"
[(set_attr "itanium_class" "fmac")])
@@ -4056,163 +3798,11 @@
"TARGET_INLINE_SQRT"
{
rtx insn;
-#if 0
- if (TARGET_INLINE_SQRT == INL_MIN_LAT)
- insn = gen_sqrtxf2_internal_lat (operands[0], operands[1]);
- else
-#else
- gcc_assert (TARGET_INLINE_SQRT != INL_MIN_LAT);
-#endif
- insn = gen_sqrtxf2_internal_thr (operands[0], operands[1]);
+ insn = gen_sqrtxf2_internal (operands[0], operands[1]);
emit_insn (insn);
DONE;
})
-;; Latency-optimized square root.
-;; FIXME: Implement.
-
-;; Throughput-optimized square root.
-
-(define_insn_and_split "sqrtxf2_internal_thr"
- [(set (match_operand:XF 0 "fr_register_operand" "=&f")
- (sqrt:XF (match_operand:XF 1 "fr_reg_or_fp01_operand" "fG")))
- ;; Register r2 in optimization guide.
- (clobber (match_scratch:DI 2 "=r"))
- ;; Register f8 in optimization guide
- (clobber (match_scratch:XF 3 "=&f"))
- ;; Register f9 in optimization guide
- (clobber (match_scratch:XF 4 "=&f"))
- ;; Register f10 in optimization guide
- (clobber (match_scratch:XF 5 "=&f"))
- ;; Register f11 in optimization guide
- (clobber (match_scratch:XF 6 "=&f"))
- ;; Register p6 in optimization guide.
- (clobber (match_scratch:BI 7 "=c"))]
- "TARGET_INLINE_SQRT == INL_MAX_THR"
- "#"
- "&& reload_completed"
- [ ;; exponent of +1/2 in r2
- (set (match_dup 2) (const_int 65534))
- ;; +1/2 in f8. The Intel manual mistakenly specifies f10.
- (set (match_dup 3)
- (unspec:XF [(match_dup 2)] UNSPEC_SETF_EXP))
- ;; Step 1
- ;; y0 = 1/sqrt(a) in f7
- (parallel [(set (match_dup 8)
- (div:XF (const_int 1)
- (unspec:XF [(match_dup 9)]
- UNSPEC_FR_SQRT_RECIP_APPROX_RES)))
- (set (match_dup 7)
- (unspec:BI [(match_dup 9)]
- UNSPEC_FR_SQRT_RECIP_APPROX))
- (use (const_int 0))])
- ;; Step 2
- ;; H0 = 1/2 * y0 in f9
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 4)
- (plus:XF (mult:XF (match_dup 3) (match_dup 8))
- (match_dup 10)))
- (use (const_int 1))]))
- ;; Step 3
- ;; S0 = a * y0 in f7
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 8)
- (plus:XF (mult:XF (match_dup 9) (match_dup 8))
- (match_dup 10)))
- (use (const_int 1))]))
- ;; Step 4
- ;; d0 = 1/2 - S0 * H0 in f10
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 5)
- (minus:XF (match_dup 3)
- (mult:XF (match_dup 8) (match_dup 4))))
- (use (const_int 1))]))
- ;; Step 5
- ;; H1 = H0 + d0 * H0 in f9
- (cond_exec (ne (match_dup 7) (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))]))
- ;; Step 6
- ;; S1 = S0 + d0 * S0 in f7
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 8)
- (plus:XF (mult:XF (match_dup 5) (match_dup 8))
- (match_dup 8)))
- (use (const_int 1))]))
- ;; Step 7
- ;; d1 = 1/2 - S1 * H1 in f10
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 5)
- (minus:XF (match_dup 3)
- (mult:XF (match_dup 8) (match_dup 4))))
- (use (const_int 1))]))
- ;; Step 8
- ;; H2 = H1 + d1 * H1 in f9
- (cond_exec (ne (match_dup 7) (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))]))
- ;; Step 9
- ;; S2 = S1 + d1 * S1 in f7
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 8)
- (plus:XF (mult:XF (match_dup 5) (match_dup 8))
- (match_dup 8)))
- (use (const_int 1))]))
- ;; Step 10
- ;; d2 = 1/2 - S2 * H2 in f10
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 5)
- (minus:XF (match_dup 3)
- (mult:XF (match_dup 8) (match_dup 4))))
- (use (const_int 1))]))
- ;; Step 11
- ;; e2 = a - S2 * S2 in f8
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 3)
- (minus:XF (match_dup 9)
- (mult:XF (match_dup 8) (match_dup 8))))
- (use (const_int 1))]))
- ;; Step 12
- ;; S3 = S2 + e2 * H2 in f7
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 8)
- (plus:XF (mult:XF (match_dup 3) (match_dup 4))
- (match_dup 8)))
- (use (const_int 1))]))
- ;; Step 13
- ;; H3 = H2 + d2 * H2 in f9
- (cond_exec (ne (match_dup 7) (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))]))
- ;; Step 14
- ;; e3 = a - S3 * S3 in f8
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 3)
- (minus:XF (match_dup 9)
- (mult:XF (match_dup 8) (match_dup 8))))
- (use (const_int 1))]))
- ;; Step 15
- ;; S = S3 + e3 * H3 in f7
- (cond_exec (ne (match_dup 7) (const_int 0))
- (parallel [(set (match_dup 0)
- (plus:XF (mult:XF (match_dup 3) (match_dup 4))
- (match_dup 8)))
- (use (const_int 0))]))]
-{
- /* Generate 82-bit versions of the input and output operands. */
- operands[8] = gen_rtx_REG (XFmode, REGNO (operands[0]));
- operands[9] = gen_rtx_REG (XFmode, REGNO (operands[1]));
- /* Generate required floating-point constants. */
- operands[10] = CONST0_RTX (XFmode);
-}
- [(set_attr "predicable" "no")])
-
;; ??? frcpa works like cmp.foo.unc.
(define_insn "*recip_approx"
diff --git a/gcc/config/ia64/ia64.opt b/gcc/config/ia64/ia64.opt
index 79198585719..27cd5b1eaeb 100644
--- a/gcc/config/ia64/ia64.opt
+++ b/gcc/config/ia64/ia64.opt
@@ -178,4 +178,8 @@ msel-sched-dont-check-control-spec
Target Report Var(mflag_sel_sched_dont_check_control_spec) Init(0)
Don't generate checks for control speculation in selective scheduling
+mfused-madd
+Target Report Mask(FUSED_MADD)
+Enable fused multiply/add and multiply/subtract instructions
+
; This comment is to ensure we retain the blank line above.
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/ia64/vect.md b/gcc/config/ia64/vect.md
index 994ec90b2eb..6b42c920d9d 100644
--- a/gcc/config/ia64/vect.md
+++ b/gcc/config/ia64/vect.md
@@ -915,6 +915,11 @@
{
rtvec v = gen_rtvec (2, CONST1_RTX (SFmode), CONST1_RTX (SFmode));
operands[3] = force_reg (V2SFmode, gen_rtx_CONST_VECTOR (V2SFmode, v));
+ if (!TARGET_FUSED_MADD)
+ {
+ emit_insn (gen_fpma (operands[0], operands[1], operands[3], operands[2]));
+ DONE;
+ }
})
;; The split condition here could be combine_completed, if we had such.
@@ -960,6 +965,11 @@
{
rtvec v = gen_rtvec (2, CONST1_RTX (SFmode), CONST1_RTX (SFmode));
operands[3] = force_reg (V2SFmode, gen_rtx_CONST_VECTOR (V2SFmode, v));
+ if (!TARGET_FUSED_MADD)
+ {
+ emit_insn (gen_fpms (operands[0], operands[1], operands[3], operands[2]));
+ DONE;
+ }
})
;; The split condition here could be combine_completed, if we had such.
@@ -1001,7 +1011,7 @@
"fpmpy %0 = %1, %2"
[(set_attr "itanium_class" "fmac")])
-(define_insn "*fpma"
+(define_insn "fpma"
[(set (match_operand:V2SF 0 "fr_register_operand" "=f")
(plus:V2SF
(mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
@@ -1011,7 +1021,7 @@
"fpma %0 = %1, %2, %3"
[(set_attr "itanium_class" "fmac")])
-(define_insn "*fpms"
+(define_insn "fpms"
[(set (match_operand:V2SF 0 "fr_register_operand" "=f")
(minus:V2SF
(mult:V2SF (match_operand:V2SF 1 "fr_register_operand" "f")
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 d98c74e7061..df8ff83dd19 100644
--- a/gcc/config/m32r/m32r.c
+++ b/gcc/config/m32r/m32r.c
@@ -492,7 +492,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);
@@ -567,7 +567,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
@@ -636,7 +636,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. */
@@ -738,7 +738,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));
@@ -778,7 +778,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));
@@ -885,7 +885,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;
@@ -898,7 +898,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;
@@ -975,7 +975,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)
@@ -1029,12 +1029,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);
@@ -1053,7 +1053,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]);
@@ -1067,7 +1067,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. */
@@ -1111,7 +1111,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),
@@ -1658,9 +1658,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;
}
@@ -1782,7 +1782,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;
@@ -1861,7 +1861,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));
@@ -1929,14 +1929,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");
@@ -1945,9 +1945,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
@@ -1967,7 +1967,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'))
@@ -1975,7 +1975,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;
@@ -2049,7 +2049,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)
@@ -2061,7 +2061,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");
@@ -2069,7 +2069,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;
@@ -2096,21 +2096,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))]);
@@ -2160,13 +2160,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)
@@ -2176,7 +2176,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. */
@@ -2191,7 +2191,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
@@ -2205,7 +2205,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);
@@ -2240,8 +2240,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)));
}
@@ -2261,7 +2261,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));
@@ -2295,13 +2295,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;
@@ -2365,7 +2365,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 861eab766d5..f0474e64888 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/m68k/constraints.md b/gcc/config/m68k/constraints.md
index 8be423788d6..a4885cda6ca 100644
--- a/gcc/config/m68k/constraints.md
+++ b/gcc/config/m68k/constraints.md
@@ -129,6 +129,11 @@
(and (match_code "const_int")
(match_test "ival < -0x8000 || ival > 0x7FFF")))
+(define_constraint "Cu"
+ "16-bit offset for wrapped symbols"
+ (and (match_code "const")
+ (match_test "m68k_unwrap_symbol (op, false) != op")))
+
(define_constraint "CQ"
"Integers valid for mvq."
(and (match_code "const_int")
diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h
index 1b91709e45d..08f8a91e691 100644
--- a/gcc/config/m68k/m68k-protos.h
+++ b/gcc/config/m68k/m68k-protos.h
@@ -59,13 +59,20 @@ extern bool m68k_illegitimate_symbolic_constant_p (rtx);
extern bool m68k_matches_q_p (rtx);
extern bool m68k_matches_u_p (rtx);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
+extern rtx m68k_legitimize_tls_address (rtx);
+extern bool m68k_tls_reference_p (rtx, bool);
extern int valid_dbcc_comparison_p_2 (rtx, enum machine_mode);
extern rtx m68k_libcall_value (enum machine_mode);
extern rtx m68k_function_value (const_tree, const_tree);
extern int emit_move_sequence (rtx *, enum machine_mode, rtx);
extern bool m68k_movem_pattern_p (rtx, rtx, HOST_WIDE_INT, bool);
extern const char *m68k_output_movem (rtx *, rtx, HOST_WIDE_INT, bool);
+extern void m68k_final_prescan_insn (rtx, rtx *, int);
+/* Functions from m68k.c used in constraints.md. */
+extern rtx m68k_unwrap_symbol (rtx, bool);
+
+/* Functions from m68k.c used in genattrtab. */
#ifdef HAVE_ATTR_cpu
extern enum attr_cpu m68k_sched_cpu;
extern enum attr_mac m68k_sched_mac;
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index 3e463023625..ec371e56a01 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
/* ??? Need to add a dependency between m68k.o and sched-int.h. */
#include "sched-int.h"
#include "insn-codes.h"
+#include "ggc.h"
enum reg_class regno_reg_class[] =
{
@@ -144,11 +145,13 @@ static tree m68k_handle_fndecl_attribute (tree *node, tree name,
static void m68k_compute_frame_layout (void);
static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
static bool m68k_ok_for_sibcall_p (tree, tree);
+static bool m68k_tls_symbol_p (rtx);
static rtx m68k_legitimize_address (rtx, rtx, enum machine_mode);
static bool m68k_rtx_costs (rtx, int, int, int *, bool);
#if M68K_HONOR_TARGET_STRICT_ALIGNMENT
static bool m68k_return_in_memory (const_tree, const_tree);
#endif
+static void m68k_output_dwarf_dtprel (FILE *, int, rtx) ATTRIBUTE_UNUSED;
/* Specify the identification number of the library being built */
@@ -249,6 +252,14 @@ const char *m68k_library_id_string = "_current_shared_library_a5_offset_";
#define TARGET_RETURN_IN_MEMORY m68k_return_in_memory
#endif
+#ifdef HAVE_AS_TLS
+#undef TARGET_HAVE_TLS
+#define TARGET_HAVE_TLS (true)
+
+#undef TARGET_ASM_OUTPUT_DWARF_DTPREL
+#define TARGET_ASM_OUTPUT_DWARF_DTPREL m68k_output_dwarf_dtprel
+#endif
+
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P m68k_legitimate_address_p
@@ -1149,8 +1160,7 @@ m68k_expand_prologue (void)
current_frame.reg_mask, true, true));
}
- if (flag_pic
- && !TARGET_SEP_DATA
+ if (!TARGET_SEP_DATA
&& crtl->uses_pic_offset_table)
insn = emit_insn (gen_load_got (pic_offset_table_rtx));
}
@@ -1432,9 +1442,12 @@ m68k_legitimize_sibcall_address (rtx x)
However, if REG is a broken-out memory address or multiplication,
nothing needs to be done because REG can certainly go in an address reg. */
-rtx
+static rtx
m68k_legitimize_address (rtx x, rtx oldx, enum machine_mode mode)
{
+ if (m68k_tls_symbol_p (x))
+ return m68k_legitimize_tls_address (x);
+
if (GET_CODE (x) == PLUS)
{
int ch = (x) != (oldx);
@@ -1853,7 +1866,7 @@ m68k_illegitimate_symbolic_constant_p (rtx x)
&& !offset_within_block_p (base, INTVAL (offset)))
return true;
}
- return false;
+ return m68k_tls_reference_p (x, false);
}
/* Return true if X is a legitimate constant address that can reach
@@ -1881,7 +1894,7 @@ m68k_legitimate_constant_address_p (rtx x, unsigned int reach, bool strict_p)
return false;
}
- return true;
+ return !m68k_tls_reference_p (x, false);
}
/* Return true if X is a LABEL_REF for a jump table. Assume that unplaced
@@ -1948,15 +1961,17 @@ m68k_decompose_address (enum machine_mode mode, rtx x,
/* Check for GOT loads. These are (bd,An,Xn) addresses if
TARGET_68020 && flag_pic == 2, otherwise they are (d16,An)
addresses. */
- if (flag_pic
- && GET_CODE (x) == PLUS
- && XEXP (x, 0) == pic_offset_table_rtx
- && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF
- || GET_CODE (XEXP (x, 1)) == LABEL_REF))
+ if (GET_CODE (x) == PLUS
+ && XEXP (x, 0) == pic_offset_table_rtx)
{
- address->base = XEXP (x, 0);
- address->offset = XEXP (x, 1);
- return true;
+ /* As we are processing a PLUS, do not unwrap RELOC32 symbols --
+ they are invalid in this context. */
+ if (m68k_unwrap_symbol (XEXP (x, 1), false) != XEXP (x, 1))
+ {
+ address->base = XEXP (x, 0);
+ address->offset = XEXP (x, 1);
+ return true;
+ }
}
/* The ColdFire FPU only accepts addressing modes 2-5. */
@@ -2101,6 +2116,243 @@ m68k_matches_u_p (rtx x)
&& !address.index);
}
+/* Return GOT pointer. */
+
+static rtx
+m68k_get_gp (void)
+{
+ if (pic_offset_table_rtx == NULL_RTX)
+ pic_offset_table_rtx = gen_rtx_REG (Pmode, PIC_REG);
+
+ crtl->uses_pic_offset_table = 1;
+
+ return pic_offset_table_rtx;
+}
+
+/* M68K relocations, used to distinguish GOT and TLS relocations in UNSPEC
+ wrappers. */
+enum m68k_reloc { RELOC_GOT, RELOC_TLSGD, RELOC_TLSLDM, RELOC_TLSLDO,
+ RELOC_TLSIE, RELOC_TLSLE };
+
+#define TLS_RELOC_P(RELOC) ((RELOC) != RELOC_GOT)
+
+/* Wrap symbol X into unspec representing relocation RELOC.
+ BASE_REG - register that should be added to the result.
+ TEMP_REG - if non-null, temporary register. */
+
+static rtx
+m68k_wrap_symbol (rtx x, enum m68k_reloc reloc, rtx base_reg, rtx temp_reg)
+{
+ bool use_x_p;
+
+ use_x_p = (base_reg == pic_offset_table_rtx) ? TARGET_XGOT : TARGET_XTLS;
+
+ if (TARGET_COLDFIRE && use_x_p)
+ /* When compiling with -mx{got, tls} switch the code will look like this:
+
+ move.l <X>@<RELOC>,<TEMP_REG>
+ add.l <BASE_REG>,<TEMP_REG> */
+ {
+ /* Wrap X in UNSPEC_??? to tip m68k_output_addr_const_extra
+ to put @RELOC after reference. */
+ x = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (reloc)),
+ UNSPEC_RELOC32);
+ x = gen_rtx_CONST (Pmode, x);
+
+ if (temp_reg == NULL)
+ {
+ gcc_assert (can_create_pseudo_p ());
+ temp_reg = gen_reg_rtx (Pmode);
+ }
+
+ emit_move_insn (temp_reg, x);
+ emit_insn (gen_addsi3 (temp_reg, temp_reg, base_reg));
+ x = temp_reg;
+ }
+ else
+ {
+ x = gen_rtx_UNSPEC (Pmode, gen_rtvec (2, x, GEN_INT (reloc)),
+ UNSPEC_RELOC16);
+ x = gen_rtx_CONST (Pmode, x);
+
+ x = gen_rtx_PLUS (Pmode, base_reg, x);
+ }
+
+ return x;
+}
+
+/* Helper for m68k_unwrap_symbol.
+ Also, if unwrapping was successful (that is if (ORIG != <return value>)),
+ sets *RELOC_PTR to relocation type for the symbol. */
+
+static rtx
+m68k_unwrap_symbol_1 (rtx orig, bool unwrap_reloc32_p,
+ enum m68k_reloc *reloc_ptr)
+{
+ if (GET_CODE (orig) == CONST)
+ {
+ rtx x;
+ enum m68k_reloc dummy;
+
+ x = XEXP (orig, 0);
+
+ if (reloc_ptr == NULL)
+ reloc_ptr = &dummy;
+
+ /* Handle an addend. */
+ if ((GET_CODE (x) == PLUS || GET_CODE (x) == MINUS)
+ && CONST_INT_P (XEXP (x, 1)))
+ x = XEXP (x, 0);
+
+ if (GET_CODE (x) == UNSPEC)
+ {
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_RELOC16:
+ orig = XVECEXP (x, 0, 0);
+ *reloc_ptr = (enum m68k_reloc) INTVAL (XVECEXP (x, 0, 1));
+ break;
+
+ case UNSPEC_RELOC32:
+ if (unwrap_reloc32_p)
+ {
+ orig = XVECEXP (x, 0, 0);
+ *reloc_ptr = (enum m68k_reloc) INTVAL (XVECEXP (x, 0, 1));
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ return orig;
+}
+
+/* Unwrap symbol from UNSPEC_RELOC16 and, if unwrap_reloc32_p,
+ UNSPEC_RELOC32 wrappers. */
+
+rtx
+m68k_unwrap_symbol (rtx orig, bool unwrap_reloc32_p)
+{
+ return m68k_unwrap_symbol_1 (orig, unwrap_reloc32_p, NULL);
+}
+
+/* Helper for m68k_final_prescan_insn. */
+
+static int
+m68k_final_prescan_insn_1 (rtx *x_ptr, void *data ATTRIBUTE_UNUSED)
+{
+ rtx x = *x_ptr;
+
+ if (m68k_unwrap_symbol (x, true) != x)
+ /* For rationale of the below, see comment in m68k_final_prescan_insn. */
+ {
+ rtx plus;
+
+ gcc_assert (GET_CODE (x) == CONST);
+ plus = XEXP (x, 0);
+
+ if (GET_CODE (plus) == PLUS || GET_CODE (plus) == MINUS)
+ {
+ rtx unspec;
+ rtx addend;
+
+ unspec = XEXP (plus, 0);
+ gcc_assert (GET_CODE (unspec) == UNSPEC);
+ addend = XEXP (plus, 1);
+ gcc_assert (CONST_INT_P (addend));
+
+ /* We now have all the pieces, rearrange them. */
+
+ /* Move symbol to plus. */
+ XEXP (plus, 0) = XVECEXP (unspec, 0, 0);
+
+ /* Move plus inside unspec. */
+ XVECEXP (unspec, 0, 0) = plus;
+
+ /* Move unspec to top level of const. */
+ XEXP (x, 0) = unspec;
+ }
+
+ return -1;
+ }
+
+ return 0;
+}
+
+/* Prescan insn before outputing assembler for it. */
+
+void
+m68k_final_prescan_insn (rtx insn ATTRIBUTE_UNUSED,
+ rtx *operands, int n_operands)
+{
+ int i;
+
+ /* Combine and, possibly, other optimizations may do good job
+ converting
+ (const (unspec [(symbol)]))
+ into
+ (const (plus (unspec [(symbol)])
+ (const_int N))).
+ The problem with this is emitting @TLS or @GOT decorations.
+ The decoration is emitted when processing (unspec), so the
+ result would be "#symbol@TLSLE+N" instead of "#symbol+N@TLSLE".
+
+ It seems that the easiest solution to this is to convert such
+ operands to
+ (const (unspec [(plus (symbol)
+ (const_int N))])).
+ Note, that the top level of operand remains intact, so we don't have
+ to patch up anything outside of the operand. */
+
+ for (i = 0; i < n_operands; ++i)
+ {
+ rtx op;
+
+ op = operands[i];
+
+ for_each_rtx (&op, m68k_final_prescan_insn_1, NULL);
+ }
+}
+
+/* Move X to a register and add REG_EQUAL note pointing to ORIG.
+ If REG is non-null, use it; generate new pseudo otherwise. */
+
+static rtx
+m68k_move_to_reg (rtx x, rtx orig, rtx reg)
+{
+ rtx insn;
+
+ if (reg == NULL_RTX)
+ {
+ gcc_assert (can_create_pseudo_p ());
+ reg = gen_reg_rtx (Pmode);
+ }
+
+ insn = emit_move_insn (reg, x);
+ /* Put a REG_EQUAL note on this insn, so that it can be optimized
+ by loop. */
+ set_unique_reg_note (insn, REG_EQUAL, orig);
+
+ return reg;
+}
+
+/* Does the same as m68k_wrap_symbol, but returns a memory reference to
+ GOT slot. */
+
+static rtx
+m68k_wrap_symbol_into_got_ref (rtx x, enum m68k_reloc reloc, rtx temp_reg)
+{
+ x = m68k_wrap_symbol (x, reloc, m68k_get_gp (), temp_reg);
+
+ x = gen_rtx_MEM (Pmode, x);
+ MEM_READONLY_P (x) = 1;
+
+ return x;
+}
+
/* Legitimize PIC addresses. If the address is already
position-independent, we return ORIG. Newly generated
position-independent addresses go to REG. If we need more
@@ -2152,42 +2404,15 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
{
gcc_assert (reg);
- if (TARGET_COLDFIRE && TARGET_XGOT)
- /* When compiling with -mxgot switch the code for the above
- example will look like this:
-
- movel a5, a0
- addl _foo@GOT, a0
- movel a0@, a0
- movel #12345, a0@ */
- {
- rtx pic_offset;
-
- /* Wrap ORIG in UNSPEC_GOTOFF to tip m68k_output_addr_const_extra
- to put @GOT after reference. */
- pic_offset = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig),
- UNSPEC_GOTOFF);
- pic_offset = gen_rtx_CONST (Pmode, pic_offset);
- emit_move_insn (reg, pic_offset);
- emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
- pic_ref = gen_rtx_MEM (Pmode, reg);
- }
- else
- pic_ref = gen_rtx_MEM (Pmode,
- gen_rtx_PLUS (Pmode,
- pic_offset_table_rtx, orig));
- crtl->uses_pic_offset_table = 1;
- MEM_READONLY_P (pic_ref) = 1;
- emit_move_insn (reg, pic_ref);
- return reg;
+ pic_ref = m68k_wrap_symbol_into_got_ref (orig, RELOC_GOT, reg);
+ pic_ref = m68k_move_to_reg (pic_ref, orig, reg);
}
else if (GET_CODE (orig) == CONST)
{
rtx base;
/* Make sure this has not already been legitimized. */
- if (GET_CODE (XEXP (orig, 0)) == PLUS
- && XEXP (XEXP (orig, 0), 0) == pic_offset_table_rtx)
+ if (m68k_unwrap_symbol (orig, true) != orig)
return orig;
gcc_assert (reg);
@@ -2200,13 +2425,257 @@ legitimize_pic_address (rtx orig, enum machine_mode mode ATTRIBUTE_UNUSED,
base == reg ? 0 : reg);
if (GET_CODE (orig) == CONST_INT)
- return plus_constant (base, INTVAL (orig));
- pic_ref = gen_rtx_PLUS (Pmode, base, orig);
- /* Likewise, should we set special REG_NOTEs here? */
+ pic_ref = plus_constant (base, INTVAL (orig));
+ else
+ pic_ref = gen_rtx_PLUS (Pmode, base, orig);
}
+
return pic_ref;
}
+/* The __tls_get_addr symbol. */
+static GTY(()) rtx m68k_tls_get_addr;
+
+/* Return SYMBOL_REF for __tls_get_addr. */
+
+static rtx
+m68k_get_tls_get_addr (void)
+{
+ if (m68k_tls_get_addr == NULL_RTX)
+ m68k_tls_get_addr = init_one_libfunc ("__tls_get_addr");
+
+ return m68k_tls_get_addr;
+}
+
+/* Return libcall result in A0 instead of usual D0. */
+static bool m68k_libcall_value_in_a0_p = false;
+
+/* Emit instruction sequence that calls __tls_get_addr. X is
+ the TLS symbol we are referencing and RELOC is the symbol type to use
+ (either TLSGD or TLSLDM). EQV is the REG_EQUAL note for the sequence
+ emitted. A pseudo register with result of __tls_get_addr call is
+ returned. */
+
+static rtx
+m68k_call_tls_get_addr (rtx x, rtx eqv, enum m68k_reloc reloc)
+{
+ rtx a0;
+ rtx insns;
+ rtx dest;
+
+ /* Emit the call sequence. */
+ start_sequence ();
+
+ /* FIXME: Unfortunately, emit_library_call_value does not
+ consider (plus (%a5) (const (unspec))) to be a good enough
+ operand for push, so it forces it into a register. The bad
+ thing about this is that combiner, due to copy propagation and other
+ optimizations, sometimes can not later fix this. As a consequence,
+ additional register may be allocated resulting in a spill.
+ For reference, see args processing loops in
+ calls.c:emit_library_call_value_1.
+ For testcase, see gcc.target/m68k/tls-{gd, ld}.c */
+ x = m68k_wrap_symbol (x, reloc, m68k_get_gp (), NULL_RTX);
+
+ /* __tls_get_addr() is not a libcall, but emitting a libcall_value
+ is the simpliest way of generating a call. The difference between
+ __tls_get_addr() and libcall is that the result is returned in D0
+ instead of A0. To workaround this, we use m68k_libcall_value_in_a0_p
+ which temporarily switches returning the result to A0. */
+
+ m68k_libcall_value_in_a0_p = true;
+ a0 = emit_library_call_value (m68k_get_tls_get_addr (), NULL_RTX, LCT_PURE,
+ Pmode, 1, x, Pmode);
+ m68k_libcall_value_in_a0_p = false;
+
+ insns = get_insns ();
+ end_sequence ();
+
+ gcc_assert (can_create_pseudo_p ());
+ dest = gen_reg_rtx (Pmode);
+ emit_libcall_block (insns, dest, a0, eqv);
+
+ return dest;
+}
+
+/* The __tls_get_addr symbol. */
+static GTY(()) rtx m68k_read_tp;
+
+/* Return SYMBOL_REF for __m68k_read_tp. */
+
+static rtx
+m68k_get_m68k_read_tp (void)
+{
+ if (m68k_read_tp == NULL_RTX)
+ m68k_read_tp = init_one_libfunc ("__m68k_read_tp");
+
+ return m68k_read_tp;
+}
+
+/* Emit instruction sequence that calls __m68k_read_tp.
+ A pseudo register with result of __m68k_read_tp call is returned. */
+
+static rtx
+m68k_call_m68k_read_tp (void)
+{
+ rtx a0;
+ rtx eqv;
+ rtx insns;
+ rtx dest;
+
+ start_sequence ();
+
+ /* __m68k_read_tp() is not a libcall, but emitting a libcall_value
+ is the simpliest way of generating a call. The difference between
+ __m68k_read_tp() and libcall is that the result is returned in D0
+ instead of A0. To workaround this, we use m68k_libcall_value_in_a0_p
+ which temporarily switches returning the result to A0. */
+
+ /* Emit the call sequence. */
+ m68k_libcall_value_in_a0_p = true;
+ a0 = emit_library_call_value (m68k_get_m68k_read_tp (), NULL_RTX, LCT_PURE,
+ Pmode, 0);
+ m68k_libcall_value_in_a0_p = false;
+ insns = get_insns ();
+ end_sequence ();
+
+ /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+ share the m68k_read_tp result with other IE/LE model accesses. */
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const1_rtx), UNSPEC_RELOC32);
+
+ gcc_assert (can_create_pseudo_p ());
+ dest = gen_reg_rtx (Pmode);
+ emit_libcall_block (insns, dest, a0, eqv);
+
+ return dest;
+}
+
+/* Return a legitimized address for accessing TLS SYMBOL_REF X.
+ For explanations on instructions sequences see TLS/NPTL ABI for m68k and
+ ColdFire. */
+
+rtx
+m68k_legitimize_tls_address (rtx orig)
+{
+ switch (SYMBOL_REF_TLS_MODEL (orig))
+ {
+ case TLS_MODEL_GLOBAL_DYNAMIC:
+ orig = m68k_call_tls_get_addr (orig, orig, RELOC_TLSGD);
+ break;
+
+ case TLS_MODEL_LOCAL_DYNAMIC:
+ {
+ rtx eqv;
+ rtx a0;
+ rtx x;
+
+ /* Attach a unique REG_EQUIV, to allow the RTL optimizers to
+ share the LDM result with other LD model accesses. */
+ eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
+ UNSPEC_RELOC32);
+
+ a0 = m68k_call_tls_get_addr (orig, eqv, RELOC_TLSLDM);
+
+ x = m68k_wrap_symbol (orig, RELOC_TLSLDO, a0, NULL_RTX);
+
+ if (can_create_pseudo_p ())
+ x = m68k_move_to_reg (x, orig, NULL_RTX);
+
+ orig = x;
+ break;
+ }
+
+ case TLS_MODEL_INITIAL_EXEC:
+ {
+ rtx a0;
+ rtx x;
+
+ a0 = m68k_call_m68k_read_tp ();
+
+ x = m68k_wrap_symbol_into_got_ref (orig, RELOC_TLSIE, NULL_RTX);
+ x = gen_rtx_PLUS (Pmode, x, a0);
+
+ if (can_create_pseudo_p ())
+ x = m68k_move_to_reg (x, orig, NULL_RTX);
+
+ orig = x;
+ break;
+ }
+
+ case TLS_MODEL_LOCAL_EXEC:
+ {
+ rtx a0;
+ rtx x;
+
+ a0 = m68k_call_m68k_read_tp ();
+
+ x = m68k_wrap_symbol (orig, RELOC_TLSLE, a0, NULL_RTX);
+
+ if (can_create_pseudo_p ())
+ x = m68k_move_to_reg (x, orig, NULL_RTX);
+
+ orig = x;
+ break;
+ }
+
+ default:
+ gcc_unreachable ();
+ }
+
+ return orig;
+}
+
+/* Return true if X is a TLS symbol. */
+
+static bool
+m68k_tls_symbol_p (rtx x)
+{
+ if (!TARGET_HAVE_TLS)
+ return false;
+
+ if (GET_CODE (x) != SYMBOL_REF)
+ return false;
+
+ return SYMBOL_REF_TLS_MODEL (x) != 0;
+}
+
+/* Helper for m68k_tls_referenced_p. */
+
+static int
+m68k_tls_reference_p_1 (rtx *x_ptr, void *data ATTRIBUTE_UNUSED)
+{
+ /* Note: this is not the same as m68k_tls_symbol_p. */
+ if (GET_CODE (*x_ptr) == SYMBOL_REF)
+ return SYMBOL_REF_TLS_MODEL (*x_ptr) != 0 ? 1 : 0;
+
+ /* Don't recurse into legitimate TLS references. */
+ if (m68k_tls_reference_p (*x_ptr, true))
+ return -1;
+
+ return 0;
+}
+
+/* If !LEGITIMATE_P, return true if X is a TLS symbol reference,
+ though illegitimate one.
+ If LEGITIMATE_P, return true if X is a legitimate TLS symbol reference. */
+
+bool
+m68k_tls_reference_p (rtx x, bool legitimate_p)
+{
+ if (!TARGET_HAVE_TLS)
+ return false;
+
+ if (!legitimate_p)
+ return for_each_rtx (&x, m68k_tls_reference_p_1, NULL) == 1 ? true : false;
+ else
+ {
+ enum m68k_reloc reloc = RELOC_GOT;
+
+ return (m68k_unwrap_symbol_1 (x, true, &reloc) != x
+ && TLS_RELOC_P (reloc));
+ }
+}
+
#define USE_MOVQ(i) ((unsigned) ((i) + 128) <= 255)
@@ -3999,18 +4468,92 @@ print_operand (FILE *file, rtx op, int letter)
}
}
+/* Return string for TLS relocation RELOC. */
+
+static const char *
+m68k_get_reloc_decoration (enum m68k_reloc reloc)
+{
+ /* To my knowledge, !MOTOROLA assemblers don't support TLS. */
+ gcc_assert (MOTOROLA || reloc == RELOC_GOT);
+
+ switch (reloc)
+ {
+ case RELOC_GOT:
+ if (MOTOROLA)
+ {
+ if (flag_pic == 1 && TARGET_68020)
+ return "@GOT.w";
+ else
+ return "@GOT";
+ }
+ else
+ {
+ if (TARGET_68020)
+ {
+ switch (flag_pic)
+ {
+ case 1:
+ return ":w";
+ case 2:
+ return ":l";
+ default:
+ return "";
+ }
+ }
+ }
+
+ case RELOC_TLSGD:
+ return "@TLSGD";
+
+ case RELOC_TLSLDM:
+ return "@TLSLDM";
+
+ case RELOC_TLSLDO:
+ return "@TLSLDO";
+
+ case RELOC_TLSIE:
+ return "@TLSIE";
+
+ case RELOC_TLSLE:
+ return "@TLSLE";
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
/* m68k implementation of OUTPUT_ADDR_CONST_EXTRA. */
bool
m68k_output_addr_const_extra (FILE *file, rtx x)
{
- if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_GOTOFF)
- return false;
+ if (GET_CODE (x) == UNSPEC)
+ {
+ switch (XINT (x, 1))
+ {
+ case UNSPEC_RELOC16:
+ case UNSPEC_RELOC32:
+ output_addr_const (file, XVECEXP (x, 0, 0));
+ fputs (m68k_get_reloc_decoration (INTVAL (XVECEXP (x, 0, 1))), file);
+ return true;
- output_addr_const (file, XVECEXP (x, 0, 0));
- /* ??? What is the non-MOTOROLA syntax? */
- fputs ("@GOT", file);
- return true;
+ default:
+ break;
+ }
+ }
+
+ return false;
+}
+
+/* M68K implementation of TARGET_ASM_OUTPUT_DWARF_DTPREL. */
+
+static void
+m68k_output_dwarf_dtprel (FILE *file, int size, rtx x)
+{
+ gcc_assert (size == 4);
+ fputs ("\t.long\t", file);
+ output_addr_const (file, x);
+ fputs ("@TLSLDO+0x8000", file);
}
@@ -4100,15 +4643,8 @@ print_operand_address (FILE *file, rtx addr)
else
{
if (address.offset)
- {
- output_addr_const (file, address.offset);
- if (flag_pic && address.base == pic_offset_table_rtx)
- {
- fprintf (file, "@GOT");
- if (flag_pic == 1 && TARGET_68020)
- fprintf (file, ".w");
- }
- }
+ output_addr_const (file, address.offset);
+
putc ('(', file);
if (address.base)
fputs (M68K_REGNAME (REGNO (address.base)), file);
@@ -4141,19 +4677,7 @@ print_operand_address (FILE *file, rtx addr)
fputs (M68K_REGNAME (REGNO (address.base)), file);
fprintf (file, "@(");
if (address.offset)
- {
- output_addr_const (file, address.offset);
- if (address.base == pic_offset_table_rtx && TARGET_68020)
- switch (flag_pic)
- {
- case 1:
- fprintf (file, ":w"); break;
- case 2:
- fprintf (file, ":l"); break;
- default:
- break;
- }
- }
+ output_addr_const (file, address.offset);
}
/* Print the ",index" component, if any. */
if (address.index)
@@ -4305,7 +4829,7 @@ output_andsi3 (rtx *operands)
return "and%.w %2,%0";
}
if (GET_CODE (operands[2]) == CONST_INT
- && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
+ && (logval = exact_log2 (~ INTVAL (operands[2]) & 0xffffffff)) >= 0
&& (DATA_REG_P (operands[0])
|| offsettable_memref_p (operands[0])))
{
@@ -4342,7 +4866,7 @@ output_iorsi3 (rtx *operands)
return "or%.w %2,%0";
}
if (GET_CODE (operands[2]) == CONST_INT
- && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
+ && (logval = exact_log2 (INTVAL (operands[2]) & 0xffffffff)) >= 0
&& (DATA_REG_P (operands[0])
|| offsettable_memref_p (operands[0])))
{
@@ -4377,7 +4901,7 @@ output_xorsi3 (rtx *operands)
return "eor%.w %2,%0";
}
if (GET_CODE (operands[2]) == CONST_INT
- && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
+ && (logval = exact_log2 (INTVAL (operands[2]) & 0xffffffff)) >= 0
&& (DATA_REG_P (operands[0])
|| offsettable_memref_p (operands[0])))
{
@@ -4641,7 +5165,8 @@ m68k_libcall_value (enum machine_mode mode)
default:
break;
}
- return gen_rtx_REG (mode, D0_REG);
+
+ return gen_rtx_REG (mode, m68k_libcall_value_in_a0_p ? A0_REG : D0_REG);
}
rtx
@@ -4907,9 +5432,8 @@ sched_attr_op_type (rtx insn, bool opx_p, bool address_p)
return OP_TYPE_IMM_L;
default:
- if (GET_CODE (op) == SYMBOL_REF)
- /* ??? Just a guess. Probably we can guess better using length
- attribute of the instructions. */
+ if (symbolic_operand (m68k_unwrap_symbol (op, false), VOIDmode))
+ /* Just a guess. */
return OP_TYPE_IMM_W;
return OP_TYPE_IMM_L;
@@ -5854,3 +6378,5 @@ m68k_sched_indexed_address_bypass_p (rtx pro, rtx con)
return 0;
}
}
+
+#include "gt-m68k.h"
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index e91ab00fcc9..2d3b592eb88 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -750,7 +750,8 @@ __transfer_from_trampoline () \
#define LEGITIMATE_PIC_OPERAND_P(X) \
(!symbolic_operand (X, VOIDmode) \
- || (TARGET_PCREL && REG_STRICT_P))
+ || (TARGET_PCREL && REG_STRICT_P) \
+ || m68k_tls_reference_p (X, true))
#define REG_OK_FOR_BASE_P(X) \
m68k_legitimate_base_reg_p (X, REG_STRICT_P)
@@ -967,6 +968,9 @@ do { if (cc_prev_status.flags & CC_IN_68881) \
assemble_name ((FILE), (NAME)), \
fprintf ((FILE), ",%u\n", (int)(ROUNDED)))
+#define FINAL_PRESCAN_INSN(INSN, OPVEC, NOPERANDS) \
+ m68k_final_prescan_insn (INSN, OPVEC, NOPERANDS)
+
/* On the 68000, we use several CODE characters:
'.' for dot needed in Motorola-style opcode names.
'-' for an operand pushing on the stack:
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 33058fa08b8..037bb372cc9 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -116,7 +116,8 @@
(UNSPEC_GOT 3)
(UNSPEC_IB 4)
(UNSPEC_TIE 5)
- (UNSPEC_GOTOFF 6)
+ (UNSPEC_RELOC16 6)
+ (UNSPEC_RELOC32 7)
])
;; UNSPEC_VOLATILE usage:
@@ -869,7 +870,41 @@
{
rtx tmp, base, offset;
- if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
+ /* Recognize the case where operand[1] is a reference to thread-local
+ data and load its address to a register. */
+ if (!TARGET_PCREL && m68k_tls_reference_p (operands[1], false))
+ {
+ rtx tmp = operands[1];
+ rtx addend = NULL;
+
+ if (GET_CODE (tmp) == CONST && GET_CODE (XEXP (tmp, 0)) == PLUS)
+ {
+ addend = XEXP (XEXP (tmp, 0), 1);
+ tmp = XEXP (XEXP (tmp, 0), 0);
+ }
+
+ gcc_assert (GET_CODE (tmp) == SYMBOL_REF);
+ gcc_assert (SYMBOL_REF_TLS_MODEL (tmp) != 0);
+
+ tmp = m68k_legitimize_tls_address (tmp);
+
+ if (addend)
+ {
+ if (!REG_P (tmp))
+ {
+ rtx reg;
+
+ reg = gen_reg_rtx (Pmode);
+ emit_move_insn (reg, tmp);
+ tmp = reg;
+ }
+
+ tmp = gen_rtx_PLUS (SImode, tmp, addend);
+ }
+
+ operands[1] = tmp;
+ }
+ else if (flag_pic && !TARGET_PCREL && symbolic_operand (operands[1], SImode))
{
/* The source is an address which requires PIC relocation.
Call legitimize_pic_address with the source, mode, and a relocation
@@ -2428,9 +2463,9 @@
"* return output_addsi3 (operands);")
(define_insn_and_split "*addsi3_5200"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=mr,mr,a,m,r, ?a, ?a,?a,?a")
- (plus:SI (match_operand:SI 1 "general_operand" "%0, 0, 0,0,0, a, a, r, a")
- (match_operand:SI 2 "general_src_operand" " I, L, J,d,mrKi,Cj, r, a, J")))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=mr,mr,a, m,r, ?a, ?a,?a,?a")
+ (plus:SI (match_operand:SI 1 "general_operand" "%0, 0, 0, 0,0, a, a, r, a")
+ (match_operand:SI 2 "general_src_operand" " I, L, JCu,d,mrKi,Cj, r, a, JCu")))]
"TARGET_COLDFIRE"
{
switch (which_alternative)
@@ -2472,9 +2507,9 @@
(plus:SI (match_dup 0)
(match_dup 1)))]
""
- [(set_attr "type" "aluq_l,aluq_l,lea,alu_l,alu_l,*,lea,lea,lea")
- (set_attr "opy" "2,2,*,2,2,*,*,*,*")
- (set_attr "opy_type" "*,*,mem5,*,*,*,mem6,mem6,mem5")])
+ [(set_attr "type" "aluq_l,aluq_l,lea, alu_l,alu_l,*,lea, lea, lea")
+ (set_attr "opy" "2, 2, *, 2, 2, *,*, *, *")
+ (set_attr "opy_type" "*, *, mem5,*, *, *,mem6,mem6,mem5")])
(define_insn ""
[(set (match_operand:SI 0 "nonimmediate_operand" "=a")
diff --git a/gcc/config/m68k/m68k.opt b/gcc/config/m68k/m68k.opt
index b0d3b3c0d59..d5aa9fa7698 100644
--- a/gcc/config/m68k/m68k.opt
+++ b/gcc/config/m68k/m68k.opt
@@ -182,3 +182,7 @@ Tune for the specified target CPU or architecture
mxgot
Target Report Mask(XGOT)
Support more than 8192 GOT entries on ColdFire
+
+mxtls
+Target Report Mask(XTLS)
+Support TLS segment larger than 64K
diff --git a/gcc/config/m68k/predicates.md b/gcc/config/m68k/predicates.md
index 417989f6d6c..6ca261fb92a 100644
--- a/gcc/config/m68k/predicates.md
+++ b/gcc/config/m68k/predicates.md
@@ -135,7 +135,9 @@
(match_code "sign_extend,zero_extend"))
;; Returns true if OP is either a symbol reference or a sum of a
-;; symbol reference and a constant.
+;; symbol reference and a constant. This predicate is for "raw"
+;; symbol references not yet processed by legitimize*_address,
+;; hence we do not handle UNSPEC_{XGOT, TLS, XTLS} here.
(define_predicate "symbolic_operand"
(match_code "symbol_ref,label_ref,const")
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/mips.h b/gcc/config/mips/mips.h
index 5b64346fef6..3d2fcac45f5 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -668,6 +668,32 @@ enum mips_code_readable_setting {
# endif
#endif
+#ifndef MIPS_ABI_DEFAULT
+#define MIPS_ABI_DEFAULT ABI_32
+#endif
+
+/* Use the most portable ABI flag for the ASM specs. */
+
+#if MIPS_ABI_DEFAULT == ABI_32
+#define MULTILIB_ABI_DEFAULT "mabi=32"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_O64
+#define MULTILIB_ABI_DEFAULT "mabi=o64"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_N32
+#define MULTILIB_ABI_DEFAULT "mabi=n32"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_64
+#define MULTILIB_ABI_DEFAULT "mabi=64"
+#endif
+
+#if MIPS_ABI_DEFAULT == ABI_EABI
+#define MULTILIB_ABI_DEFAULT "mabi=eabi"
+#endif
+
#ifndef MULTILIB_DEFAULTS
#define MULTILIB_DEFAULTS \
{ MULTILIB_ENDIAN_DEFAULT, MULTILIB_ISA_DEFAULT, MULTILIB_ABI_DEFAULT }
@@ -730,10 +756,21 @@ enum mips_code_readable_setting {
#define MIPS_32BIT_OPTION_SPEC \
"mips1|mips2|mips32*|mgp32"
+#if MIPS_ABI_DEFAULT == ABI_O64 \
+ || MIPS_ABI_DEFAULT == ABI_N32 \
+ || MIPS_ABI_DEFAULT == ABI_64
+#define OPT_ARCH64 "mabi=32|mgp32:;"
+#define OPT_ARCH32 "mabi=32|mgp32"
+#else
+#define OPT_ARCH64 "mabi=o64|mabi=n32|mabi=64|mgp64"
+#define OPT_ARCH32 "mabi=o64|mabi=n32|mabi=64|mgp64:;"
+#endif
+
/* Support for a compile-time default CPU, et cetera. The rules are:
--with-arch is ignored if -march is specified or a -mips is specified
- (other than -mips16).
- --with-tune is ignored if -mtune is specified.
+ (other than -mips16); likewise --with-arch-32 and --with-arch-64.
+ --with-tune is ignored if -mtune is specified; likewise
+ --with-tune-32 and --with-tune-64.
--with-abi is ignored if -mabi is specified.
--with-float is ignored if -mhard-float or -msoft-float are
specified.
@@ -741,7 +778,11 @@ enum mips_code_readable_setting {
specified. */
#define OPTION_DEFAULT_SPECS \
{"arch", "%{" MIPS_ARCH_OPTION_SPEC ":;: -march=%(VALUE)}" }, \
+ {"arch_32", "%{" OPT_ARCH32 ":%{" MIPS_ARCH_OPTION_SPEC ":;: -march=%(VALUE)}}" }, \
+ {"arch_64", "%{" OPT_ARCH64 ":%{" MIPS_ARCH_OPTION_SPEC ":;: -march=%(VALUE)}}" }, \
{"tune", "%{!mtune=*:-mtune=%(VALUE)}" }, \
+ {"tune_32", "%{" OPT_ARCH32 ":%{!mtune=*:-mtune=%(VALUE)}}" }, \
+ {"tune_64", "%{" OPT_ARCH64 ":%{!mtune=*:-mtune=%(VALUE)}}" }, \
{"abi", "%{!mabi=*:-mabi=%(VALUE)}" }, \
{"float", "%{!msoft-float:%{!mhard-float:-m%(VALUE)-float}}" }, \
{"divide", "%{!mdivide-traps:%{!mdivide-breaks:-mdivide-%(VALUE)}}" }, \
@@ -1076,32 +1117,6 @@ enum mips_code_readable_setting {
#endif
-#ifndef MIPS_ABI_DEFAULT
-#define MIPS_ABI_DEFAULT ABI_32
-#endif
-
-/* Use the most portable ABI flag for the ASM specs. */
-
-#if MIPS_ABI_DEFAULT == ABI_32
-#define MULTILIB_ABI_DEFAULT "mabi=32"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_O64
-#define MULTILIB_ABI_DEFAULT "mabi=o64"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_N32
-#define MULTILIB_ABI_DEFAULT "mabi=n32"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_64
-#define MULTILIB_ABI_DEFAULT "mabi=64"
-#endif
-
-#if MIPS_ABI_DEFAULT == ABI_EABI
-#define MULTILIB_ABI_DEFAULT "mabi=eabi"
-#endif
-
/* SUBTARGET_ASM_OPTIMIZING_SPEC handles passing optimization options
to the assembler. It may be overridden by subtargets. */
#ifndef SUBTARGET_ASM_OPTIMIZING_SPEC
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 78539cbe49d..e571614b35c 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -2736,74 +2736,6 @@
"exts\t%0,%1,%2,31"
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
-
-;; Combiner patterns for truncate/sign_extend combinations. The SI versions
-;; use the shift/truncate patterns above.
-
-(define_insn_and_split "*extenddi_truncate<mode>"
- [(set (match_operand:DI 0 "register_operand" "=d")
- (sign_extend:DI
- (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "#"
- "&& reload_completed"
- [(set (match_dup 2)
- (ashift:DI (match_dup 1)
- (match_dup 3)))
- (set (match_dup 0)
- (ashiftrt:DI (match_dup 2)
- (match_dup 3)))]
-{
- operands[2] = gen_lowpart (DImode, operands[0]);
- operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode));
-})
-
-(define_insn_and_split "*extendsi_truncate<mode>"
- [(set (match_operand:SI 0 "register_operand" "=d")
- (sign_extend:SI
- (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "#"
- "&& reload_completed"
- [(set (match_dup 2)
- (ashift:DI (match_dup 1)
- (match_dup 3)))
- (set (match_dup 0)
- (truncate:SI (ashiftrt:DI (match_dup 2)
- (match_dup 3))))]
-{
- operands[2] = gen_lowpart (DImode, operands[0]);
- operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode));
-})
-
-;; Combiner patterns to optimize truncate/zero_extend combinations.
-
-(define_insn "*zero_extend<mode>_trunchi"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (zero_extend:GPR
- (truncate:HI (match_operand:DI 1 "register_operand" "d"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "andi\t%0,%1,0xffff"
- [(set_attr "type" "logical")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "*zero_extend<mode>_truncqi"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (zero_extend:GPR
- (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "andi\t%0,%1,0xff"
- [(set_attr "type" "logical")
- (set_attr "mode" "<MODE>")])
-
-(define_insn ""
- [(set (match_operand:HI 0 "register_operand" "=d")
- (zero_extend:HI
- (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
- "TARGET_64BIT && !TARGET_MIPS16"
- "andi\t%0,%1,0xff"
- [(set_attr "type" "logical")
- (set_attr "mode" "HI")])
;;
;; ....................
@@ -2928,6 +2860,29 @@
"lbu\t%0,%1"
[(set_attr "move_type" "load")
(set_attr "mode" "HI")])
+
+;; Combiner patterns to optimize truncate/zero_extend combinations.
+
+(define_insn "*zero_extend<GPR:mode>_trunc<SHORT:mode>"
+ [(set (match_operand:GPR 0 "register_operand" "=d")
+ (zero_extend:GPR
+ (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+{
+ operands[2] = GEN_INT (GET_MODE_MASK (<SHORT:MODE>mode));
+ return "andi\t%0,%1,%x2";
+}
+ [(set_attr "type" "logical")
+ (set_attr "mode" "<GPR:MODE>")])
+
+(define_insn "*zero_extendhi_truncqi"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (zero_extend:HI
+ (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+ "andi\t%0,%1,0xff"
+ [(set_attr "type" "logical")
+ (set_attr "mode" "HI")])
;;
;; ....................
@@ -3054,6 +3009,80 @@
[(set_attr "move_type" "signext,load")
(set_attr "mode" "SI")])
+;; Combiner patterns for truncate/sign_extend combinations. The SI versions
+;; use the shift/truncate patterns.
+
+(define_insn_and_split "*extenddi_truncate<mode>"
+ [(set (match_operand:DI 0 "register_operand" "=d")
+ (sign_extend:DI
+ (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+{
+ if (!ISA_HAS_EXTS)
+ return "#";
+ operands[2] = GEN_INT (GET_MODE_BITSIZE (<SHORT:MODE>mode));
+ return "exts\t%0,%1,0,%m2";
+}
+ "&& reload_completed && !ISA_HAS_EXTS"
+ [(set (match_dup 2)
+ (ashift:DI (match_dup 1)
+ (match_dup 3)))
+ (set (match_dup 0)
+ (ashiftrt:DI (match_dup 2)
+ (match_dup 3)))]
+{
+ operands[2] = gen_lowpart (DImode, operands[0]);
+ operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode));
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "DI")])
+
+(define_insn_and_split "*extendsi_truncate<mode>"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (sign_extend:SI
+ (truncate:SHORT (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+{
+ if (!ISA_HAS_EXTS)
+ return "#";
+ operands[2] = GEN_INT (GET_MODE_BITSIZE (<SHORT:MODE>mode));
+ return "exts\t%0,%1,0,%m2";
+}
+ "&& reload_completed && !ISA_HAS_EXTS"
+ [(set (match_dup 2)
+ (ashift:DI (match_dup 1)
+ (match_dup 3)))
+ (set (match_dup 0)
+ (truncate:SI (ashiftrt:DI (match_dup 2)
+ (match_dup 3))))]
+{
+ operands[2] = gen_lowpart (DImode, operands[0]);
+ operands[3] = GEN_INT (BITS_PER_WORD - GET_MODE_BITSIZE (<MODE>mode));
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
+(define_insn_and_split "*extendhi_truncateqi"
+ [(set (match_operand:HI 0 "register_operand" "=d")
+ (sign_extend:HI
+ (truncate:QI (match_operand:DI 1 "register_operand" "d"))))]
+ "TARGET_64BIT && !TARGET_MIPS16"
+{
+ return ISA_HAS_EXTS ? "exts\t%0,%1,0,7" : "#";
+}
+ "&& reload_completed && !ISA_HAS_EXTS"
+ [(set (match_dup 2)
+ (ashift:DI (match_dup 1)
+ (const_int 56)))
+ (set (match_dup 0)
+ (truncate:HI (ashiftrt:DI (match_dup 2)
+ (const_int 56))))]
+{
+ operands[2] = gen_lowpart (DImode, operands[0]);
+}
+ [(set_attr "type" "arith")
+ (set_attr "mode" "SI")])
+
(define_insn "extendsfdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
(float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
@@ -3462,16 +3491,16 @@
[(set_attr "type" "arith")
(set_attr "mode" "<MODE>")])
-(define_insn "*extzv_trunc<mode>_exts"
- [(set (match_operand:GPR 0 "register_operand" "=d")
- (truncate:GPR
+(define_insn "*extzv_truncsi_exts"
+ [(set (match_operand:SI 0 "register_operand" "=d")
+ (truncate:SI
(zero_extract:DI (match_operand:DI 1 "register_operand" "d")
(match_operand 2 "const_int_operand" "")
(match_operand 3 "const_int_operand" ""))))]
"ISA_HAS_EXTS && TARGET_64BIT && IN_RANGE (INTVAL (operands[2]), 32, 63)"
"exts\t%0,%1,%3,31"
[(set_attr "type" "arith")
- (set_attr "mode" "<MODE>")])
+ (set_attr "mode" "SI")])
(define_expand "insv"
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/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/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/s390/2064.md b/gcc/config/s390/2064.md
index 573826a7549..143978334a3 100644
--- a/gcc/config/s390/2064.md
+++ b/gcc/config/s390/2064.md
@@ -21,22 +21,22 @@
;;
;; References:
-;; The microarchitecture of the IBM eServer z900 processor.
+;; The microarchitecture of the IBM eServer z900 processor.
;; E.M. Schwarz et al.
;; IBM Journal of Research and Development Vol. 46 No 4/5, 2002.
-;;
+;;
;; z900 (cpu 2064) pipeline
-;;
+;;
;; dec
;; --> | <---
;; LA bypass | agen |
-;; | | |
+;; | | |
;; --- c1 | Load bypass
-;; | |
+;; | |
;; c2----
;; |
-;; e1
-;; |
+;; e1
+;; |
;; wr
;; This scheduler description is also used for the g5 and g6.
@@ -46,12 +46,12 @@
(define_cpu_unit "z_wr" "z_ipu")
-(define_insn_reservation "z_la" 1
+(define_insn_reservation "z_la" 1
(and (eq_attr "cpu" "z900,g5,g6")
(eq_attr "type" "la"))
"z_e1,z_wr")
-(define_insn_reservation "z_larl" 1
+(define_insn_reservation "z_larl" 1
(and (eq_attr "cpu" "z900,g5,g6")
(eq_attr "type" "larl"))
"z_e1,z_wr")
@@ -101,32 +101,32 @@
"z_e1,z_wr")
;;
-;; s390_agen_dep_p returns 1, if a register is set in the
+;; s390_agen_dep_p returns 1, if a register is set in the
;; first insn and used in the dependent insn to form a address.
;;
;;
;; If an instruction uses a register to address memory, it needs
;; to be set 5 cycles in advance.
-;;
+;;
-(define_bypass 5 "z_int,z_agen"
+(define_bypass 5 "z_int,z_agen"
"z_agen,z_la,z_call,z_load,z_store" "s390_agen_dep_p")
;;
-;; A load type instruction uses a bypass to feed the result back
-;; to the address generation pipeline stage.
+;; A load type instruction uses a bypass to feed the result back
+;; to the address generation pipeline stage.
;;
-(define_bypass 3 "z_load"
+(define_bypass 3 "z_load"
"z_agen,z_la,z_call,z_load,z_store" "s390_agen_dep_p")
;;
-;; A load address type instruction uses a bypass to feed the
-;; result back to the address generation pipeline stage.
+;; A load address type instruction uses a bypass to feed the
+;; result back to the address generation pipeline stage.
;;
-(define_bypass 2 "z_larl,z_la"
+(define_bypass 2 "z_larl,z_la"
"z_agen,z_la,z_call,z_load,z_store" "s390_agen_dep_p")
diff --git a/gcc/config/s390/2084.md b/gcc/config/s390/2084.md
index a72ae365734..38669c23a97 100644
--- a/gcc/config/s390/2084.md
+++ b/gcc/config/s390/2084.md
@@ -76,38 +76,38 @@
(define_insn_reservation "x_lr" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "lr"))
- "x-e1-st,x-wr-st")
+ "x-e1-st,x-wr-st")
-(define_insn_reservation "x_la" 1
+(define_insn_reservation "x_la" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "la"))
- "x-e1-st,x-wr-st")
+ "x-e1-st,x-wr-st")
-(define_insn_reservation "x_larl" 1
+(define_insn_reservation "x_larl" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "larl"))
- "x-e1-st,x-wr-st")
+ "x-e1-st,x-wr-st")
-(define_insn_reservation "x_load" 1
+(define_insn_reservation "x_load" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "load"))
- "x-e1-st+x-mem,x-wr-st")
+ "x-e1-st+x-mem,x-wr-st")
-(define_insn_reservation "x_store" 1
+(define_insn_reservation "x_store" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "store"))
- "x-e1-st+x_store_tok,x-wr-st")
+ "x-e1-st+x_store_tok,x-wr-st")
-(define_insn_reservation "x_branch" 1
+(define_insn_reservation "x_branch" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "branch"))
- "x_e1_r,x_wr_r")
+ "x_e1_r,x_wr_r")
-(define_insn_reservation "x_call" 5
+(define_insn_reservation "x_call" 5
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "jsr"))
"x-e1-np*5,x-wr-np")
-
+
(define_insn_reservation "x_mul_hi" 2
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "imulhi"))
@@ -123,162 +123,162 @@
(eq_attr "type" "idiv"))
"x-e1-np*10,x-wr-np")
-(define_insn_reservation "x_sem" 17
+(define_insn_reservation "x_sem" 17
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "sem"))
- "x-e1-np+x-mem,x-e1-np*16,x-wr-st")
+ "x-e1-np+x-mem,x-e1-np*16,x-wr-st")
;;
;; Multicycle insns
;;
-(define_insn_reservation "x_cs" 1
+(define_insn_reservation "x_cs" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "cs"))
- "x-e1-np,x-wr-np")
+ "x-e1-np,x-wr-np")
-(define_insn_reservation "x_vs" 1
+(define_insn_reservation "x_vs" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "vs"))
- "x-e1-np*10,x-wr-np")
+ "x-e1-np*10,x-wr-np")
-(define_insn_reservation "x_stm" 1
+(define_insn_reservation "x_stm" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "stm"))
- "(x-e1-np+x_store_tok)*10,x-wr-np")
+ "(x-e1-np+x_store_tok)*10,x-wr-np")
-(define_insn_reservation "x_lm" 1
+(define_insn_reservation "x_lm" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "lm"))
- "x-e1-np*10,x-wr-np")
+ "x-e1-np*10,x-wr-np")
-(define_insn_reservation "x_other" 1
+(define_insn_reservation "x_other" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "other"))
- "x-e1-np,x-wr-np")
+ "x-e1-np,x-wr-np")
;;
;; Floating point insns
;;
-(define_insn_reservation "x_fsimptf" 7
+(define_insn_reservation "x_fsimptf" 7
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "fsimptf"))
- "x_e1_t*2,x-wr-fp")
+ "x_e1_t*2,x-wr-fp")
-(define_insn_reservation "x_fsimpdf" 6
+(define_insn_reservation "x_fsimpdf" 6
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "fsimpdf,fmuldf"))
- "x_e1_t,x-wr-fp")
+ "x_e1_t,x-wr-fp")
-(define_insn_reservation "x_fsimpsf" 6
+(define_insn_reservation "x_fsimpsf" 6
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "fsimpsf,fmulsf"))
- "x_e1_t,x-wr-fp")
+ "x_e1_t,x-wr-fp")
(define_insn_reservation "x_fmultf" 33
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "fmultf"))
- "x_e1_t*27,x-wr-fp")
+ "x_e1_t*27,x-wr-fp")
(define_insn_reservation "x_fdivtf" 82
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "fdivtf,fsqrttf"))
- "x_e1_t*76,x-wr-fp")
+ "x_e1_t*76,x-wr-fp")
(define_insn_reservation "x_fdivdf" 36
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "fdivdf,fsqrtdf"))
- "x_e1_t*30,x-wr-fp")
+ "x_e1_t*30,x-wr-fp")
-(define_insn_reservation "x_fdivsf" 36
+(define_insn_reservation "x_fdivsf" 36
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "fdivsf,fsqrtsf"))
- "x_e1_t*30,x-wr-fp")
+ "x_e1_t*30,x-wr-fp")
-(define_insn_reservation "x_floadtf" 6
+(define_insn_reservation "x_floadtf" 6
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "floadtf"))
- "x_e1_t,x-wr-fp")
+ "x_e1_t,x-wr-fp")
-(define_insn_reservation "x_floaddf" 6
+(define_insn_reservation "x_floaddf" 6
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "floaddf"))
- "x_e1_t,x-wr-fp")
+ "x_e1_t,x-wr-fp")
-(define_insn_reservation "x_floadsf" 6
+(define_insn_reservation "x_floadsf" 6
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "floadsf"))
- "x_e1_t,x-wr-fp")
+ "x_e1_t,x-wr-fp")
-(define_insn_reservation "x_fstoredf" 1
+(define_insn_reservation "x_fstoredf" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "fstoredf"))
- "x_e1_t,x-wr-fp")
+ "x_e1_t,x-wr-fp")
-(define_insn_reservation "x_fstoresf" 1
+(define_insn_reservation "x_fstoresf" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "fstoresf"))
- "x_e1_t,x-wr-fp")
+ "x_e1_t,x-wr-fp")
(define_insn_reservation "x_ftrunctf" 16
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "ftrunctf"))
- "x_e1_t*10,x-wr-fp")
+ "x_e1_t*10,x-wr-fp")
(define_insn_reservation "x_ftruncdf" 11
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "ftruncdf"))
- "x_e1_t*5,x-wr-fp")
+ "x_e1_t*5,x-wr-fp")
-(define_insn_reservation "x_ftoi" 1
+(define_insn_reservation "x_ftoi" 1
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "ftoi"))
- "x_e1_t*3,x-wr-fp")
+ "x_e1_t*3,x-wr-fp")
-(define_insn_reservation "x_itof" 7
+(define_insn_reservation "x_itof" 7
(and (eq_attr "cpu" "z990,z9_109")
(eq_attr "type" "itoftf,itofdf,itofsf"))
- "x_e1_t*3,x-wr-fp")
+ "x_e1_t*3,x-wr-fp")
(define_bypass 1 "x_fsimpdf" "x_fstoredf")
(define_bypass 1 "x_fsimpsf" "x_fstoresf")
(define_bypass 1 "x_floaddf" "x_fsimpdf,x_fstoredf,x_floaddf")
-
+
(define_bypass 1 "x_floadsf" "x_fsimpsf,x_fstoresf,x_floadsf")
;;
-;; s390_agen_dep_p returns 1, if a register is set in the
+;; s390_agen_dep_p returns 1, if a register is set in the
;; first insn and used in the dependent insn to form a address.
;;
;;
;; If an instruction uses a register to address memory, it needs
;; to be set 5 cycles in advance.
-;;
+;;
-(define_bypass 5 "x_int,x_agen,x_lr"
+(define_bypass 5 "x_int,x_agen,x_lr"
"x_agen,x_la,x_branch,x_call,x_load,x_store,x_cs,x_stm,x_lm,x_other"
"s390_agen_dep_p")
-(define_bypass 9 "x_int,x_agen,x_lr"
+(define_bypass 9 "x_int,x_agen,x_lr"
"x_floadtf, x_floaddf, x_floadsf, x_fstoredf, x_fstoresf,\
x_fsimpdf, x_fsimpsf, x_fdivdf, x_fdivsf"
"s390_agen_dep_p")
;;
-;; A load type instruction uses a bypass to feed the result back
-;; to the address generation pipeline stage.
+;; A load type instruction uses a bypass to feed the result back
+;; to the address generation pipeline stage.
;;
-(define_bypass 4 "x_load"
+(define_bypass 4 "x_load"
"x_agen,x_la,x_branch,x_call,x_load,x_store,x_cs,x_stm,x_lm,x_other"
"s390_agen_dep_p")
@@ -288,11 +288,11 @@
"s390_agen_dep_p")
;;
-;; A load address type instruction uses a bypass to feed the
-;; result back to the address generation pipeline stage.
+;; A load address type instruction uses a bypass to feed the
+;; result back to the address generation pipeline stage.
;;
-(define_bypass 3 "x_larl,x_la"
+(define_bypass 3 "x_larl,x_la"
"x_agen,x_la,x_branch,x_call,x_load,x_store,x_cs,x_stm,x_lm,x_other"
"s390_agen_dep_p")
diff --git a/gcc/config/s390/constraints.md b/gcc/config/s390/constraints.md
index 6cc33d1cf8a..8fec7e124a6 100644
--- a/gcc/config/s390/constraints.md
+++ b/gcc/config/s390/constraints.md
@@ -76,27 +76,27 @@
;; Register constraints.
;;
-(define_register_constraint "a"
+(define_register_constraint "a"
"ADDR_REGS"
"Any address register from 1 to 15.")
-(define_register_constraint "c"
+(define_register_constraint "c"
"CC_REGS"
"Condition code register 33")
-(define_register_constraint "d"
+(define_register_constraint "d"
"GENERAL_REGS"
"Any register from 0 to 15")
-(define_register_constraint "f"
+(define_register_constraint "f"
"FP_REGS"
"Floating point registers")
-(define_register_constraint "t"
+(define_register_constraint "t"
"ACCESS_REGS"
"@internal
Access registers 36 and 37")
@@ -187,9 +187,9 @@
;; is specified instead of a part number, the constraint matches
;; if there is any single part with non-default value.
;;
-;; The following patterns define only those constraints that are actually
-;; used in s390.md. If you need an additional one, simply add it in the
-;; obvious way. Function s390_N_constraint_str is ready to handle all
+;; The following patterns define only those constraints that are actually
+;; used in s390.md. If you need an additional one, simply add it in the
+;; obvious way. Function s390_N_constraint_str is ready to handle all
;; combinations.
;;
@@ -409,53 +409,53 @@ constraint."
|| s390_mem_constraint (\"T\", op)"))
(define_memory_constraint "AQ"
- "@internal
+ "@internal
Offsettable memory reference without index register and with short displacement"
(match_test "s390_mem_constraint (\"AQ\", op)"))
(define_memory_constraint "AR"
- "@internal
+ "@internal
Offsettable memory reference with index register and short displacement"
(match_test "s390_mem_constraint (\"AR\", op)"))
(define_memory_constraint "AS"
- "@internal
+ "@internal
Offsettable memory reference without index register but with long displacement"
(match_test "s390_mem_constraint (\"AS\", op)"))
(define_memory_constraint "AT"
- "@internal
+ "@internal
Offsettable memory reference with index register and long displacement"
(match_test "s390_mem_constraint (\"AT\", op)"))
(define_constraint "BQ"
- "@internal
- Memory reference without index register and with short
+ "@internal
+ Memory reference without index register and with short
displacement that does *not* refer to a literal pool entry."
(match_test "s390_mem_constraint (\"BQ\", op)"))
(define_constraint "BR"
- "@internal
+ "@internal
Memory reference with index register and short displacement that
does *not* refer to a literal pool entry. "
(match_test "s390_mem_constraint (\"BR\", op)"))
(define_constraint "BS"
- "@internal
+ "@internal
Memory reference without index register but with long displacement
that does *not* refer to a literal pool entry. "
(match_test "s390_mem_constraint (\"BS\", op)"))
(define_constraint "BT"
- "@internal
+ "@internal
Memory reference with index register and long displacement that
does *not* refer to a literal pool entry. "
(match_test "s390_mem_constraint (\"BT\", op)"))
diff --git a/gcc/config/s390/fixdfdi.h b/gcc/config/s390/fixdfdi.h
index b6fb833e5d0..ddddf3a7c9c 100644
--- a/gcc/config/s390/fixdfdi.h
+++ b/gcc/config/s390/fixdfdi.h
@@ -63,12 +63,12 @@ __fixunstfdi (long double a1)
if (!EXPD (dl1) || SIGND(dl1))
return 0;
- /* The exponent - considered the binary point at the right end of
+ /* The exponent - considered the binary point at the right end of
the mantissa. */
exp = EXPD (dl1) - EXPONENT_BIAS - MANTISSA_BITS;
/* number < 1: If the mantissa would need to be right-shifted more bits than
- its size (plus the implied one bit on the left) the result would be
+ its size (plus the implied one bit on the left) the result would be
zero. */
if (exp <= -PRECISION)
return 0;
@@ -238,7 +238,7 @@ __fixunsdfdi (double a1)
/* shift down until exp < 12 or l = 0 */
if (exp > 0)
l <<= exp;
- else
+ else
l >>= -exp;
return l;
@@ -313,7 +313,7 @@ __fixdfdi (double a1)
/* shift down until exp < 12 or l = 0 */
if (exp > 0)
l <<= exp;
- else
+ else
l >>= -exp;
return (SIGND (dl1) ? -l : l);
@@ -381,7 +381,7 @@ __fixunssfdi (float a1)
if (exp > 0)
l <<= exp;
- else
+ else
l >>= -exp;
return l;
@@ -452,7 +452,7 @@ __fixsfdi (float a1)
if (exp > 0)
l <<= exp;
- else
+ else
l >>= -exp;
return (SIGN (fl1) ? -l : l);
diff --git a/gcc/config/s390/libgcc-glibc.ver b/gcc/config/s390/libgcc-glibc.ver
index 4832ba78ee3..6fc52e40d78 100644
--- a/gcc/config/s390/libgcc-glibc.ver
+++ b/gcc/config/s390/libgcc-glibc.ver
@@ -23,7 +23,7 @@
# to defer implementation of these routines to libgcc.so via DT_AUXILIARY.
# Note that we cannot use the default libgcc-glibc.ver file on s390x,
-# because GLIBC_2.0 does not exist on this architecture, as the first
+# because GLIBC_2.0 does not exist on this architecture, as the first
# ever glibc release on the platform was GLIBC_2.2.
%ifndef __s390x__
diff --git a/gcc/config/s390/s390-modes.def b/gcc/config/s390/s390-modes.def
index b701a550e8f..be2bf6ea798 100644
--- a/gcc/config/s390/s390-modes.def
+++ b/gcc/config/s390/s390-modes.def
@@ -45,8 +45,8 @@ Signed compares
CCS: EQ LT GT UNORDERED (LTGFR, LTGR, LTR, ICM/Y,
LTDBR, LTDR, LTEBR, LTER,
- CG/R, C/R/Y, CGHI, CHI,
- CDB/R, CD/R, CEB/R, CE/R,
+ CG/R, C/R/Y, CGHI, CHI,
+ CDB/R, CD/R, CEB/R, CE/R,
ADB/R, AEB/R, SDB/R, SEB/R,
SRAG, SRA, SRDA)
CCSR: EQ GT LT UNORDERED (CGF/R, CH/Y)
@@ -60,7 +60,7 @@ CCAN: EQ LT GT GT (AGHI, AHI)
Condition codes of unsigned adds and subs
CCL: EQ NE EQ NE (ALGF/R, ALG/R, AL/R/Y,
- ALCG/R, ALC/R,
+ ALCG/R, ALC/R,
SLGF/R, SLG/R, SL/R/Y,
SLBG/R, SLB/R)
CCL1: GEU GEU LTU LTU (ALG/R, AL/R/Y)
@@ -69,14 +69,14 @@ CCL3: EQ LTU EQ GTU (SLG/R, SL/R/Y)
Test under mask checks
-CCT: EQ NE NE NE (ICM/Y, TML, CG/R, CGHI,
+CCT: EQ NE NE NE (ICM/Y, TML, CG/R, CGHI,
C/R/Y, CHI, NG/R, N/R/Y,
OG/R, O/R/Y, XG/R, X/R/Y)
CCT1: NE EQ NE NE (TMH, TML)
CCT2: NE NE EQ NE (TMH, TML)
CCT3: NE NE NE EQ (TMH, TML)
-CCA and CCT modes are request only modes. These modes are never returned by
+CCA and CCT modes are request only modes. These modes are never returned by
s390_select_cc_mode. They are only intended to match other modes.
Requested mode -> Destination CC register mode
@@ -89,11 +89,11 @@ CCA -> CCAP, CCAN
CCAP, CCAN
-The CC obtained from add instruction usually can't be used for comparisons
+The CC obtained from add instruction usually can't be used for comparisons
because its coupling with overflow flag. In case of an overflow the
less than/greater than data are lost. Nevertheless a comparison can be done
whenever immediate values are involved because they are known at compile time.
-If you know whether the used constant is positive or negative you can predict
+If you know whether the used constant is positive or negative you can predict
the sign of the result even in case of an overflow.
@@ -103,7 +103,7 @@ If bits of an integer masked with an AND instruction are checked, the test under
mask instructions turn out to be very handy for a set of special cases.
The simple cases are checks whether all masked bits are zero or ones:
- int a;
+ int a;
if ((a & (16 + 128)) == 0) -> CCT/CCZ
if ((a & (16 + 128)) == 16 + 128) -> CCT3
@@ -120,15 +120,15 @@ CCSR, CCUR
There are several instructions comparing 32 bit with 64-bit unsigned/signed
values. Such instructions can be considered to have a builtin zero/sign_extend.
-The problem is that in the RTL (to be canonical) the zero/sign extended operand
-has to be the first one but the machine instructions like it the other way
-around. The following both modes can be considered as CCS and CCU modes with
+The problem is that in the RTL (to be canonical) the zero/sign extended operand
+has to be the first one but the machine instructions like it the other way
+around. The following both modes can be considered as CCS and CCU modes with
exchanged operands.
CCL1, CCL2
-These modes represent the result of overflow checks.
+These modes represent the result of overflow checks.
if (a + b < a) -> CCL1 state of the carry bit (CC2 | CC3)
if (a - b > a) -> CCL2 state of the borrow bit (CC0 | CC1)
@@ -142,7 +142,7 @@ CCL3
A logical subtract instruction sets the borrow bit in case of an overflow.
The resulting condition code of those instructions is represented by the
-CCL3 mode. Together with the CCU mode this mode is used for jumpless
+CCL3 mode. Together with the CCU mode this mode is used for jumpless
implementations of several if-constructs - see s390_expand_addcc for more
details.
@@ -152,7 +152,7 @@ The compare and swap instructions sets the condition code to 0/1 if the
operands were equal/unequal. The CCZ1 mode ensures the result can be
effectively placed into a register.
-*/
+*/
CC_MODE (CCZ);
diff --git a/gcc/config/s390/s390-protos.h b/gcc/config/s390/s390-protos.h
index b410de538d0..2329138cf1f 100644
--- a/gcc/config/s390/s390-protos.h
+++ b/gcc/config/s390/s390-protos.h
@@ -22,7 +22,7 @@ along with GCC; see the file COPYING3. If not see
-/* Prototypes of functions used for constraint evaluation in
+/* Prototypes of functions used for constraint evaluation in
constraints.c. */
extern int s390_mem_constraint (const char *str, rtx op);
@@ -92,7 +92,7 @@ extern void s390_expand_cmpmem (rtx, rtx, rtx, rtx);
extern bool s390_expand_addcc (enum rtx_code, rtx, rtx, rtx, rtx, rtx);
extern bool s390_expand_insv (rtx, rtx, rtx, rtx);
extern void s390_expand_cs_hqi (enum machine_mode, rtx, rtx, rtx, rtx);
-extern void s390_expand_atomic (enum machine_mode, enum rtx_code,
+extern void s390_expand_atomic (enum machine_mode, enum rtx_code,
rtx, rtx, rtx, bool);
extern rtx s390_return_addr_rtx (int, rtx);
extern rtx s390_back_chain_rtx (void);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index b1cfad1adfe..d5c3c22a93c 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -56,7 +56,7 @@ along with GCC; see the file COPYING3. If not see
/* Define the specific costs for a given cpu. */
-struct processor_costs
+struct processor_costs
{
/* multiplication */
const int m; /* cost of an M instruction. */
@@ -94,7 +94,7 @@ struct processor_costs
const struct processor_costs *s390_cost;
static const
-struct processor_costs z900_cost =
+struct processor_costs z900_cost =
{
COSTS_N_INSNS (5), /* M */
COSTS_N_INSNS (10), /* MGHI */
@@ -126,7 +126,7 @@ struct processor_costs z900_cost =
};
static const
-struct processor_costs z990_cost =
+struct processor_costs z990_cost =
{
COSTS_N_INSNS (4), /* M */
COSTS_N_INSNS (2), /* MGHI */
@@ -158,7 +158,7 @@ struct processor_costs z990_cost =
};
static const
-struct processor_costs z9_109_cost =
+struct processor_costs z9_109_cost =
{
COSTS_N_INSNS (4), /* M */
COSTS_N_INSNS (2), /* MGHI */
@@ -252,7 +252,7 @@ HOST_WIDE_INT s390_warn_framesize = 0;
HOST_WIDE_INT s390_stack_size = 0;
HOST_WIDE_INT s390_stack_guard = 0;
-/* The following structure is embedded in the machine
+/* The following structure is embedded in the machine
specific part of struct function. */
struct GTY (()) s390_frame_layout
@@ -275,8 +275,8 @@ struct GTY (()) s390_frame_layout
int last_save_gpr;
int last_restore_gpr;
- /* Bits standing for floating point registers. Set, if the
- respective register has to be saved. Starting with reg 16 (f0)
+ /* Bits standing for floating point registers. Set, if the
+ respective register has to be saved. Starting with reg 16 (f0)
at the rightmost bit.
Bit 15 - 8 7 6 5 4 3 2 1 0
fpr 15 - 8 7 5 3 1 6 4 2 0
@@ -400,7 +400,7 @@ s390_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
case CCZ1mode:
if (m2 == CCZmode)
return m1;
-
+
return VOIDmode;
default:
@@ -510,7 +510,7 @@ s390_tm_ccmode (rtx op1, rtx op2, bool mixed)
if (INTVAL (op2) == 0)
return CCTmode;
- /* Selected bits all one: CC3.
+ /* Selected bits all one: CC3.
e.g.: int a; if ((a & (16 + 128)) == 16 + 128) */
if (INTVAL (op2) == INTVAL (op1))
return CCT3mode;
@@ -582,7 +582,7 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
case GT:
/* The only overflow condition of NEG and ABS happens when
-INT_MAX is used as parameter, which stays negative. So
- we have an overflow from a positive value to a negative.
+ we have an overflow from a positive value to a negative.
Using CCAP mode the resulting cc can be used for comparisons. */
if ((GET_CODE (op0) == NEG || GET_CODE (op0) == ABS)
&& GET_MODE_CLASS (GET_MODE (op0)) == MODE_INT)
@@ -591,7 +591,7 @@ s390_select_ccmode (enum rtx_code code, rtx op0, rtx op1)
/* If constants are involved in an add instruction it is possible to use
the resulting cc for comparisons with zero. Knowing the sign of the
constant the overflow behavior gets predictable. e.g.:
- int a, b; if ((b = a + c) > 0)
+ int a, b; if ((b = a + c) > 0)
with c as a constant value: c < 0 -> CCAN and c >= 0 -> CCAP */
if (GET_CODE (op0) == PLUS && GET_CODE (XEXP (op0, 1)) == CONST_INT
&& CONST_OK_FOR_K (INTVAL (XEXP (op0, 1))))
@@ -714,7 +714,7 @@ s390_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
&& GET_CODE (*op1) == CONST_INT
&& INTVAL (*op1) == 0xffff
&& SCALAR_INT_MODE_P (GET_MODE (*op0))
- && (nonzero_bits (*op0, GET_MODE (*op0))
+ && (nonzero_bits (*op0, GET_MODE (*op0))
& ~(unsigned HOST_WIDE_INT) 0xffff) == 0)
{
*op0 = gen_lowpart (HImode, *op0);
@@ -822,7 +822,7 @@ s390_emit_compare (enum rtx_code code, rtx op0, rtx op1)
emit_insn (gen_rtx_SET (VOIDmode, cc, gen_rtx_COMPARE (mode, op0, op1)));
}
- return gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx);
+ return gen_rtx_fmt_ee (code, VOIDmode, cc, const0_rtx);
}
/* Emit a SImode compare and swap instruction setting MEM to NEW_RTX if OLD
@@ -1296,9 +1296,9 @@ s390_overlap_p (rtx mem1, rtx mem2, HOST_WIDE_INT size)
/* This overlapping check is used by peepholes merging memory block operations.
Overlapping operations would otherwise be recognized by the S/390 hardware
- and would fall back to a slower implementation. Allowing overlapping
+ and would fall back to a slower implementation. Allowing overlapping
operations would lead to slow code but not to wrong code. Therefore we are
- somewhat optimistic if we cannot prove that the memory blocks are
+ somewhat optimistic if we cannot prove that the memory blocks are
overlapping.
That's why we return false here although this may accept operations on
overlapping memory areas. */
@@ -1621,7 +1621,7 @@ override_options (void)
error ("stack size must not be greater than 64k");
}
else if (s390_stack_guard)
- error ("-mstack-guard implies use of -mstack-size");
+ error ("-mstack-guard implies use of -mstack-size");
#ifdef TARGET_DEFAULT_LONG_DOUBLE_128
if (!(target_flags_explicit & MASK_LONG_DOUBLE_128))
@@ -1804,7 +1804,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
{
case UNSPEC_LTREF:
if (!disp)
- disp = gen_rtx_UNSPEC (Pmode,
+ disp = gen_rtx_UNSPEC (Pmode,
gen_rtvec (1, XVECEXP (base, 0, 0)),
UNSPEC_LTREL_OFFSET);
else
@@ -1824,8 +1824,8 @@ s390_decompose_address (rtx addr, struct s390_address *out)
return false;
}
- if (!REG_P (base)
- || (GET_MODE (base) != SImode
+ if (!REG_P (base)
+ || (GET_MODE (base) != SImode
&& GET_MODE (base) != Pmode))
return false;
@@ -1852,7 +1852,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
{
case UNSPEC_LTREF:
if (!disp)
- disp = gen_rtx_UNSPEC (Pmode,
+ disp = gen_rtx_UNSPEC (Pmode,
gen_rtvec (1, XVECEXP (indx, 0, 0)),
UNSPEC_LTREL_OFFSET);
else
@@ -1872,7 +1872,7 @@ s390_decompose_address (rtx addr, struct s390_address *out)
return false;
}
- if (!REG_P (indx)
+ if (!REG_P (indx)
|| (GET_MODE (indx) != SImode
&& GET_MODE (indx) != Pmode))
return false;
@@ -1904,21 +1904,21 @@ s390_decompose_address (rtx addr, struct s390_address *out)
/* Validate displacement. */
if (!disp)
{
- /* If virtual registers are involved, the displacement will change later
- anyway as the virtual registers get eliminated. This could make a
- valid displacement invalid, but it is more likely to make an invalid
- displacement valid, because we sometimes access the register save area
+ /* If virtual registers are involved, the displacement will change later
+ anyway as the virtual registers get eliminated. This could make a
+ valid displacement invalid, but it is more likely to make an invalid
+ displacement valid, because we sometimes access the register save area
via negative offsets to one of those registers.
Thus we don't check the displacement for validity here. If after
elimination the displacement turns out to be invalid after all,
this is fixed up by reload in any case. */
- if (base != arg_pointer_rtx
- && indx != arg_pointer_rtx
- && base != return_address_pointer_rtx
+ if (base != arg_pointer_rtx
+ && indx != arg_pointer_rtx
+ && base != return_address_pointer_rtx
&& indx != return_address_pointer_rtx
- && base != frame_pointer_rtx
+ && base != frame_pointer_rtx
&& indx != frame_pointer_rtx
- && base != virtual_stack_vars_rtx
+ && base != virtual_stack_vars_rtx
&& indx != virtual_stack_vars_rtx)
if (!DISP_IN_RANGE (offset))
return false;
@@ -2271,8 +2271,8 @@ s390_float_const_zero_p (rtx value)
/* Compute a (partial) cost for rtx X. Return true if the complete
cost has been computed, and false if subexpressions should be
- scanned. In either case, *TOTAL contains the cost result.
- CODE contains GET_CODE (x), OUTER_CODE contains the code
+ scanned. In either case, *TOTAL contains the cost result.
+ CODE contains GET_CODE (x), OUTER_CODE contains the code
of the superexpression of x. */
static bool
@@ -2323,7 +2323,7 @@ s390_rtx_costs (rtx x, int code, int outer_code, int *total,
*total = COSTS_N_INSNS (1);
return false;
- case MULT:
+ case MULT:
switch (GET_MODE (x))
{
case SImode:
@@ -3104,11 +3104,11 @@ s390_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
}
else
{
- if (ad.base
+ if (ad.base
&& !(REGNO (ad.base) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (ad.base)) == ADDR_REGS))
return false;
-
+
if (ad.indx
&& !(REGNO (ad.indx) >= FIRST_PSEUDO_REGISTER
|| REGNO_REG_CLASS (REGNO (ad.indx)) == ADDR_REGS))
@@ -3354,7 +3354,7 @@ legitimize_pic_address (rtx orig, rtx reg)
gcc_unreachable ();
}
}
- else
+ else
gcc_assert (GET_CODE (addr) == PLUS);
}
if (GET_CODE (addr) == PLUS)
@@ -3743,7 +3743,7 @@ s390_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
return x;
}
else if (GET_CODE (x) == PLUS
- && (TLS_SYMBOLIC_CONST (XEXP (x, 0))
+ && (TLS_SYMBOLIC_CONST (XEXP (x, 0))
|| TLS_SYMBOLIC_CONST (XEXP (x, 1))))
{
return x;
@@ -3822,7 +3822,7 @@ s390_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
MODE is the mode of the enclosing MEM. OPNUM is the operand number
and TYPE is the reload type of the current reload. */
-rtx
+rtx
legitimize_reload_address (rtx ad, enum machine_mode mode ATTRIBUTE_UNUSED,
int opnum, int type)
{
@@ -3854,7 +3854,7 @@ legitimize_reload_address (rtx ad, enum machine_mode mode ATTRIBUTE_UNUSED,
new_rtx = gen_rtx_PLUS (Pmode, tem, GEN_INT (lower));
push_reload (XEXP (tem, 1), 0, &XEXP (tem, 1), 0,
- BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
+ BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
opnum, (enum reload_type) type);
return new_rtx;
}
@@ -3952,7 +3952,7 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
return;
gcc_assert (GET_CODE (val) == CONST_INT || GET_MODE (val) == QImode);
-
+
if (GET_CODE (len) == CONST_INT && INTVAL (len) > 0 && INTVAL (len) <= 257)
{
if (val == const0_rtx && INTVAL (len) <= 256)
@@ -3961,7 +3961,7 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
{
/* Initialize memory by storing the first byte. */
emit_move_insn (adjust_address (dst, QImode, 0), val);
-
+
if (INTVAL (len) > 1)
{
/* Initiate 1 byte overlap move.
@@ -3972,7 +3972,7 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
rtx dstp1 = adjust_address (dst, VOIDmode, 1);
set_mem_size (dst, const1_rtx);
- emit_insn (gen_movmem_short (dstp1, dst,
+ emit_insn (gen_movmem_short (dstp1, dst,
GEN_INT (INTVAL (len) - 2)));
}
}
@@ -4018,7 +4018,7 @@ s390_expand_setmem (rtx dst, rtx len, rtx val)
/* Initialize memory by storing the first byte. */
emit_move_insn (adjust_address (dst, QImode, 0), val);
-
+
/* If count is 1 we are done. */
emit_cmp_and_jump_insns (count, const1_rtx,
EQ, NULL_RTX, mode, 1, end_label);
@@ -4268,9 +4268,9 @@ s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
}
p = rtvec_alloc (2);
- RTVEC_ELT (p, 0) =
+ RTVEC_ELT (p, 0) =
gen_rtx_SET (VOIDmode, dst, op_res);
- RTVEC_ELT (p, 1) =
+ RTVEC_ELT (p, 1) =
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
@@ -4329,15 +4329,15 @@ s390_expand_addcc (enum rtx_code cmp_code, rtx cmp_op0, rtx cmp_op1,
if (!register_operand (src, GET_MODE (dst)))
src = force_reg (GET_MODE (dst), src);
- op_res = gen_rtx_MINUS (GET_MODE (dst),
- gen_rtx_MINUS (GET_MODE (dst), src, const0_rtx),
- gen_rtx_fmt_ee (cmp_code, GET_MODE (dst),
- gen_rtx_REG (cc_mode, CC_REGNUM),
+ op_res = gen_rtx_MINUS (GET_MODE (dst),
+ gen_rtx_MINUS (GET_MODE (dst), src, const0_rtx),
+ gen_rtx_fmt_ee (cmp_code, GET_MODE (dst),
+ gen_rtx_REG (cc_mode, CC_REGNUM),
const0_rtx));
p = rtvec_alloc (2);
- RTVEC_ELT (p, 0) =
+ RTVEC_ELT (p, 0) =
gen_rtx_SET (VOIDmode, dst, op_res);
- RTVEC_ELT (p, 1) =
+ RTVEC_ELT (p, 1) =
gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
emit_insn (gen_rtx_PARALLEL (VOIDmode, p));
@@ -4397,7 +4397,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
set_mem_size (dest, GEN_INT (size));
s390_expand_movmem (dest, src_mem, GEN_INT (size));
}
-
+
/* (set (ze (mem)) (reg)). */
else if (register_operand (src, word_mode))
{
@@ -4410,7 +4410,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
int stcmh_width = bitsize - GET_MODE_BITSIZE (SImode);
int size = stcmh_width / BITS_PER_UNIT;
- emit_move_insn (adjust_address (dest, SImode, size),
+ emit_move_insn (adjust_address (dest, SImode, size),
gen_lowpart (SImode, src));
set_mem_size (dest, GEN_INT (size));
emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest, GEN_INT
@@ -4427,7 +4427,7 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
/* (set (ze (reg)) (const_int)). */
if (TARGET_ZARCH
- && register_operand (dest, word_mode)
+ && register_operand (dest, word_mode)
&& (bitpos % 16) == 0
&& (bitsize % 16) == 0
&& const_int_operand (src, VOIDmode))
@@ -4447,9 +4447,9 @@ s390_expand_insv (rtx dest, rtx op1, rtx op2, rtx src)
putsize = GET_MODE_BITSIZE (putmode);
regpos -= putsize;
- emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest,
+ emit_move_insn (gen_rtx_ZERO_EXTRACT (word_mode, dest,
GEN_INT (putsize),
- GEN_INT (regpos)),
+ GEN_INT (regpos)),
gen_int_mode (val, putmode));
val >>= putsize;
}
@@ -4468,16 +4468,16 @@ s390_expand_mask_and_shift (rtx val, enum machine_mode mode, rtx count)
{
val = expand_simple_binop (SImode, AND, val, GEN_INT (GET_MODE_MASK (mode)),
NULL_RTX, 1, OPTAB_DIRECT);
- return expand_simple_binop (SImode, ASHIFT, val, count,
+ return expand_simple_binop (SImode, ASHIFT, val, count,
NULL_RTX, 1, OPTAB_DIRECT);
}
/* Structure to hold the initial parameters for a compare_and_swap operation
- in HImode and QImode. */
+ in HImode and QImode. */
struct alignment_context
{
- rtx memsi; /* SI aligned memory location. */
+ rtx memsi; /* SI aligned memory location. */
rtx shift; /* Bit offset with regard to lsb. */
rtx modemask; /* Mask of the HQImode shifted by SHIFT bits. */
rtx modemaski; /* ~modemask */
@@ -4529,7 +4529,7 @@ init_alignment_context (struct alignment_context *ac, rtx mem,
ac->shift = expand_simple_binop (SImode, MULT, ac->shift, GEN_INT (BITS_PER_UNIT),
NULL_RTX, 1, OPTAB_DIRECT);
/* Calculate masks. */
- ac->modemask = expand_simple_binop (SImode, ASHIFT,
+ ac->modemask = expand_simple_binop (SImode, ASHIFT,
GEN_INT (GET_MODE_MASK (mode)), ac->shift,
NULL_RTX, 1, OPTAB_DIRECT);
ac->modemaski = expand_simple_unop (SImode, NOT, ac->modemask, NULL_RTX, 1);
@@ -4567,9 +4567,9 @@ s390_expand_cs_hqi (enum machine_mode mode, rtx target, rtx mem, rtx cmp, rtx ne
/* Start CS loop. */
emit_label (csloop);
- /* val = "<mem>00..0<mem>"
+ /* val = "<mem>00..0<mem>"
* cmp = "00..0<cmp>00..0"
- * new = "00..0<new>00..0"
+ * new = "00..0<new>00..0"
*/
/* Patch cmp and new with val at correct position. */
@@ -4595,17 +4595,17 @@ s390_expand_cs_hqi (enum machine_mode mode, rtx target, rtx mem, rtx cmp, rtx ne
cmpv, newv));
/* Check for changes outside mode. */
- resv = expand_simple_binop (SImode, AND, res, ac.modemaski,
+ resv = expand_simple_binop (SImode, AND, res, ac.modemaski,
NULL_RTX, 1, OPTAB_DIRECT);
- cc = s390_emit_compare (NE, resv, val);
+ cc = s390_emit_compare (NE, resv, val);
emit_move_insn (val, resv);
/* Loop internal if so. */
s390_emit_jump (csloop, cc);
emit_label (csend);
-
+
/* Return the correct part of the bitfield. */
- convert_move (target, expand_simple_binop (SImode, LSHIFTRT, res, ac.shift,
+ convert_move (target, expand_simple_binop (SImode, LSHIFTRT, res, ac.shift,
NULL_RTX, 1, OPTAB_DIRECT), 1);
}
@@ -4659,7 +4659,7 @@ s390_expand_atomic (enum machine_mode mode, enum rtx_code code,
val = expand_simple_binop (SImode, AND, val, ac.modemask,
NULL_RTX, 1, OPTAB_DIRECT);
/* FALLTHRU */
- case SET:
+ case SET:
if (ac.aligned && MEM_P (val))
store_bit_field (new_rtx, GET_MODE_BITSIZE (mode), 0, SImode, val);
else
@@ -5511,8 +5511,8 @@ s390_split_branches (void)
}
-/* Find an annotated literal pool symbol referenced in RTX X,
- and store it at REF. Will abort if X contains references to
+/* Find an annotated literal pool symbol referenced in RTX X,
+ and store it at REF. Will abort if X contains references to
more than one such pool symbol; multiple references to the same
symbol are allowed, however.
@@ -5545,7 +5545,7 @@ find_constant_pool_ref (rtx x, rtx *ref)
if (*ref == NULL_RTX)
*ref = sym;
- else
+ else
gcc_assert (*ref == sym);
return;
@@ -5566,7 +5566,7 @@ find_constant_pool_ref (rtx x, rtx *ref)
}
}
-/* Replace every reference to the annotated literal pool
+/* Replace every reference to the annotated literal pool
symbol REF in X by its base plus OFFSET. */
static void
@@ -6511,7 +6511,7 @@ s390_chunkify_start (void)
for (curr_pool = pool_list; curr_pool; curr_pool = curr_pool->next)
{
- rtx new_insn = gen_reload_base (cfun->machine->base_reg,
+ rtx new_insn = gen_reload_base (cfun->machine->base_reg,
curr_pool->label);
rtx insn = curr_pool->first_insn;
INSN_ADDRESSES_NEW (emit_insn_before (new_insn, insn), -1);
@@ -6526,7 +6526,7 @@ s390_chunkify_start (void)
struct constant_pool *pool = s390_find_pool (pool_list, insn);
if (pool)
{
- rtx new_insn = gen_reload_base (cfun->machine->base_reg,
+ rtx new_insn = gen_reload_base (cfun->machine->base_reg,
pool->label);
INSN_ADDRESSES_NEW (emit_insn_after (new_insn, insn), -1);
}
@@ -6763,7 +6763,7 @@ find_unused_clobbered_reg (void)
}
-/* Helper function for s390_regs_ever_clobbered. Sets the fields in DATA for all
+/* Helper function for s390_regs_ever_clobbered. Sets the fields in DATA for all
clobbered hard regs in SETREG. */
static void
@@ -6821,8 +6821,8 @@ s390_regs_ever_clobbered (int *regs_ever_clobbered)
deal with this automatically. */
if (crtl->calls_eh_return || cfun->machine->has_landing_pad_p)
for (i = 0; EH_RETURN_DATA_REGNO (i) != INVALID_REGNUM ; i++)
- if (crtl->calls_eh_return
- || (cfun->machine->has_landing_pad_p
+ if (crtl->calls_eh_return
+ || (cfun->machine->has_landing_pad_p
&& df_regs_ever_live_p (EH_RETURN_DATA_REGNO (i))))
regs_ever_clobbered[EH_RETURN_DATA_REGNO (i)] = 1;
@@ -6841,16 +6841,16 @@ s390_regs_ever_clobbered (int *regs_ever_clobbered)
{
if (INSN_P (cur_insn))
note_stores (PATTERN (cur_insn),
- s390_reg_clobbered_rtx,
+ s390_reg_clobbered_rtx,
regs_ever_clobbered);
}
}
}
-/* Determine the frame area which actually has to be accessed
- in the function epilogue. The values are stored at the
+/* Determine the frame area which actually has to be accessed
+ in the function epilogue. The values are stored at the
given pointers AREA_BOTTOM (address of the lowest used stack
- address) and AREA_TOP (address of the first item which does
+ address) and AREA_TOP (address of the first item which does
not belong to the stack frame). */
static void
@@ -6884,7 +6884,7 @@ s390_frame_area (int *area_bottom, int *area_top)
b = MIN (b, cfun_frame_layout.f4_offset + (i - 2) * 8);
t = MAX (t, cfun_frame_layout.f4_offset + (i - 1) * 8);
}
-
+
*area_bottom = b;
*area_top = t;
}
@@ -6923,10 +6923,10 @@ s390_register_info (int clobbered_regs[])
clobbered_regs[HARD_FRAME_POINTER_REGNUM] = 1;
if (flag_pic)
- clobbered_regs[PIC_OFFSET_TABLE_REGNUM]
+ clobbered_regs[PIC_OFFSET_TABLE_REGNUM]
|= df_regs_ever_live_p (PIC_OFFSET_TABLE_REGNUM);
- clobbered_regs[BASE_REGNUM]
+ clobbered_regs[BASE_REGNUM]
|= (cfun->machine->base_reg
&& REGNO (cfun->machine->base_reg) == BASE_REGNUM);
@@ -6969,8 +6969,8 @@ s390_register_info (int clobbered_regs[])
cfun_frame_layout.first_save_gpr_slot = i;
cfun_frame_layout.last_save_gpr_slot = j;
- for (i = cfun_frame_layout.first_save_gpr_slot;
- i < cfun_frame_layout.last_save_gpr_slot + 1;
+ for (i = cfun_frame_layout.first_save_gpr_slot;
+ i < cfun_frame_layout.last_save_gpr_slot + 1;
i++)
if (clobbered_regs[i])
break;
@@ -6978,7 +6978,7 @@ s390_register_info (int clobbered_regs[])
for (j = cfun_frame_layout.last_save_gpr_slot; j > i; j--)
if (clobbered_regs[j])
break;
-
+
if (i == cfun_frame_layout.last_save_gpr_slot + 1)
{
/* Nothing to save/restore. */
@@ -7058,7 +7058,7 @@ s390_frame_info (void)
cfun_frame_layout.frame_size = get_frame_size ();
if (!TARGET_64BIT && cfun_frame_layout.frame_size > 0x7fff0000)
fatal_error ("total size of local variables exceeds architecture limit");
-
+
if (!TARGET_PACKED_STACK)
{
cfun_frame_layout.backchain_offset = 0;
@@ -7072,46 +7072,46 @@ s390_frame_info (void)
{
cfun_frame_layout.backchain_offset = (STACK_POINTER_OFFSET
- UNITS_PER_WORD);
- cfun_frame_layout.gprs_offset
- = (cfun_frame_layout.backchain_offset
+ cfun_frame_layout.gprs_offset
+ = (cfun_frame_layout.backchain_offset
- (STACK_POINTER_REGNUM - cfun_frame_layout.first_save_gpr_slot + 1)
* UNITS_PER_WORD);
-
+
if (TARGET_64BIT)
{
- cfun_frame_layout.f4_offset
+ cfun_frame_layout.f4_offset
= (cfun_frame_layout.gprs_offset
- 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
-
- cfun_frame_layout.f0_offset
- = (cfun_frame_layout.f4_offset
+
+ cfun_frame_layout.f0_offset
+ = (cfun_frame_layout.f4_offset
- 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
}
else
{
/* On 31 bit we have to care about alignment of the
floating point regs to provide fastest access. */
- cfun_frame_layout.f0_offset
- = ((cfun_frame_layout.gprs_offset
+ cfun_frame_layout.f0_offset
+ = ((cfun_frame_layout.gprs_offset
& ~(STACK_BOUNDARY / BITS_PER_UNIT - 1))
- 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
-
- cfun_frame_layout.f4_offset
+
+ cfun_frame_layout.f4_offset
= (cfun_frame_layout.f0_offset
- 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
}
}
else /* no backchain */
{
- cfun_frame_layout.f4_offset
+ cfun_frame_layout.f4_offset
= (STACK_POINTER_OFFSET
- 8 * (cfun_fpr_bit_p (2) + cfun_fpr_bit_p (3)));
-
- cfun_frame_layout.f0_offset
+
+ cfun_frame_layout.f0_offset
= (cfun_frame_layout.f4_offset
- 8 * (cfun_fpr_bit_p (0) + cfun_fpr_bit_p (1)));
-
- cfun_frame_layout.gprs_offset
+
+ cfun_frame_layout.gprs_offset
= cfun_frame_layout.f0_offset - cfun_gprs_save_area_size;
}
@@ -7132,7 +7132,7 @@ s390_frame_info (void)
if (TARGET_BACKCHAIN)
cfun_frame_layout.frame_size += UNITS_PER_WORD;
- /* No alignment trouble here because f8-f15 are only saved under
+ /* No alignment trouble here because f8-f15 are only saved under
64 bit. */
cfun_frame_layout.f8_offset = (MIN (MIN (cfun_frame_layout.f0_offset,
cfun_frame_layout.f4_offset),
@@ -7144,9 +7144,9 @@ s390_frame_info (void)
for (i = 0; i < 8; i++)
if (cfun_fpr_bit_p (i))
cfun_frame_layout.frame_size += 8;
-
+
cfun_frame_layout.frame_size += cfun_gprs_save_area_size;
-
+
/* If under 31 bit an odd number of gprs has to be saved we have to adjust
the frame size to sustain 8 byte alignment of stack frames. */
cfun_frame_layout.frame_size = ((cfun_frame_layout.frame_size +
@@ -7213,11 +7213,11 @@ s390_update_frame_layout (void)
s390_register_info (clobbered_regs);
- df_set_regs_ever_live (BASE_REGNUM,
+ df_set_regs_ever_live (BASE_REGNUM,
clobbered_regs[BASE_REGNUM] ? true : false);
- df_set_regs_ever_live (RETURN_REGNUM,
+ df_set_regs_ever_live (RETURN_REGNUM,
clobbered_regs[RETURN_REGNUM] ? true : false);
- df_set_regs_ever_live (STACK_POINTER_REGNUM,
+ df_set_regs_ever_live (STACK_POINTER_REGNUM,
clobbered_regs[STACK_POINTER_REGNUM] ? true : false);
if (cfun->machine->base_reg)
@@ -7249,10 +7249,10 @@ s390_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
case GENERAL_REGS:
if (REGNO_PAIR_OK (regno, mode))
{
- if (TARGET_64BIT
+ if (TARGET_64BIT
|| (mode != TFmode && mode != TCmode && mode != TDmode))
return true;
- }
+ }
break;
case CC_REGS:
if (GET_MODE_CLASS (mode) == MODE_CC)
@@ -7268,7 +7268,7 @@ s390_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
default:
return false;
}
-
+
return false;
}
@@ -7365,7 +7365,7 @@ s390_initial_elimination_offset (int from, int to)
switch (from)
{
case FRAME_POINTER_REGNUM:
- offset = (get_frame_size()
+ offset = (get_frame_size()
+ STACK_POINTER_OFFSET
+ crtl->outgoing_args_size);
break;
@@ -7460,7 +7460,7 @@ save_gprs (rtx base, int offset, int first, int last)
for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
{
rtx mem = XEXP (XVECEXP (PATTERN (insn), 0, i), 0);
-
+
if (first + i <= 6)
set_mem_alias_set (mem, get_varargs_alias_set ());
}
@@ -7624,8 +7624,8 @@ s390_emit_prologue (void)
/* Choose best register to use for temp use within prologue.
See below for why TPF must use the register 1. */
- if (!has_hard_reg_initial_val (Pmode, RETURN_REGNUM)
- && !current_function_is_leaf
+ if (!has_hard_reg_initial_val (Pmode, RETURN_REGNUM)
+ && !current_function_is_leaf
&& !TARGET_TPF_PROFILING)
temp_reg = gen_rtx_REG (Pmode, RETURN_REGNUM);
else
@@ -7634,11 +7634,11 @@ s390_emit_prologue (void)
/* Save call saved gprs. */
if (cfun_frame_layout.first_save_gpr != -1)
{
- insn = save_gprs (stack_pointer_rtx,
- cfun_frame_layout.gprs_offset +
- UNITS_PER_WORD * (cfun_frame_layout.first_save_gpr
+ insn = save_gprs (stack_pointer_rtx,
+ cfun_frame_layout.gprs_offset +
+ UNITS_PER_WORD * (cfun_frame_layout.first_save_gpr
- cfun_frame_layout.first_save_gpr_slot),
- cfun_frame_layout.first_save_gpr,
+ cfun_frame_layout.first_save_gpr,
cfun_frame_layout.last_save_gpr);
emit_insn (insn);
}
@@ -7691,14 +7691,14 @@ s390_emit_prologue (void)
if (cfun_fpr_bit_p (i))
{
insn = save_fpr (stack_pointer_rtx, offset, i + 16);
-
+
RTX_FRAME_RELATED_P (insn) = 1;
offset -= 8;
}
if (offset >= cfun_frame_layout.f8_offset)
next_fpr = i + 16;
}
-
+
if (!TARGET_PACKED_STACK)
next_fpr = cfun_save_high_fprs_p ? 31 : 0;
@@ -7750,9 +7750,9 @@ s390_emit_prologue (void)
}
}
- if (s390_warn_framesize > 0
+ if (s390_warn_framesize > 0
&& cfun_frame_layout.frame_size >= s390_warn_framesize)
- warning (0, "frame size of %qs is " HOST_WIDE_INT_PRINT_DEC " bytes",
+ warning (0, "frame size of %qs is " HOST_WIDE_INT_PRINT_DEC " bytes",
current_function_name (), cfun_frame_layout.frame_size);
if (s390_warn_dynamicstack_p && cfun->calls_alloca)
@@ -7767,7 +7767,7 @@ s390_emit_prologue (void)
if (DISP_IN_RANGE (INTVAL (frame_off)))
{
insn = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
- gen_rtx_PLUS (Pmode, stack_pointer_rtx,
+ gen_rtx_PLUS (Pmode, stack_pointer_rtx,
frame_off));
insn = emit_insn (insn);
}
@@ -7792,11 +7792,11 @@ s390_emit_prologue (void)
if (TARGET_BACKCHAIN)
{
if (cfun_frame_layout.backchain_offset)
- addr = gen_rtx_MEM (Pmode,
- plus_constant (stack_pointer_rtx,
+ addr = gen_rtx_MEM (Pmode,
+ plus_constant (stack_pointer_rtx,
cfun_frame_layout.backchain_offset));
else
- addr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
+ addr = gen_rtx_MEM (Pmode, stack_pointer_rtx);
set_mem_alias_set (addr, get_frame_alias_set ());
insn = emit_insn (gen_move_insn (addr, temp_reg));
}
@@ -7821,7 +7821,7 @@ s390_emit_prologue (void)
moved below the use of the stack slots. */
s390_emit_stack_tie ();
- insn = emit_insn (gen_add2_insn (temp_reg,
+ insn = emit_insn (gen_add2_insn (temp_reg,
GEN_INT (cfun_frame_layout.f8_offset)));
offset = 0;
@@ -7833,7 +7833,7 @@ s390_emit_prologue (void)
cfun_frame_layout.frame_size
+ cfun_frame_layout.f8_offset
+ offset);
-
+
insn = save_fpr (temp_reg, offset, i);
offset += 8;
RTX_FRAME_RELATED_P (insn) = 1;
@@ -7904,7 +7904,7 @@ s390_emit_epilogue (bool sibcall)
/* Check whether to use frame or stack pointer for restore. */
- frame_pointer = (frame_pointer_needed
+ frame_pointer = (frame_pointer_needed
? hard_frame_pointer_rtx : stack_pointer_rtx);
s390_frame_area (&area_bottom, &area_top);
@@ -7962,7 +7962,7 @@ s390_emit_epilogue (bool sibcall)
}
}
}
-
+
}
else
{
@@ -7978,7 +7978,7 @@ s390_emit_epilogue (bool sibcall)
else if (!TARGET_PACKED_STACK)
next_offset += 8;
}
-
+
}
/* Return register. */
@@ -8010,7 +8010,7 @@ s390_emit_epilogue (bool sibcall)
if (global_regs[i])
{
addr = plus_constant (frame_pointer,
- offset + cfun_frame_layout.gprs_offset
+ offset + cfun_frame_layout.gprs_offset
+ (i - cfun_frame_layout.first_save_gpr_slot)
* UNITS_PER_WORD);
addr = gen_rtx_MEM (Pmode, addr);
@@ -8035,7 +8035,7 @@ s390_emit_epilogue (bool sibcall)
addr = plus_constant (frame_pointer,
offset + cfun_frame_layout.gprs_offset
- + (RETURN_REGNUM
+ + (RETURN_REGNUM
- cfun_frame_layout.first_save_gpr_slot)
* UNITS_PER_WORD);
addr = gen_rtx_MEM (Pmode, addr);
@@ -8046,7 +8046,7 @@ s390_emit_epilogue (bool sibcall)
insn = restore_gprs (frame_pointer,
offset + cfun_frame_layout.gprs_offset
- + (cfun_frame_layout.first_restore_gpr
+ + (cfun_frame_layout.first_restore_gpr
- cfun_frame_layout.first_save_gpr_slot)
* UNITS_PER_WORD,
cfun_frame_layout.first_restore_gpr,
@@ -8456,7 +8456,7 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
t = make_tree (TREE_TYPE (sav), return_address_pointer_rtx);
t = build2 (POINTER_PLUS_EXPR, TREE_TYPE (sav), t,
size_int (-RETURN_REGNUM * UNITS_PER_WORD));
-
+
t = build2 (MODIFY_EXPR, TREE_TYPE (sav), sav, t);
TREE_SIDE_EFFECTS (t) = 1;
expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
@@ -8488,7 +8488,7 @@ s390_va_start (tree valist, rtx nextarg ATTRIBUTE_UNUSED)
} */
static tree
-s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
+s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
gimple_seq *post_p ATTRIBUTE_UNUSED)
{
tree f_gpr, f_fpr, f_ovf, f_sav;
@@ -8588,9 +8588,9 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
t = build3 (COND_EXPR, void_type_node, t, u, NULL_TREE);
gimplify_and_add (t, pre_p);
- t = build2 (POINTER_PLUS_EXPR, ptr_type_node, sav,
+ t = build2 (POINTER_PLUS_EXPR, ptr_type_node, sav,
size_int (sav_ofs));
- u = build2 (MULT_EXPR, TREE_TYPE (reg), reg,
+ u = build2 (MULT_EXPR, TREE_TYPE (reg), reg,
fold_convert (TREE_TYPE (reg), size_int (sav_scale)));
t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t, fold_convert (sizetype, u));
@@ -8605,14 +8605,14 @@ s390_gimplify_va_arg (tree valist, tree type, gimple_seq *pre_p,
t = ovf;
if (size < UNITS_PER_WORD)
- t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t,
+ t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t,
size_int (UNITS_PER_WORD - size));
gimplify_expr (&t, pre_p, NULL, is_gimple_val, fb_rvalue);
gimplify_assign (addr, t, pre_p);
- t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t,
+ t = build2 (POINTER_PLUS_EXPR, ptr_type_node, t,
size_int (size));
gimplify_assign (ovf, t, pre_p);
@@ -9268,7 +9268,7 @@ s390_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
{
*p1 = CC_REGNUM;
*p2 = INVALID_REGNUM;
-
+
return true;
}
@@ -9434,10 +9434,10 @@ s390_optimize_prologue (void)
/* If all special registers are in fact used, there's nothing we
can do, so no point in walking the insn list. */
- if (cfun_frame_layout.first_save_gpr <= BASE_REGNUM
+ if (cfun_frame_layout.first_save_gpr <= BASE_REGNUM
&& cfun_frame_layout.last_save_gpr >= BASE_REGNUM
- && (TARGET_CPU_ZARCH
- || (cfun_frame_layout.first_save_gpr <= RETURN_REGNUM
+ && (TARGET_CPU_ZARCH
+ || (cfun_frame_layout.first_save_gpr <= RETURN_REGNUM
&& cfun_frame_layout.last_save_gpr >= RETURN_REGNUM)))
return;
@@ -9477,9 +9477,9 @@ s390_optimize_prologue (void)
if (cfun_frame_layout.first_save_gpr != -1)
{
- new_insn = save_gprs (base,
+ new_insn = save_gprs (base,
off + (cfun_frame_layout.first_save_gpr
- - first) * UNITS_PER_WORD,
+ - first) * UNITS_PER_WORD,
cfun_frame_layout.first_save_gpr,
cfun_frame_layout.last_save_gpr);
new_insn = emit_insn_before (new_insn, insn);
@@ -9538,9 +9538,9 @@ s390_optimize_prologue (void)
if (cfun_frame_layout.first_restore_gpr != -1)
{
- new_insn = restore_gprs (base,
+ new_insn = restore_gprs (base,
off + (cfun_frame_layout.first_restore_gpr
- - first) * UNITS_PER_WORD,
+ - first) * UNITS_PER_WORD,
cfun_frame_layout.first_restore_gpr,
cfun_frame_layout.last_restore_gpr);
new_insn = emit_insn_before (new_insn, insn);
diff --git a/gcc/config/s390/s390.h b/gcc/config/s390/s390.h
index 26bdd9e7493..f34b7f22567 100644
--- a/gcc/config/s390/s390.h
+++ b/gcc/config/s390/s390.h
@@ -180,7 +180,7 @@ extern int s390_arch_flags;
#define S390_TDC_POSITIVE_NORMALIZED_DFP_NUMBER (1 << 7)
#define S390_TDC_NEGATIVE_NORMALIZED_DFP_NUMBER (1 << 6)
-/* For signbit, the BFP-DFP-difference makes no difference. */
+/* For signbit, the BFP-DFP-difference makes no difference. */
#define S390_TDC_SIGNBIT_SET (S390_TDC_NEGATIVE_ZERO \
| S390_TDC_NEGATIVE_NORMALIZED_BFP_NUMBER \
| S390_TDC_NEGATIVE_DENORMALIZED_BFP_NUMBER\
@@ -298,10 +298,10 @@ if (INTEGRAL_MODE_P (MODE) && \
correspond to actual hardware:
Reg 32: Argument pointer
Reg 33: Condition code
- Reg 34: Frame pointer
+ Reg 34: Frame pointer
Reg 35: Return address pointer
- Registers 36 and 37 are mapped to access registers
+ Registers 36 and 37 are mapped to access registers
0 and 1, used to implement thread-local storage. */
#define FIRST_PSEUDO_REGISTER 38
@@ -455,7 +455,7 @@ if (INTEGRAL_MODE_P (MODE) && \
enum reg_class
{
NO_REGS, CC_REGS, ADDR_REGS, GENERAL_REGS, ACCESS_REGS,
- ADDR_CC_REGS, GENERAL_CC_REGS,
+ ADDR_CC_REGS, GENERAL_CC_REGS,
FP_REGS, ADDR_FP_REGS, GENERAL_FP_REGS,
ALL_REGS, LIM_REG_CLASSES
};
@@ -575,7 +575,7 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
the argument area. */
#define FIRST_PARM_OFFSET(FNDECL) 0
-/* Defining this macro makes __builtin_frame_address(0) and
+/* Defining this macro makes __builtin_frame_address(0) and
__builtin_return_address(0) work with -fomit-frame-pointer. */
#define INITIAL_FRAME_ADDRESS_RTX \
(plus_constant (arg_pointer_rtx, -STACK_POINTER_OFFSET))
@@ -615,7 +615,7 @@ extern const enum reg_class regclass_map[FIRST_PSEUDO_REGISTER];
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) ((N) < 4 ? (N) + 6 : INVALID_REGNUM)
#define EH_RETURN_HANDLER_RTX gen_rtx_MEM (Pmode, return_address_pointer_rtx)
-
+
/* Select a format to encode pointers in exception handling data. */
#define ASM_PREFERRED_EH_DATA_FORMAT(CODE, GLOBAL) \
(flag_pic \
@@ -807,7 +807,7 @@ do { \
#define SLOW_BYTE_ACCESS 1
/* An integer expression for the size in bits of the largest integer machine
- mode that should actually be used. We allow pairs of registers. */
+ mode that should actually be used. We allow pairs of registers. */
#define MAX_FIXED_MODE_SIZE GET_MODE_BITSIZE (TARGET_64BIT ? TImode : DImode)
/* The maximum number of bytes that a single instruction can move quickly
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 7c9a2b28100..17c36887e49 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -37,7 +37,7 @@
;; %N: print the second word of a DImode operand.
;; %M: print the second word of a TImode operand.
;; %Y: print shift count operand.
-;;
+;;
;; %b: print integer X as if it's an unsigned byte.
;; %c: print integer X as if it's an signed byte.
;; %x: print integer X as if it's an unsigned halfword.
@@ -154,7 +154,7 @@
(RETURN_REGNUM 14)
; Condition code register.
(CC_REGNUM 33)
- ; Thread local storage pointer register.
+ ; Thread local storage pointer register.
(TP_REGNUM 36)
])
@@ -220,7 +220,7 @@
;; reg: Instruction does not use the agen unit
(define_attr "atype" "agen,reg"
- (if_then_else (eq_attr "op_type" "E,RR,RI,RRE")
+ (if_then_else (eq_attr "op_type" "E,RR,RI,RRE")
(const_string "reg")
(const_string "agen")))
@@ -319,7 +319,7 @@
;; These mode iterators allow floating point patterns to be generated from the
;; same template.
-(define_mode_iterator FP_ALL [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")
+(define_mode_iterator FP_ALL [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")
(SD "TARGET_HARD_DFP")])
(define_mode_iterator FP [TF DF SF (TD "TARGET_HARD_DFP") (DD "TARGET_HARD_DFP")])
(define_mode_iterator FPALL [TF DF SF TD DD SD])
@@ -360,15 +360,15 @@
;; This iterator and attribute allow to combine most atomic operations.
(define_code_iterator ATOMIC [and ior xor plus minus mult])
-(define_code_attr atomic [(and "and") (ior "ior") (xor "xor")
+(define_code_attr atomic [(and "and") (ior "ior") (xor "xor")
(plus "add") (minus "sub") (mult "nand")])
-;; In FP templates, a string like "lt<de>br" will expand to "ltxbr" in
+;; In FP templates, a string like "lt<de>br" will expand to "ltxbr" in
;; TF/TDmode, "ltdbr" in DF/DDmode, and "ltebr" in SF/SDmode.
(define_mode_attr xde [(TF "x") (DF "d") (SF "e") (TD "x") (DD "d") (SD "e")])
-;; In FP templates, a <dee> in "m<dee><bt>r" will expand to "mx<bt>r" in
-;; TF/TDmode, "md<bt>r" in DF/DDmode, "mee<bt>r" in SFmode and "me<bt>r in
+;; In FP templates, a <dee> in "m<dee><bt>r" will expand to "mx<bt>r" in
+;; TF/TDmode, "md<bt>r" in DF/DDmode, "mee<bt>r" in SFmode and "me<bt>r in
;; SDmode.
(define_mode_attr xdee [(TF "x") (DF "d") (SF "ee") (TD "x") (DD "d") (SD "e")])
@@ -382,14 +382,14 @@
;; dfp variants in a single insn definition.
;; This attribute is used to set op_type accordingly.
-(define_mode_attr RRer [(TF "RRE") (DF "RRE") (SF "RRE") (TD "RRR")
+(define_mode_attr RRer [(TF "RRE") (DF "RRE") (SF "RRE") (TD "RRR")
(DD "RRR") (SD "RRR")])
-;; This attribute is used in the operand constraint list in order to have the
+;; This attribute is used in the operand constraint list in order to have the
;; first and the second operand match for bfp modes.
(define_mode_attr f0 [(TF "0") (DF "0") (SF "0") (TD "f") (DD "f") (DD "f")])
-;; This attribute is used in the operand list of the instruction to have an
+;; This attribute is used in the operand list of the instruction to have an
;; additional operand for the dfp instructions.
(define_mode_attr op1 [(TF "") (DF "") (SF "")
(TD "%1,") (DD "%1,") (SD "%1,")])
diff --git a/gcc/config/s390/tpf-unwind.h b/gcc/config/s390/tpf-unwind.h
index 4fd9ffaa103..33fd5f5c8c5 100644
--- a/gcc/config/s390/tpf-unwind.h
+++ b/gcc/config/s390/tpf-unwind.h
@@ -46,7 +46,7 @@ __isPATrange (void *addr)
/* TPF return address offset from start of stack frame. */
#define TPFRA_OFFSET 168
-/* Exceptions macro defined for TPF so that functions without
+/* Exceptions macro defined for TPF so that functions without
dwarf frame information can be used with exceptions. */
#define MD_FALLBACK_FRAME_STATE_FOR s390_fallback_frame_state
@@ -165,20 +165,20 @@ __tpf_eh_return (void *target)
/* Begin looping through stack frames. Stop if invalid
code information is retrieved or if a match between the
- current stack frame iteration shared object's address
+ current stack frame iteration shared object's address
matches that of the target, calculated above. */
do
{
/* Get return address based on our stackptr iterator. */
- current = (void *) *((unsigned long int *)
+ current = (void *) *((unsigned long int *)
(stackptr+RA_OFFSET));
/* Is it a Pat Stub? */
- if (__isPATrange (current))
+ if (__isPATrange (current))
{
- /* Yes it was, get real return address
+ /* Yes it was, get real return address
in TPF stack area. */
- current = (void *) *((unsigned long int *)
+ current = (void *) *((unsigned long int *)
(stackptr+TPFRA_OFFSET));
is_a_stub = 1;
}
@@ -198,7 +198,7 @@ __tpf_eh_return (void *target)
/* Yes! They are in the same module.
Force copy of TPF private stack area to
destination stack frame TPF private area. */
- destination_frame = (void *) *((unsigned long int *)
+ destination_frame = (void *) *((unsigned long int *)
(*PREVIOUS_STACK_PTR() + R15_OFFSET));
/* Copy TPF linkage area from current frame to
@@ -209,24 +209,24 @@ __tpf_eh_return (void *target)
/* Now overlay the
real target address into the TPF stack area of
the target frame we are jumping to. */
- *((unsigned long int *) (destination_frame +
+ *((unsigned long int *) (destination_frame +
TPFRA_OFFSET)) = (unsigned long int) target;
/* Before returning the desired pat stub address to
- the exception handling unwinder so that it can
- actually do the "leap" shift out the low order
+ the exception handling unwinder so that it can
+ actually do the "leap" shift out the low order
bit designated to determine if we are in 64BIT mode.
This is necessary for CTOA stubs.
- Otherwise we leap one byte past where we want to
+ Otherwise we leap one byte past where we want to
go to in the TPF pat stub linkage code. */
- shifter = *((unsigned long int *)
+ shifter = *((unsigned long int *)
(stackptr + RA_OFFSET));
shifter &= ~1ul;
/* Store Pat Stub Address in destination Stack Frame. */
*((unsigned long int *) (destination_frame +
- RA_OFFSET)) = shifter;
+ RA_OFFSET)) = shifter;
/* Re-adjust pat stub address to go to correct place
in linkage. */
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-protos.h b/gcc/config/sh/sh-protos.h
index fb896819b34..7e3f321c7b8 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -59,7 +59,6 @@ extern int fp_one_operand (rtx);
extern int fp_int_operand (rtx);
extern rtx get_fpscr_rtx (void);
extern bool sh_legitimate_index_p (enum machine_mode, rtx);
-extern bool sh_legitimate_address_p (enum machine_mode, rtx, bool);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern int nonpic_symbol_mentioned_p (rtx);
extern void emit_sf_insn (rtx);
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 3bf3e752755..f798696f80c 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -241,6 +241,7 @@ static bool sh_rtx_costs (rtx, int, int, int *, bool);
static int sh_address_cost (rtx, bool);
static int sh_pr_n_sets (void);
static rtx sh_allocate_initial_value (rtx);
+static bool sh_legitimate_address_p (enum machine_mode, rtx, bool);
static rtx sh_legitimize_address (rtx, rtx, enum machine_mode);
static int shmedia_target_regs_stack_space (HARD_REG_SET *);
static int shmedia_reserve_space_for_target_registers_p (int, HARD_REG_SET *);
@@ -483,6 +484,9 @@ static int sh2a_function_vector_p (tree);
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD sh_secondary_reload
+#undef TARGET_LEGITIMATE_ADDRESS_P
+#define TARGET_LEGITIMATE_ADDRESS_P sh_legitimate_address_p
+
/* Machine-specific symbol_ref flags. */
#define SYMBOL_FLAG_FUNCVEC_FUNCTION (SYMBOL_FLAG_MACH_DEP << 0)
@@ -1635,7 +1639,8 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
operands[2] = op2h;
operands[4] = NULL_RTX;
if (reload_completed
- && ! arith_reg_or_0_operand (op2h, SImode) && true_regnum (op1h)
+ && ! arith_reg_or_0_operand (op2h, SImode)
+ && (true_regnum (op1h) || (comparison != EQ && comparison != NE))
&& (msw_taken != LAST_AND_UNUSED_RTX_CODE
|| msw_skip != LAST_AND_UNUSED_RTX_CODE))
{
@@ -1665,8 +1670,12 @@ expand_cbranchdi4 (rtx *operands, enum rtx_code comparison)
if (lsw_taken != LAST_AND_UNUSED_RTX_CODE)
{
if (reload_completed
- && ! arith_reg_or_0_operand (op2l, SImode) && true_regnum (op1l))
- operands[4] = scratch;
+ && ! arith_reg_or_0_operand (op2l, SImode)
+ && (true_regnum (op1l) || (lsw_taken != EQ && lsw_taken != NE)))
+ {
+ emit_move_insn (scratch, operands[2]);
+ operands[2] = scratch;
+ }
expand_cbranchsi4 (operands, lsw_taken, lsw_taken_prob);
}
if (msw_skip != LAST_AND_UNUSED_RTX_CODE)
@@ -7049,6 +7058,8 @@ sh_set_return_address (rtx ra, rtx tmp)
tmp = gen_frame_mem (Pmode, tmp);
emit_insn (GEN_MOV (tmp, ra));
+ /* Tell this store isn't dead. */
+ emit_use (tmp);
}
/* Clear variables at function end. */
@@ -9027,7 +9038,7 @@ sh_legitimate_index_p (enum machine_mode mode, rtx op)
REG++
--REG */
-bool
+static bool
sh_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
{
if (MAYBE_BASE_REGISTER_RTX_P (x, strict))
@@ -11077,7 +11088,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.h b/gcc/config/sh/sh.h
index 837b03a64a8..9ad3fa74a0c 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -2320,20 +2320,6 @@ struct sh_args {
if (sh_legitimate_index_p ((MODE), (OP))) \
goto WIN; \
} while (0)
-
-#ifdef REG_OK_STRICT
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
- do { \
- if (sh_legitimate_address_p ((MODE), (X), true)) \
- goto LABEL; \
- } while (0)
-#else
-#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
- do { \
- if (sh_legitimate_address_p ((MODE), (X), false)) \
- goto LABEL; \
- } while (0)
-#endif
/* A C compound statement that attempts to replace X, which is an address
that needs reloading, with a valid memory address for an operand of
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 51bda0f46fe..95f280bd1ef 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -9110,16 +9110,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"
@@ -9565,7 +9555,7 @@ mov.l\\t1f,r0\\n\\
;; The c / m alternative is a fake to guide reload to load directly into
;; fpscr, since reload doesn't know how to use post-increment.
-;; GO_IF_LEGITIMATE_ADDRESS guards about bogus addresses before reload,
+;; TARGET_LEGITIMATE_ADDRESS_P guards about bogus addresses before reload,
;; SECONDARY_INPUT_RELOAD_CLASS does this during reload, and the insn's
;; predicate after reload.
;; The mac_gp type for r/!c might look a bit odd, but it actually schedules
diff --git a/gcc/config/sh/t-sh b/gcc/config/sh/t-sh
index e23be33580e..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
- $(CXX) -c $(ALL_CXXFLAGS) $(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/predicates.md b/gcc/config/spu/predicates.md
index ce91ba230bb..8c6798d8063 100644
--- a/gcc/config/spu/predicates.md
+++ b/gcc/config/spu/predicates.md
@@ -39,14 +39,14 @@
(ior (not (match_code "subreg"))
(match_test "valid_subreg (op)"))))
-(define_predicate "spu_mem_operand"
- (and (match_operand 0 "memory_operand")
- (match_test "reload_in_progress || reload_completed || aligned_mem_p (op)")))
-
(define_predicate "spu_mov_operand"
- (ior (match_operand 0 "spu_mem_operand")
+ (ior (match_operand 0 "memory_operand")
(match_operand 0 "spu_nonmem_operand")))
+(define_predicate "spu_dest_operand"
+ (ior (match_operand 0 "memory_operand")
+ (match_operand 0 "spu_reg_operand")))
+
(define_predicate "call_operand"
(and (match_code "mem")
(match_test "(!TARGET_LARGE_MEM && satisfies_constraint_S (op))
@@ -114,3 +114,9 @@
(and (match_operand 0 "immediate_operand")
(match_test "exp2_immediate_p (op, mode, 0, 127)"))))
+(define_predicate "shiftrt_operator"
+ (match_code "lshiftrt,ashiftrt"))
+
+(define_predicate "extend_operator"
+ (match_code "sign_extend,zero_extend"))
+
diff --git a/gcc/config/spu/spu-protos.h b/gcc/config/spu/spu-protos.h
index 33951d77ea9..2dbc6460750 100644
--- a/gcc/config/spu/spu-protos.h
+++ b/gcc/config/spu/spu-protos.h
@@ -62,11 +62,9 @@ extern void spu_setup_incoming_varargs (int *cum, enum machine_mode mode,
tree type, int *pretend_size,
int no_rtl);
extern void spu_conditional_register_usage (void);
-extern int aligned_mem_p (rtx mem);
extern int spu_expand_mov (rtx * ops, enum machine_mode mode);
-extern void spu_split_load (rtx * ops);
-extern void spu_split_store (rtx * ops);
-extern int spu_valid_move (rtx * ops);
+extern int spu_split_load (rtx * ops);
+extern int spu_split_store (rtx * ops);
extern int fsmbi_const_p (rtx x);
extern int cpat_const_p (rtx x, enum machine_mode mode);
extern rtx gen_cpat_const (rtx * ops);
@@ -87,6 +85,7 @@ extern void spu_initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt);
extern void spu_expand_sign_extend (rtx ops[]);
extern void spu_expand_vector_init (rtx target, rtx vals);
extern void spu_init_expanders (void);
+extern void spu_split_convert (rtx *);
/* spu-c.c */
extern tree spu_resolve_overloaded_builtin (tree fndecl, void *fnargs);
diff --git a/gcc/config/spu/spu.c b/gcc/config/spu/spu.c
index b8e08c83ea6..5ee18e53a7e 100644
--- a/gcc/config/spu/spu.c
+++ b/gcc/config/spu/spu.c
@@ -189,9 +189,9 @@ static tree spu_build_builtin_va_list (void);
static void spu_va_start (tree, rtx);
static tree spu_gimplify_va_arg_expr (tree valist, tree type,
gimple_seq * pre_p, gimple_seq * post_p);
-static int regno_aligned_for_load (int regno);
static int store_with_one_insn_p (rtx mem);
static int mem_is_padded_component_ref (rtx x);
+static int reg_aligned_for_addr (rtx x);
static bool spu_assemble_integer (rtx x, unsigned int size, int aligned_p);
static void spu_asm_globalize_label (FILE * file, const char *name);
static unsigned char spu_rtx_costs (rtx x, int code, int outer_code,
@@ -211,6 +211,7 @@ static tree spu_builtin_vec_perm (tree, tree *);
static int spu_sms_res_mii (struct ddg *g);
static void asm_file_start (void);
static unsigned int spu_section_type_flags (tree, const char *, int);
+static rtx spu_expand_load (rtx, rtx, rtx, int);
extern const char *reg_names[];
@@ -582,66 +583,85 @@ adjust_operand (rtx op, HOST_WIDE_INT * start)
void
spu_expand_extv (rtx ops[], int unsignedp)
{
+ rtx dst = ops[0], src = ops[1];
HOST_WIDE_INT width = INTVAL (ops[2]);
HOST_WIDE_INT start = INTVAL (ops[3]);
- HOST_WIDE_INT src_size, dst_size;
- enum machine_mode src_mode, dst_mode;
- rtx dst = ops[0], src = ops[1];
- rtx s;
+ HOST_WIDE_INT align_mask;
+ rtx s0, s1, mask, r0;
- dst = adjust_operand (ops[0], 0);
- dst_mode = GET_MODE (dst);
- dst_size = GET_MODE_BITSIZE (GET_MODE (dst));
-
- src = adjust_operand (src, &start);
- src_mode = GET_MODE (src);
- src_size = GET_MODE_BITSIZE (GET_MODE (src));
+ gcc_assert (REG_P (dst) && GET_MODE (dst) == TImode);
- if (start > 0)
+ if (MEM_P (src))
{
- s = gen_reg_rtx (src_mode);
- switch (src_mode)
+ /* First, determine if we need 1 TImode load or 2. We need only 1
+ if the bits being extracted do not cross the alignment boundary
+ as determined by the MEM and its address. */
+
+ align_mask = -MEM_ALIGN (src);
+ if ((start & align_mask) == ((start + width - 1) & align_mask))
{
- case SImode:
- emit_insn (gen_ashlsi3 (s, src, GEN_INT (start)));
- break;
- case DImode:
- emit_insn (gen_ashldi3 (s, src, GEN_INT (start)));
- break;
- case TImode:
- emit_insn (gen_ashlti3 (s, src, GEN_INT (start)));
- break;
- default:
- abort ();
+ /* Alignment is sufficient for 1 load. */
+ s0 = gen_reg_rtx (TImode);
+ r0 = spu_expand_load (s0, 0, src, start / 8);
+ start &= 7;
+ if (r0)
+ emit_insn (gen_rotqby_ti (s0, s0, r0));
}
- src = s;
+ else
+ {
+ /* Need 2 loads. */
+ s0 = gen_reg_rtx (TImode);
+ s1 = gen_reg_rtx (TImode);
+ r0 = spu_expand_load (s0, s1, src, start / 8);
+ start &= 7;
+
+ gcc_assert (start + width <= 128);
+ if (r0)
+ {
+ rtx r1 = gen_reg_rtx (SImode);
+ mask = gen_reg_rtx (TImode);
+ emit_move_insn (mask, GEN_INT (-1));
+ emit_insn (gen_rotqby_ti (s0, s0, r0));
+ emit_insn (gen_rotqby_ti (s1, s1, r0));
+ if (GET_CODE (r0) == CONST_INT)
+ r1 = GEN_INT (INTVAL (r0) & 15);
+ else
+ emit_insn (gen_andsi3 (r1, r0, GEN_INT (15)));
+ emit_insn (gen_shlqby_ti (mask, mask, r1));
+ emit_insn (gen_selb (s0, s1, s0, mask));
+ }
+ }
+
+ }
+ else if (GET_CODE (src) == SUBREG)
+ {
+ rtx r = SUBREG_REG (src);
+ gcc_assert (REG_P (r) && SCALAR_INT_MODE_P (GET_MODE (r)));
+ s0 = gen_reg_rtx (TImode);
+ if (GET_MODE_SIZE (GET_MODE (r)) < GET_MODE_SIZE (TImode))
+ emit_insn (gen_rtx_SET (VOIDmode, s0, gen_rtx_ZERO_EXTEND (TImode, r)));
+ else
+ emit_move_insn (s0, src);
+ }
+ else
+ {
+ gcc_assert (REG_P (src) && GET_MODE (src) == TImode);
+ s0 = gen_reg_rtx (TImode);
+ emit_move_insn (s0, src);
}
- if (width < src_size)
+ /* Now s0 is TImode and contains the bits to extract at start. */
+
+ if (start)
+ emit_insn (gen_rotlti3 (s0, s0, GEN_INT (start)));
+
+ if (128 - width)
{
- rtx pat;
- int icode;
- switch (src_mode)
- {
- case SImode:
- icode = unsignedp ? CODE_FOR_lshrsi3 : CODE_FOR_ashrsi3;
- break;
- case DImode:
- icode = unsignedp ? CODE_FOR_lshrdi3 : CODE_FOR_ashrdi3;
- break;
- case TImode:
- icode = unsignedp ? CODE_FOR_lshrti3 : CODE_FOR_ashrti3;
- break;
- default:
- abort ();
- }
- s = gen_reg_rtx (src_mode);
- pat = GEN_FCN (icode) (s, src, GEN_INT (src_size - width));
- emit_insn (pat);
- src = s;
+ tree c = build_int_cst (NULL_TREE, 128 - width);
+ s0 = expand_shift (RSHIFT_EXPR, TImode, s0, c, s0, unsignedp);
}
- convert_move (dst, src, unsignedp);
+ emit_move_insn (dst, s0);
}
void
@@ -734,38 +754,41 @@ spu_expand_insv (rtx ops[])
}
if (GET_CODE (ops[0]) == MEM)
{
- rtx aligned = gen_reg_rtx (SImode);
rtx low = gen_reg_rtx (SImode);
- rtx addr = gen_reg_rtx (SImode);
rtx rotl = gen_reg_rtx (SImode);
rtx mask0 = gen_reg_rtx (TImode);
+ rtx addr;
+ rtx addr0;
+ rtx addr1;
rtx mem;
- emit_move_insn (addr, XEXP (ops[0], 0));
- emit_insn (gen_andsi3 (aligned, addr, GEN_INT (-16)));
+ addr = force_reg (Pmode, XEXP (ops[0], 0));
+ addr0 = gen_rtx_AND (Pmode, addr, GEN_INT (-16));
emit_insn (gen_andsi3 (low, addr, GEN_INT (15)));
emit_insn (gen_negsi2 (rotl, low));
emit_insn (gen_rotqby_ti (shift_reg, shift_reg, rotl));
emit_insn (gen_rotqmby_ti (mask0, mask, rotl));
- mem = change_address (ops[0], TImode, aligned);
+ mem = change_address (ops[0], TImode, addr0);
set_mem_alias_set (mem, 0);
emit_move_insn (dst, mem);
emit_insn (gen_selb (dst, dst, shift_reg, mask0));
- emit_move_insn (mem, dst);
if (start + width > MEM_ALIGN (ops[0]))
{
rtx shl = gen_reg_rtx (SImode);
rtx mask1 = gen_reg_rtx (TImode);
rtx dst1 = gen_reg_rtx (TImode);
rtx mem1;
+ addr1 = plus_constant (addr, 16);
+ addr1 = gen_rtx_AND (Pmode, addr1, GEN_INT (-16));
emit_insn (gen_subsi3 (shl, GEN_INT (16), low));
emit_insn (gen_shlqby_ti (mask1, mask, shl));
- mem1 = adjust_address (mem, TImode, 16);
+ mem1 = change_address (ops[0], TImode, addr1);
set_mem_alias_set (mem1, 0);
emit_move_insn (dst1, mem1);
emit_insn (gen_selb (dst1, dst1, shift_reg, mask1));
emit_move_insn (mem1, dst1);
}
+ emit_move_insn (mem, dst);
}
else
emit_insn (gen_selb (dst, copy_rtx (dst), shift_reg, mask));
@@ -2998,7 +3021,7 @@ spu_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
insn = ready[i];
if (INSN_CODE (insn) == -1
|| INSN_CODE (insn) == CODE_FOR_blockage
- || INSN_CODE (insn) == CODE_FOR__spu_convert)
+ || (INSN_P (insn) && get_attr_length (insn) == 0))
{
ready[i] = ready[nready - 1];
ready[nready - 1] = insn;
@@ -3129,8 +3152,8 @@ spu_sched_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
|| INSN_CODE (dep_insn) == CODE_FOR_blockage)
return 0;
- if (INSN_CODE (insn) == CODE_FOR__spu_convert
- || INSN_CODE (dep_insn) == CODE_FOR__spu_convert)
+ if ((INSN_P (insn) && get_attr_length (insn) == 0)
+ || (INSN_P (dep_insn) && get_attr_length (dep_insn) == 0))
return 0;
/* Make sure hbrps are spread out. */
@@ -3611,44 +3634,36 @@ spu_legitimate_constant_p (rtx x)
/* Valid address are:
- symbol_ref, label_ref, const
- reg
- - reg + const, where either reg or const is 16 byte aligned
+ - reg + const_int, where const_int is 16 byte aligned
- reg + reg, alignment doesn't matter
The alignment matters in the reg+const case because lqd and stqd
- ignore the 4 least significant bits of the const. (TODO: It might be
- preferable to allow any alignment and fix it up when splitting.) */
-bool
-spu_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
+ ignore the 4 least significant bits of the const. We only care about
+ 16 byte modes because the expand phase will change all smaller MEM
+ references to TImode. */
+static bool
+spu_legitimate_address_p (enum machine_mode mode,
rtx x, bool reg_ok_strict)
{
- if (mode == TImode && GET_CODE (x) == AND
+ int aligned = GET_MODE_SIZE (mode) >= 16;
+ if (aligned
+ && GET_CODE (x) == AND
&& GET_CODE (XEXP (x, 1)) == CONST_INT
- && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT) -16)
+ && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT) - 16)
x = XEXP (x, 0);
switch (GET_CODE (x))
{
- case SYMBOL_REF:
case LABEL_REF:
- return !TARGET_LARGE_MEM;
-
+ case SYMBOL_REF:
case CONST:
- if (!TARGET_LARGE_MEM && GET_CODE (XEXP (x, 0)) == PLUS)
- {
- rtx sym = XEXP (XEXP (x, 0), 0);
- rtx cst = XEXP (XEXP (x, 0), 1);
-
- /* Accept any symbol_ref + constant, assuming it does not
- wrap around the local store addressability limit. */
- if (GET_CODE (sym) == SYMBOL_REF && GET_CODE (cst) == CONST_INT)
- return 1;
- }
- return 0;
+ return !TARGET_LARGE_MEM;
case CONST_INT:
return INTVAL (x) >= 0 && INTVAL (x) <= 0x3ffff;
case SUBREG:
x = XEXP (x, 0);
- gcc_assert (GET_CODE (x) == REG);
+ if (REG_P (x))
+ return 0;
case REG:
return INT_REG_OK_FOR_BASE_P (x, reg_ok_strict);
@@ -3662,29 +3677,25 @@ spu_legitimate_address_p (enum machine_mode mode ATTRIBUTE_UNUSED,
op0 = XEXP (op0, 0);
if (GET_CODE (op1) == SUBREG)
op1 = XEXP (op1, 0);
- /* We can't just accept any aligned register because CSE can
- change it to a register that is not marked aligned and then
- recog will fail. So we only accept frame registers because
- they will only be changed to other frame registers. */
if (GET_CODE (op0) == REG
&& INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
&& GET_CODE (op1) == CONST_INT
&& INTVAL (op1) >= -0x2000
&& INTVAL (op1) <= 0x1fff
- && (regno_aligned_for_load (REGNO (op0)) || (INTVAL (op1) & 15) == 0))
- return 1;
+ && (!aligned || (INTVAL (op1) & 15) == 0))
+ return TRUE;
if (GET_CODE (op0) == REG
&& INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
&& GET_CODE (op1) == REG
&& INT_REG_OK_FOR_INDEX_P (op1, reg_ok_strict))
- return 1;
+ return TRUE;
}
break;
default:
break;
}
- return 0;
+ return FALSE;
}
/* When the address is reg + const_int, force the const_int into a
@@ -4137,60 +4148,14 @@ spu_conditional_register_usage (void)
}
}
-/* This is called to decide when we can simplify a load instruction. We
- must only return true for registers which we know will always be
- aligned. Taking into account that CSE might replace this reg with
- another one that has not been marked aligned.
- So this is really only true for frame, stack and virtual registers,
- which we know are always aligned and should not be adversely effected
- by CSE. */
+/* This is called any time we inspect the alignment of a register for
+ addresses. */
static int
-regno_aligned_for_load (int regno)
+reg_aligned_for_addr (rtx x)
{
- return regno == FRAME_POINTER_REGNUM
- || (frame_pointer_needed && regno == HARD_FRAME_POINTER_REGNUM)
- || regno == ARG_POINTER_REGNUM
- || regno == STACK_POINTER_REGNUM
- || (regno >= FIRST_VIRTUAL_REGISTER
- && regno <= LAST_VIRTUAL_REGISTER);
-}
-
-/* Return TRUE when mem is known to be 16-byte aligned. */
-int
-aligned_mem_p (rtx mem)
-{
- if (MEM_ALIGN (mem) >= 128)
- return 1;
- if (GET_MODE_SIZE (GET_MODE (mem)) >= 16)
- return 1;
- if (GET_CODE (XEXP (mem, 0)) == PLUS)
- {
- rtx p0 = XEXP (XEXP (mem, 0), 0);
- rtx p1 = XEXP (XEXP (mem, 0), 1);
- if (regno_aligned_for_load (REGNO (p0)))
- {
- if (GET_CODE (p1) == REG && regno_aligned_for_load (REGNO (p1)))
- return 1;
- if (GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15) == 0)
- return 1;
- }
- }
- else if (GET_CODE (XEXP (mem, 0)) == REG)
- {
- if (regno_aligned_for_load (REGNO (XEXP (mem, 0))))
- return 1;
- }
- else if (ALIGNED_SYMBOL_REF_P (XEXP (mem, 0)))
- return 1;
- else if (GET_CODE (XEXP (mem, 0)) == CONST)
- {
- rtx p0 = XEXP (XEXP (XEXP (mem, 0), 0), 0);
- rtx p1 = XEXP (XEXP (XEXP (mem, 0), 0), 1);
- if (GET_CODE (p0) == SYMBOL_REF
- && GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15) == 0)
- return 1;
- }
- return 0;
+ int regno =
+ REGNO (x) < FIRST_PSEUDO_REGISTER ? ORIGINAL_REGNO (x) : REGNO (x);
+ return REGNO_POINTER_ALIGN (regno) >= 128;
}
/* Encode symbol attributes (local vs. global, tls model) of a SYMBOL_REF
@@ -4219,9 +4184,12 @@ spu_encode_section_info (tree decl, rtx rtl, int first)
static int
store_with_one_insn_p (rtx mem)
{
+ enum machine_mode mode = GET_MODE (mem);
rtx addr = XEXP (mem, 0);
- if (GET_MODE (mem) == BLKmode)
+ if (mode == BLKmode)
return 0;
+ if (GET_MODE_SIZE (mode) >= 16)
+ return 1;
/* Only static objects. */
if (GET_CODE (addr) == SYMBOL_REF)
{
@@ -4245,6 +4213,22 @@ store_with_one_insn_p (rtx mem)
return 0;
}
+/* Return 1 when the address is not valid for a simple load and store as
+ required by the '_mov*' patterns. We could make this less strict
+ for loads, but we prefer mem's to look the same so they are more
+ likely to be merged. */
+static int
+address_needs_split (rtx mem)
+{
+ if (GET_MODE_SIZE (GET_MODE (mem)) < 16
+ && (GET_MODE_SIZE (GET_MODE (mem)) < 4
+ || !(store_with_one_insn_p (mem)
+ || mem_is_padded_component_ref (mem))))
+ return 1;
+
+ return 0;
+}
+
int
spu_expand_mov (rtx * ops, enum machine_mode mode)
{
@@ -4289,54 +4273,63 @@ spu_expand_mov (rtx * ops, enum machine_mode mode)
return spu_split_immediate (ops);
return 0;
}
- else
+
+ /* Catch the SImode immediates greater than 0x7fffffff, and sign
+ extend them. */
+ if (GET_CODE (ops[1]) == CONST_INT)
{
- if (GET_CODE (ops[0]) == MEM)
- {
- if (!spu_valid_move (ops))
- {
- emit_insn (gen_store (ops[0], ops[1], gen_reg_rtx (TImode),
- gen_reg_rtx (TImode)));
- return 1;
- }
- }
- else if (GET_CODE (ops[1]) == MEM)
+ HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (ops[1]), mode);
+ if (val != INTVAL (ops[1]))
{
- if (!spu_valid_move (ops))
- {
- emit_insn (gen_load
- (ops[0], ops[1], gen_reg_rtx (TImode),
- gen_reg_rtx (SImode)));
- return 1;
- }
- }
- /* Catch the SImode immediates greater than 0x7fffffff, and sign
- extend them. */
- if (GET_CODE (ops[1]) == CONST_INT)
- {
- HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (ops[1]), mode);
- if (val != INTVAL (ops[1]))
- {
- emit_move_insn (ops[0], GEN_INT (val));
- return 1;
- }
+ emit_move_insn (ops[0], GEN_INT (val));
+ return 1;
}
}
+ if (MEM_P (ops[0]))
+ return spu_split_store (ops);
+ if (MEM_P (ops[1]))
+ return spu_split_load (ops);
+
return 0;
}
-void
-spu_split_load (rtx * ops)
+static void
+spu_convert_move (rtx dst, rtx src)
{
- enum machine_mode mode = GET_MODE (ops[0]);
- rtx addr, load, rot, mem, p0, p1;
- int rot_amt;
+ enum machine_mode mode = GET_MODE (dst);
+ enum machine_mode int_mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
+ rtx reg;
+ gcc_assert (GET_MODE (src) == TImode);
+ reg = int_mode != mode ? gen_reg_rtx (int_mode) : dst;
+ emit_insn (gen_rtx_SET (VOIDmode, reg,
+ gen_rtx_TRUNCATE (int_mode,
+ gen_rtx_LSHIFTRT (TImode, src,
+ GEN_INT (int_mode == DImode ? 64 : 96)))));
+ if (int_mode != mode)
+ {
+ reg = simplify_gen_subreg (mode, reg, int_mode, 0);
+ emit_move_insn (dst, reg);
+ }
+}
- addr = XEXP (ops[1], 0);
+/* Load TImode values into DST0 and DST1 (when it is non-NULL) using
+ the address from SRC and SRC+16. Return a REG or CONST_INT that
+ specifies how many bytes to rotate the loaded registers, plus any
+ extra from EXTRA_ROTQBY. The address and rotate amounts are
+ normalized to improve merging of loads and rotate computations. */
+static rtx
+spu_expand_load (rtx dst0, rtx dst1, rtx src, int extra_rotby)
+{
+ rtx addr = XEXP (src, 0);
+ rtx p0, p1, rot, addr0, addr1;
+ int rot_amt;
rot = 0;
rot_amt = 0;
- if (GET_CODE (addr) == PLUS)
+
+ if (MEM_ALIGN (src) >= 128)
+ /* Address is already aligned; simply perform a TImode load. */ ;
+ else if (GET_CODE (addr) == PLUS)
{
/* 8 cases:
aligned reg + aligned reg => lqx
@@ -4350,12 +4343,34 @@ spu_split_load (rtx * ops)
*/
p0 = XEXP (addr, 0);
p1 = XEXP (addr, 1);
- if (REG_P (p0) && !regno_aligned_for_load (REGNO (p0)))
+ if (!reg_aligned_for_addr (p0))
{
- if (REG_P (p1) && !regno_aligned_for_load (REGNO (p1)))
+ if (REG_P (p1) && !reg_aligned_for_addr (p1))
{
- emit_insn (gen_addsi3 (ops[3], p0, p1));
- rot = ops[3];
+ rot = gen_reg_rtx (SImode);
+ emit_insn (gen_addsi3 (rot, p0, p1));
+ }
+ else if (GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15))
+ {
+ if (INTVAL (p1) > 0
+ && REG_POINTER (p0)
+ && INTVAL (p1) * BITS_PER_UNIT
+ < REGNO_POINTER_ALIGN (REGNO (p0)))
+ {
+ rot = gen_reg_rtx (SImode);
+ emit_insn (gen_addsi3 (rot, p0, p1));
+ addr = p0;
+ }
+ else
+ {
+ rtx x = gen_reg_rtx (SImode);
+ emit_move_insn (x, p1);
+ if (!spu_arith_operand (p1, SImode))
+ p1 = x;
+ rot = gen_reg_rtx (SImode);
+ emit_insn (gen_addsi3 (rot, p0, p1));
+ addr = gen_rtx_PLUS (Pmode, p0, x);
+ }
}
else
rot = p0;
@@ -4365,16 +4380,21 @@ spu_split_load (rtx * ops)
if (GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15))
{
rot_amt = INTVAL (p1) & 15;
- p1 = GEN_INT (INTVAL (p1) & -16);
- addr = gen_rtx_PLUS (SImode, p0, p1);
+ if (INTVAL (p1) & -16)
+ {
+ p1 = GEN_INT (INTVAL (p1) & -16);
+ addr = gen_rtx_PLUS (SImode, p0, p1);
+ }
+ else
+ addr = p0;
}
- else if (REG_P (p1) && !regno_aligned_for_load (REGNO (p1)))
+ else if (REG_P (p1) && !reg_aligned_for_addr (p1))
rot = p1;
}
}
- else if (GET_CODE (addr) == REG)
+ else if (REG_P (addr))
{
- if (!regno_aligned_for_load (REGNO (addr)))
+ if (!reg_aligned_for_addr (addr))
rot = addr;
}
else if (GET_CODE (addr) == CONST)
@@ -4393,7 +4413,10 @@ spu_split_load (rtx * ops)
addr = XEXP (XEXP (addr, 0), 0);
}
else
- rot = addr;
+ {
+ rot = gen_reg_rtx (Pmode);
+ emit_move_insn (rot, addr);
+ }
}
else if (GET_CODE (addr) == CONST_INT)
{
@@ -4401,49 +4424,96 @@ spu_split_load (rtx * ops)
addr = GEN_INT (rot_amt & -16);
}
else if (!ALIGNED_SYMBOL_REF_P (addr))
- rot = addr;
+ {
+ rot = gen_reg_rtx (Pmode);
+ emit_move_insn (rot, addr);
+ }
- if (GET_MODE_SIZE (mode) < 4)
- rot_amt += GET_MODE_SIZE (mode) - 4;
+ rot_amt += extra_rotby;
rot_amt &= 15;
if (rot && rot_amt)
{
- emit_insn (gen_addsi3 (ops[3], rot, GEN_INT (rot_amt)));
- rot = ops[3];
+ rtx x = gen_reg_rtx (SImode);
+ emit_insn (gen_addsi3 (x, rot, GEN_INT (rot_amt)));
+ rot = x;
rot_amt = 0;
}
+ if (!rot && rot_amt)
+ rot = GEN_INT (rot_amt);
+
+ addr0 = copy_rtx (addr);
+ addr0 = gen_rtx_AND (SImode, copy_rtx (addr), GEN_INT (-16));
+ emit_insn (gen__movti (dst0, change_address (src, TImode, addr0)));
+
+ if (dst1)
+ {
+ addr1 = plus_constant (copy_rtx (addr), 16);
+ addr1 = gen_rtx_AND (SImode, addr1, GEN_INT (-16));
+ emit_insn (gen__movti (dst1, change_address (src, TImode, addr1)));
+ }
- load = ops[2];
+ return rot;
+}
+
+int
+spu_split_load (rtx * ops)
+{
+ enum machine_mode mode = GET_MODE (ops[0]);
+ rtx addr, load, rot;
+ int rot_amt;
- addr = gen_rtx_AND (SImode, copy_rtx (addr), GEN_INT (-16));
- mem = change_address (ops[1], TImode, addr);
+ if (GET_MODE_SIZE (mode) >= 16)
+ return 0;
- emit_insn (gen_movti (load, mem));
+ addr = XEXP (ops[1], 0);
+ gcc_assert (GET_CODE (addr) != AND);
+
+ if (!address_needs_split (ops[1]))
+ {
+ ops[1] = change_address (ops[1], TImode, addr);
+ load = gen_reg_rtx (TImode);
+ emit_insn (gen__movti (load, ops[1]));
+ spu_convert_move (ops[0], load);
+ return 1;
+ }
+
+ rot_amt = GET_MODE_SIZE (mode) < 4 ? GET_MODE_SIZE (mode) - 4 : 0;
+
+ load = gen_reg_rtx (TImode);
+ rot = spu_expand_load (load, 0, ops[1], rot_amt);
if (rot)
emit_insn (gen_rotqby_ti (load, load, rot));
- else if (rot_amt)
- emit_insn (gen_rotlti3 (load, load, GEN_INT (rot_amt * 8)));
- if (reload_completed)
- emit_move_insn (ops[0], gen_rtx_REG (GET_MODE (ops[0]), REGNO (load)));
- else
- emit_insn (gen_spu_convert (ops[0], load));
+ spu_convert_move (ops[0], load);
+ return 1;
}
-void
+int
spu_split_store (rtx * ops)
{
enum machine_mode mode = GET_MODE (ops[0]);
- rtx pat = ops[2];
- rtx reg = ops[3];
+ rtx reg;
rtx addr, p0, p1, p1_lo, smem;
int aform;
int scalar;
+ if (GET_MODE_SIZE (mode) >= 16)
+ return 0;
+
addr = XEXP (ops[0], 0);
+ gcc_assert (GET_CODE (addr) != AND);
+
+ if (!address_needs_split (ops[0]))
+ {
+ reg = gen_reg_rtx (TImode);
+ emit_insn (gen_spu_convert (reg, ops[1]));
+ ops[0] = change_address (ops[0], TImode, addr);
+ emit_move_insn (ops[0], reg);
+ return 1;
+ }
if (GET_CODE (addr) == PLUS)
{
@@ -4455,19 +4525,31 @@ spu_split_store (rtx * ops)
unaligned reg + aligned reg => lqx, c?x, shuf, stqx
unaligned reg + unaligned reg => lqx, c?x, shuf, stqx
unaligned reg + aligned const => lqd, c?d, shuf, stqx
- unaligned reg + unaligned const -> not allowed by legitimate address
+ unaligned reg + unaligned const -> lqx, c?d, shuf, stqx
*/
aform = 0;
p0 = XEXP (addr, 0);
p1 = p1_lo = XEXP (addr, 1);
- if (GET_CODE (p0) == REG && GET_CODE (p1) == CONST_INT)
+ if (REG_P (p0) && GET_CODE (p1) == CONST_INT)
{
p1_lo = GEN_INT (INTVAL (p1) & 15);
- p1 = GEN_INT (INTVAL (p1) & -16);
- addr = gen_rtx_PLUS (SImode, p0, p1);
+ if (reg_aligned_for_addr (p0))
+ {
+ p1 = GEN_INT (INTVAL (p1) & -16);
+ if (p1 == const0_rtx)
+ addr = p0;
+ else
+ addr = gen_rtx_PLUS (SImode, p0, p1);
+ }
+ else
+ {
+ rtx x = gen_reg_rtx (SImode);
+ emit_move_insn (x, p1);
+ addr = gen_rtx_PLUS (SImode, p0, x);
+ }
}
}
- else if (GET_CODE (addr) == REG)
+ else if (REG_P (addr))
{
aform = 0;
p0 = addr;
@@ -4481,31 +4563,34 @@ spu_split_store (rtx * ops)
p1_lo = addr;
if (ALIGNED_SYMBOL_REF_P (addr))
p1_lo = const0_rtx;
- else if (GET_CODE (addr) == CONST)
+ else if (GET_CODE (addr) == CONST
+ && GET_CODE (XEXP (addr, 0)) == PLUS
+ && ALIGNED_SYMBOL_REF_P (XEXP (XEXP (addr, 0), 0))
+ && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
{
- if (GET_CODE (XEXP (addr, 0)) == PLUS
- && ALIGNED_SYMBOL_REF_P (XEXP (XEXP (addr, 0), 0))
- && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
- {
- HOST_WIDE_INT v = INTVAL (XEXP (XEXP (addr, 0), 1));
- if ((v & -16) != 0)
- addr = gen_rtx_CONST (Pmode,
- gen_rtx_PLUS (Pmode,
- XEXP (XEXP (addr, 0), 0),
- GEN_INT (v & -16)));
- else
- addr = XEXP (XEXP (addr, 0), 0);
- p1_lo = GEN_INT (v & 15);
- }
+ HOST_WIDE_INT v = INTVAL (XEXP (XEXP (addr, 0), 1));
+ if ((v & -16) != 0)
+ addr = gen_rtx_CONST (Pmode,
+ gen_rtx_PLUS (Pmode,
+ XEXP (XEXP (addr, 0), 0),
+ GEN_INT (v & -16)));
+ else
+ addr = XEXP (XEXP (addr, 0), 0);
+ p1_lo = GEN_INT (v & 15);
}
else if (GET_CODE (addr) == CONST_INT)
{
p1_lo = GEN_INT (INTVAL (addr) & 15);
addr = GEN_INT (INTVAL (addr) & -16);
}
+ else
+ {
+ p1_lo = gen_reg_rtx (SImode);
+ emit_move_insn (p1_lo, addr);
+ }
}
- addr = gen_rtx_AND (SImode, copy_rtx (addr), GEN_INT (-16));
+ reg = gen_reg_rtx (TImode);
scalar = store_with_one_insn_p (ops[0]);
if (!scalar)
@@ -4515,11 +4600,12 @@ spu_split_store (rtx * ops)
possible, and copying the flags will prevent that in certain
cases, e.g. consider the volatile flag. */
+ rtx pat = gen_reg_rtx (TImode);
rtx lmem = change_address (ops[0], TImode, copy_rtx (addr));
set_mem_alias_set (lmem, 0);
emit_insn (gen_movti (reg, lmem));
- if (!p0 || regno_aligned_for_load (REGNO (p0)))
+ if (!p0 || reg_aligned_for_addr (p0))
p0 = stack_pointer_rtx;
if (!p1_lo)
p1_lo = const0_rtx;
@@ -4527,17 +4613,6 @@ spu_split_store (rtx * ops)
emit_insn (gen_cpat (pat, p0, p1_lo, GEN_INT (GET_MODE_SIZE (mode))));
emit_insn (gen_shufb (reg, ops[1], reg, pat));
}
- else if (reload_completed)
- {
- if (GET_CODE (ops[1]) == REG)
- emit_move_insn (reg, gen_rtx_REG (GET_MODE (reg), REGNO (ops[1])));
- else if (GET_CODE (ops[1]) == SUBREG)
- emit_move_insn (reg,
- gen_rtx_REG (GET_MODE (reg),
- REGNO (SUBREG_REG (ops[1]))));
- else
- abort ();
- }
else
{
if (GET_CODE (ops[1]) == REG)
@@ -4549,15 +4624,16 @@ spu_split_store (rtx * ops)
}
if (GET_MODE_SIZE (mode) < 4 && scalar)
- emit_insn (gen_shlqby_ti
- (reg, reg, GEN_INT (4 - GET_MODE_SIZE (mode))));
+ emit_insn (gen_ashlti3
+ (reg, reg, GEN_INT (32 - GET_MODE_BITSIZE (mode))));
- smem = change_address (ops[0], TImode, addr);
+ smem = change_address (ops[0], TImode, copy_rtx (addr));
/* We can't use the previous alias set because the memory has changed
size and can potentially overlap objects of other types. */
set_mem_alias_set (smem, 0);
emit_insn (gen_movti (smem, reg));
+ return 1;
}
/* Return TRUE if X is MEM which is a struct member reference
@@ -4656,37 +4732,6 @@ fix_range (const char *const_str)
}
}
-int
-spu_valid_move (rtx * ops)
-{
- enum machine_mode mode = GET_MODE (ops[0]);
- if (!register_operand (ops[0], mode) && !register_operand (ops[1], mode))
- return 0;
-
- /* init_expr_once tries to recog against load and store insns to set
- the direct_load[] and direct_store[] arrays. We always want to
- consider those loads and stores valid. init_expr_once is called in
- the context of a dummy function which does not have a decl. */
- if (cfun->decl == 0)
- return 1;
-
- /* Don't allows loads/stores which would require more than 1 insn.
- During and after reload we assume loads and stores only take 1
- insn. */
- if (GET_MODE_SIZE (mode) < 16 && !reload_in_progress && !reload_completed)
- {
- if (GET_CODE (ops[0]) == MEM
- && (GET_MODE_SIZE (mode) < 4
- || !(store_with_one_insn_p (ops[0])
- || mem_is_padded_component_ref (ops[0]))))
- return 0;
- if (GET_CODE (ops[1]) == MEM
- && (GET_MODE_SIZE (mode) < 4 || !aligned_mem_p (ops[1])))
- return 0;
- }
- return 1;
-}
-
/* Return TRUE if x is a CONST_INT, CONST_DOUBLE or CONST_VECTOR that
can be generated using the fsmbi instruction. */
int
@@ -6400,12 +6445,25 @@ spu_sms_res_mii (struct ddg *g)
void
spu_init_expanders (void)
-{
- /* HARD_FRAME_REGISTER is only 128 bit aligned when
- * frame_pointer_needed is true. We don't know that until we're
- * expanding the prologue. */
+{
if (cfun)
- REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 8;
+ {
+ rtx r0, r1;
+ /* HARD_FRAME_REGISTER is only 128 bit aligned when
+ frame_pointer_needed is true. We don't know that until we're
+ expanding the prologue. */
+ REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 8;
+
+ /* A number of passes use LAST_VIRTUAL_REGISTER+1 and
+ LAST_VIRTUAL_REGISTER+2 to test the back-end. We want them
+ to be treated as aligned, so generate them here. */
+ r0 = gen_reg_rtx (SImode);
+ r1 = gen_reg_rtx (SImode);
+ mark_reg_pointer (r0, 128);
+ mark_reg_pointer (r1, 128);
+ gcc_assert (REGNO (r0) == LAST_VIRTUAL_REGISTER + 1
+ && REGNO (r1) == LAST_VIRTUAL_REGISTER + 2);
+ }
}
static enum machine_mode
@@ -6480,4 +6538,20 @@ spu_gen_exp2 (enum machine_mode mode, rtx scale)
}
}
+/* After reload, just change the convert into a move instruction
+ or a dead instruction. */
+void
+spu_split_convert (rtx ops[])
+{
+ if (REGNO (ops[0]) == REGNO (ops[1]))
+ emit_note (NOTE_INSN_DELETED);
+ else
+ {
+ /* Use TImode always as this might help hard reg copyprop. */
+ rtx op0 = gen_rtx_REG (TImode, REGNO (ops[0]));
+ rtx op1 = gen_rtx_REG (TImode, REGNO (ops[1]));
+ emit_insn (gen_move_insn (op0, op1));
+ }
+}
+
#include "gt-spu.h"
diff --git a/gcc/config/spu/spu.md b/gcc/config/spu/spu.md
index db42db16111..181d0db991c 100644
--- a/gcc/config/spu/spu.md
+++ b/gcc/config/spu/spu.md
@@ -178,6 +178,8 @@
SF V4SF
DF V2DF])
+(define_mode_iterator QHSI [QI HI SI])
+(define_mode_iterator QHSDI [QI HI SI DI])
(define_mode_iterator DTI [DI TI])
(define_mode_iterator VINT [QI V16QI
@@ -316,9 +318,10 @@
;; move internal
(define_insn "_mov<mode>"
- [(set (match_operand:MOV 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
+ [(set (match_operand:MOV 0 "spu_dest_operand" "=r,r,r,r,r,m")
(match_operand:MOV 1 "spu_mov_operand" "r,A,f,j,m,r"))]
- "spu_valid_move (operands)"
+ "register_operand(operands[0], <MODE>mode)
+ || register_operand(operands[1], <MODE>mode)"
"@
ori\t%0,%1,0
il%s1\t%0,%S1
@@ -336,9 +339,10 @@
"iohl\t%0,%2@l")
(define_insn "_movdi"
- [(set (match_operand:DI 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
+ [(set (match_operand:DI 0 "spu_dest_operand" "=r,r,r,r,r,m")
(match_operand:DI 1 "spu_mov_operand" "r,a,f,k,m,r"))]
- "spu_valid_move (operands)"
+ "register_operand(operands[0], DImode)
+ || register_operand(operands[1], DImode)"
"@
ori\t%0,%1,0
il%d1\t%0,%D1
@@ -349,9 +353,10 @@
[(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
(define_insn "_movti"
- [(set (match_operand:TI 0 "spu_nonimm_operand" "=r,r,r,r,r,m")
+ [(set (match_operand:TI 0 "spu_dest_operand" "=r,r,r,r,r,m")
(match_operand:TI 1 "spu_mov_operand" "r,U,f,l,m,r"))]
- "spu_valid_move (operands)"
+ "register_operand(operands[0], TImode)
+ || register_operand(operands[1], TImode)"
"@
ori\t%0,%1,0
il%t1\t%0,%T1
@@ -361,30 +366,29 @@
stq%p0\t%1,%0"
[(set_attr "type" "fx2,fx2,shuf,shuf,load,store")])
-(define_insn_and_split "load"
- [(set (match_operand 0 "spu_reg_operand" "=r")
- (match_operand 1 "memory_operand" "m"))
- (clobber (match_operand:TI 2 "spu_reg_operand" "=&r"))
- (clobber (match_operand:SI 3 "spu_reg_operand" "=&r"))]
- "GET_MODE(operands[0]) == GET_MODE(operands[1])"
- "#"
- ""
+(define_split
+ [(set (match_operand 0 "spu_reg_operand")
+ (match_operand 1 "memory_operand"))]
+ "GET_MODE_SIZE (GET_MODE (operands[0])) < 16
+ && GET_MODE(operands[0]) == GET_MODE(operands[1])
+ && !reload_in_progress && !reload_completed"
[(set (match_dup 0)
(match_dup 1))]
- { spu_split_load(operands); DONE; })
+ { if (spu_split_load(operands))
+ DONE;
+ })
-(define_insn_and_split "store"
- [(set (match_operand 0 "memory_operand" "=m")
- (match_operand 1 "spu_reg_operand" "r"))
- (clobber (match_operand:TI 2 "spu_reg_operand" "=&r"))
- (clobber (match_operand:TI 3 "spu_reg_operand" "=&r"))]
- "GET_MODE(operands[0]) == GET_MODE(operands[1])"
- "#"
- ""
+(define_split
+ [(set (match_operand 0 "memory_operand")
+ (match_operand 1 "spu_reg_operand"))]
+ "GET_MODE_SIZE (GET_MODE (operands[0])) < 16
+ && GET_MODE(operands[0]) == GET_MODE(operands[1])
+ && !reload_in_progress && !reload_completed"
[(set (match_dup 0)
(match_dup 1))]
- { spu_split_store(operands); DONE; })
-
+ { if (spu_split_store(operands))
+ DONE;
+ })
;; Operand 3 is the number of bytes. 1:b 2:h 4:w 8:d
(define_expand "cpat"
@@ -462,33 +466,20 @@
""
"xswd\t%0,%1");
-(define_expand "extendqiti2"
- [(set (match_operand:TI 0 "register_operand" "")
- (sign_extend:TI (match_operand:QI 1 "register_operand" "")))]
- ""
- "spu_expand_sign_extend(operands);
- DONE;")
-
-(define_expand "extendhiti2"
+;; By splitting this late we don't allow much opportunity for sharing of
+;; constants. That's ok because this should really be optimized away.
+(define_insn_and_split "extend<mode>ti2"
[(set (match_operand:TI 0 "register_operand" "")
- (sign_extend:TI (match_operand:HI 1 "register_operand" "")))]
+ (sign_extend:TI (match_operand:QHSDI 1 "register_operand" "")))]
""
- "spu_expand_sign_extend(operands);
- DONE;")
-
-(define_expand "extendsiti2"
- [(set (match_operand:TI 0 "register_operand" "")
- (sign_extend:TI (match_operand:SI 1 "register_operand" "")))]
- ""
- "spu_expand_sign_extend(operands);
- DONE;")
-
-(define_expand "extendditi2"
- [(set (match_operand:TI 0 "register_operand" "")
- (sign_extend:TI (match_operand:DI 1 "register_operand" "")))]
+ "#"
""
- "spu_expand_sign_extend(operands);
- DONE;")
+ [(set (match_dup:TI 0)
+ (sign_extend:TI (match_dup:QHSDI 1)))]
+ {
+ spu_expand_sign_extend(operands);
+ DONE;
+ })
;; zero_extend
@@ -525,6 +516,22 @@
"rotqmbyi\t%0,%1,-4"
[(set_attr "type" "shuf")])
+(define_insn "zero_extendqiti2"
+ [(set (match_operand:TI 0 "spu_reg_operand" "=r")
+ (zero_extend:TI (match_operand:QI 1 "spu_reg_operand" "r")))]
+ ""
+ "andi\t%0,%1,0x00ff\;rotqmbyi\t%0,%0,-12"
+ [(set_attr "type" "multi0")
+ (set_attr "length" "8")])
+
+(define_insn "zero_extendhiti2"
+ [(set (match_operand:TI 0 "spu_reg_operand" "=r")
+ (zero_extend:TI (match_operand:HI 1 "spu_reg_operand" "r")))]
+ ""
+ "shli\t%0,%1,16\;rotqmbyi\t%0,%0,-14"
+ [(set_attr "type" "multi1")
+ (set_attr "length" "8")])
+
(define_insn "zero_extendsiti2"
[(set (match_operand:TI 0 "spu_reg_operand" "=r")
(zero_extend:TI (match_operand:SI 1 "spu_reg_operand" "r")))]
@@ -2348,6 +2355,13 @@
""
[(set_attr "type" "*,fx3")])
+(define_insn "<v>lshr<mode>3_imm"
+ [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
+ (lshiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")
+ (match_operand:VHSI 2 "immediate_operand" "W")))]
+ ""
+ "rot<bh>mi\t%0,%1,-%<umask>2"
+ [(set_attr "type" "fx3")])
(define_insn "rotm_<mode>"
[(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
@@ -2359,89 +2373,59 @@
rot<bh>mi\t%0,%1,-%<nmask>2"
[(set_attr "type" "fx3")])
-(define_expand "lshr<mode>3"
- [(parallel [(set (match_operand:DTI 0 "spu_reg_operand" "")
- (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "")
- (match_operand:SI 2 "spu_nonmem_operand" "")))
- (clobber (match_dup:DTI 3))
- (clobber (match_dup:SI 4))
- (clobber (match_dup:SI 5))])]
- ""
- "if (GET_CODE (operands[2]) == CONST_INT)
- {
- emit_insn (gen_lshr<mode>3_imm(operands[0], operands[1], operands[2]));
- DONE;
- }
- operands[3] = gen_reg_rtx (<MODE>mode);
- operands[4] = gen_reg_rtx (SImode);
- operands[5] = gen_reg_rtx (SImode);")
-
-(define_insn_and_split "lshr<mode>3_imm"
- [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
- (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
- (match_operand:SI 2 "immediate_operand" "O,P")))]
+(define_insn_and_split "lshr<mode>3"
+ [(set (match_operand:DTI 0 "spu_reg_operand" "=r,r,r")
+ (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r,r")
+ (match_operand:SI 2 "spu_nonmem_operand" "r,O,P")))]
""
"@
+ #
rotqmbyi\t%0,%1,-%h2
rotqmbii\t%0,%1,-%e2"
- "!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2])"
- [(set (match_dup:DTI 0)
+ "REG_P (operands[2]) || (!satisfies_constraint_O (operands[2]) && !satisfies_constraint_P (operands[2]))"
+ [(set (match_dup:DTI 3)
(lshiftrt:DTI (match_dup:DTI 1)
(match_dup:SI 4)))
(set (match_dup:DTI 0)
- (lshiftrt:DTI (match_dup:DTI 0)
+ (lshiftrt:DTI (match_dup:DTI 3)
(match_dup:SI 5)))]
{
- HOST_WIDE_INT val = INTVAL(operands[2]);
- operands[4] = GEN_INT (val&7);
- operands[5] = GEN_INT (val&-8);
+ operands[3] = gen_reg_rtx (<MODE>mode);
+ if (GET_CODE (operands[2]) == CONST_INT)
+ {
+ HOST_WIDE_INT val = INTVAL(operands[2]);
+ operands[4] = GEN_INT (val & 7);
+ operands[5] = GEN_INT (val & -8);
+ }
+ else
+ {
+ rtx t0 = gen_reg_rtx (SImode);
+ rtx t1 = gen_reg_rtx (SImode);
+ emit_insn (gen_subsi3(t0, GEN_INT(0), operands[2]));
+ emit_insn (gen_subsi3(t1, GEN_INT(7), operands[2]));
+ operands[4] = gen_rtx_AND (SImode, gen_rtx_NEG (SImode, t0), GEN_INT (7));
+ operands[5] = gen_rtx_AND (SImode, gen_rtx_NEG (SImode, gen_rtx_AND (SImode, t1, GEN_INT (-8))), GEN_INT (-8));
+ }
}
- [(set_attr "type" "shuf,shuf")])
-
-(define_insn_and_split "lshr<mode>3_reg"
- [(set (match_operand:DTI 0 "spu_reg_operand" "=r")
- (lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r")
- (match_operand:SI 2 "spu_reg_operand" "r")))
- (clobber (match_operand:DTI 3 "spu_reg_operand" "=&r"))
- (clobber (match_operand:SI 4 "spu_reg_operand" "=&r"))
- (clobber (match_operand:SI 5 "spu_reg_operand" "=&r"))]
- ""
- "#"
- ""
- [(set (match_dup:DTI 3)
- (lshiftrt:DTI (match_dup:DTI 1)
- (and:SI (neg:SI (match_dup:SI 4))
- (const_int 7))))
- (set (match_dup:DTI 0)
- (lshiftrt:DTI (match_dup:DTI 3)
- (and:SI (neg:SI (and:SI (match_dup:SI 5)
- (const_int -8)))
- (const_int -8))))]
- {
- emit_insn (gen_subsi3(operands[4], GEN_INT(0), operands[2]));
- emit_insn (gen_subsi3(operands[5], GEN_INT(7), operands[2]));
- })
+ [(set_attr "type" "*,shuf,shuf")])
-(define_insn_and_split "shrqbybi_<mode>"
+(define_expand "shrqbybi_<mode>"
[(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
(lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
- (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
- (const_int -8))))
- (clobber (match_scratch:SI 3 "=&r,X"))]
- ""
- "#"
- "reload_completed"
- [(set (match_dup:DTI 0)
- (lshiftrt:DTI (match_dup:DTI 1)
- (and:SI (neg:SI (and:SI (match_dup:SI 3) (const_int -8)))
+ (and:SI (neg:SI (and:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
+ (const_int -8)))
(const_int -8))))]
+ ""
{
if (GET_CODE (operands[2]) == CONST_INT)
- operands[3] = GEN_INT (7 - INTVAL (operands[2]));
+ operands[2] = GEN_INT (7 - INTVAL (operands[2]));
else
- emit_insn (gen_subsi3 (operands[3], GEN_INT (7), operands[2]));
- }
- [(set_attr "type" "shuf")])
+ {
+ rtx t0 = gen_reg_rtx (SImode);
+ emit_insn (gen_subsi3 (t0, GEN_INT (7), operands[2]));
+ operands[2] = t0;
+ }
+ })
(define_insn "rotqmbybi_<mode>"
[(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
@@ -2486,25 +2470,22 @@
rotqmbii\t%0,%1,-%E2"
[(set_attr "type" "shuf")])
-(define_insn_and_split "shrqby_<mode>"
+(define_expand "shrqby_<mode>"
[(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
(lshiftrt:DTI (match_operand:DTI 1 "spu_reg_operand" "r,r")
- (mult:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I")
- (const_int 8))))
- (clobber (match_scratch:SI 3 "=&r,X"))]
+ (mult:SI (neg:SI (match_operand:SI 2 "spu_nonmem_operand" "r,I"))
+ (const_int 8))))]
""
- "#"
- "reload_completed"
- [(set (match_dup:DTI 0)
- (lshiftrt:DTI (match_dup:DTI 1)
- (mult:SI (neg:SI (match_dup:SI 3)) (const_int 8))))]
{
if (GET_CODE (operands[2]) == CONST_INT)
- operands[3] = GEN_INT (-INTVAL (operands[2]));
+ operands[2] = GEN_INT (-INTVAL (operands[2]));
else
- emit_insn (gen_subsi3 (operands[3], GEN_INT (0), operands[2]));
- }
- [(set_attr "type" "shuf")])
+ {
+ rtx t0 = gen_reg_rtx (SImode);
+ emit_insn (gen_subsi3 (t0, GEN_INT (0), operands[2]));
+ operands[2] = t0;
+ }
+ })
(define_insn "rotqmby_<mode>"
[(set (match_operand:DTI 0 "spu_reg_operand" "=r,r")
@@ -2538,6 +2519,14 @@
""
[(set_attr "type" "*,fx3")])
+(define_insn "<v>ashr<mode>3_imm"
+ [(set (match_operand:VHSI 0 "spu_reg_operand" "=r")
+ (ashiftrt:VHSI (match_operand:VHSI 1 "spu_reg_operand" "r")
+ (match_operand:VHSI 2 "immediate_operand" "W")))]
+ ""
+ "rotma<bh>i\t%0,%1,-%<umask>2"
+ [(set_attr "type" "fx3")])
+
(define_insn "rotma_<mode>"
[(set (match_operand:VHSI 0 "spu_reg_operand" "=r,r")
@@ -2622,11 +2611,16 @@
})
-(define_expand "ashrti3"
- [(set (match_operand:TI 0 "spu_reg_operand" "")
- (ashiftrt:TI (match_operand:TI 1 "spu_reg_operand" "")
- (match_operand:SI 2 "spu_nonmem_operand" "")))]
+(define_insn_and_split "ashrti3"
+ [(set (match_operand:TI 0 "spu_reg_operand" "=r,r")
+ (ashiftrt:TI (match_operand:TI 1 "spu_reg_operand" "r,r")
+ (match_operand:SI 2 "spu_nonmem_operand" "r,i")))]
+ ""
+ "#"
""
+ [(set (match_dup:TI 0)
+ (ashiftrt:TI (match_dup:TI 1)
+ (match_dup:SI 2)))]
{
rtx sign_shift = gen_reg_rtx (SImode);
rtx sign_mask = gen_reg_rtx (TImode);
@@ -2711,33 +2705,133 @@
;; struct extract/insert
-;; We have to handle mem's because GCC will generate invalid SUBREG's
-;; if it handles them. We generate better code anyway.
+;; We handle mem's because GCC will generate invalid SUBREG's
+;; and inefficient code.
(define_expand "extv"
- [(set (match_operand 0 "register_operand" "")
- (sign_extract (match_operand 1 "register_operand" "")
- (match_operand:SI 2 "const_int_operand" "")
- (match_operand:SI 3 "const_int_operand" "")))]
+ [(set (match_operand:TI 0 "register_operand" "")
+ (sign_extract:TI (match_operand 1 "nonimmediate_operand" "")
+ (match_operand:SI 2 "const_int_operand" "")
+ (match_operand:SI 3 "const_int_operand" "")))]
""
- { spu_expand_extv(operands, 0); DONE; })
+ {
+ spu_expand_extv (operands, 0);
+ DONE;
+ })
(define_expand "extzv"
- [(set (match_operand 0 "register_operand" "")
- (zero_extract (match_operand 1 "register_operand" "")
+ [(set (match_operand:TI 0 "register_operand" "")
+ (zero_extract:TI (match_operand 1 "nonimmediate_operand" "")
(match_operand:SI 2 "const_int_operand" "")
(match_operand:SI 3 "const_int_operand" "")))]
""
- { spu_expand_extv(operands, 1); DONE; })
+ {
+ spu_expand_extv (operands, 1);
+ DONE;
+ })
(define_expand "insv"
- [(set (zero_extract (match_operand 0 "register_operand" "")
+ [(set (zero_extract (match_operand 0 "nonimmediate_operand" "")
(match_operand:SI 1 "const_int_operand" "")
(match_operand:SI 2 "const_int_operand" ""))
(match_operand 3 "nonmemory_operand" ""))]
""
{ spu_expand_insv(operands); DONE; })
+;; Simplify a number of patterns that get generated by extv, extzv,
+;; insv, and loads.
+(define_insn_and_split "trunc_shr_ti<mode>"
+ [(set (match_operand:QHSI 0 "spu_reg_operand" "=r")
+ (truncate:QHSI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "0")
+ (const_int 96)])))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ spu_split_convert (operands);
+ DONE;
+ }
+ [(set_attr "type" "convert")
+ (set_attr "length" "0")])
+
+(define_insn_and_split "trunc_shr_tidi"
+ [(set (match_operand:DI 0 "spu_reg_operand" "=r")
+ (truncate:DI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "0")
+ (const_int 64)])))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ spu_split_convert (operands);
+ DONE;
+ }
+ [(set_attr "type" "convert")
+ (set_attr "length" "0")])
+
+(define_insn_and_split "shl_ext_<mode>ti"
+ [(set (match_operand:TI 0 "spu_reg_operand" "=r")
+ (ashift:TI (match_operator:TI 2 "extend_operator" [(match_operand:QHSI 1 "spu_reg_operand" "0")])
+ (const_int 96)))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ spu_split_convert (operands);
+ DONE;
+ }
+ [(set_attr "type" "convert")
+ (set_attr "length" "0")])
+
+(define_insn_and_split "shl_ext_diti"
+ [(set (match_operand:TI 0 "spu_reg_operand" "=r")
+ (ashift:TI (match_operator:TI 2 "extend_operator" [(match_operand:DI 1 "spu_reg_operand" "0")])
+ (const_int 64)))]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ spu_split_convert (operands);
+ DONE;
+ }
+ [(set_attr "type" "convert")
+ (set_attr "length" "0")])
+
+(define_insn "sext_trunc_lshr_tiqisi"
+ [(set (match_operand:SI 0 "spu_reg_operand" "=r")
+ (sign_extend:SI (truncate:QI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
+ (const_int 120)]))))]
+ ""
+ "rotmai\t%0,%1,-24"
+ [(set_attr "type" "fx3")])
+
+(define_insn "zext_trunc_lshr_tiqisi"
+ [(set (match_operand:SI 0 "spu_reg_operand" "=r")
+ (zero_extend:SI (truncate:QI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
+ (const_int 120)]))))]
+ ""
+ "rotmi\t%0,%1,-24"
+ [(set_attr "type" "fx3")])
+
+(define_insn "sext_trunc_lshr_tihisi"
+ [(set (match_operand:SI 0 "spu_reg_operand" "=r")
+ (sign_extend:SI (truncate:HI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
+ (const_int 112)]))))]
+ ""
+ "rotmai\t%0,%1,-16"
+ [(set_attr "type" "fx3")])
+
+(define_insn "zext_trunc_lshr_tihisi"
+ [(set (match_operand:SI 0 "spu_reg_operand" "=r")
+ (zero_extend:SI (truncate:HI (match_operator:TI 2 "shiftrt_operator" [(match_operand:TI 1 "spu_reg_operand" "r")
+ (const_int 112)]))))]
+ ""
+ "rotmi\t%0,%1,-16"
+ [(set_attr "type" "fx3")])
+
;; String/block move insn.
;; Argument 0 is the destination
@@ -4303,21 +4397,20 @@ selb\t%0,%4,%0,%3"
DONE;
})
-(define_insn "_spu_convert"
+(define_insn_and_split "_spu_convert"
[(set (match_operand 0 "spu_reg_operand" "=r")
(unspec [(match_operand 1 "spu_reg_operand" "0")] UNSPEC_CONVERT))]
- "operands"
""
+ "#"
+ "reload_completed"
+ [(const_int 0)]
+ {
+ spu_split_convert (operands);
+ DONE;
+ }
[(set_attr "type" "convert")
(set_attr "length" "0")])
-(define_peephole2
- [(set (match_operand 0 "spu_reg_operand")
- (unspec [(match_operand 1 "spu_reg_operand")] UNSPEC_CONVERT))]
- ""
- [(use (const_int 0))]
- "")
-
;;
(include "spu-builtins.md")
@@ -5186,8 +5279,8 @@ DONE;
}")
(define_insn "stack_protect_set"
- [(set (match_operand:SI 0 "spu_mem_operand" "=m")
- (unspec:SI [(match_operand:SI 1 "spu_mem_operand" "m")] UNSPEC_SP_SET))
+ [(set (match_operand:SI 0 "memory_operand" "=m")
+ (unspec:SI [(match_operand:SI 1 "memory_operand" "m")] UNSPEC_SP_SET))
(set (match_scratch:SI 2 "=&r") (const_int 0))]
""
"lq%p1\t%2,%1\;stq%p0\t%2,%0\;xor\t%2,%2,%2"
@@ -5196,8 +5289,8 @@ DONE;
)
(define_expand "stack_protect_test"
- [(match_operand 0 "spu_mem_operand" "")
- (match_operand 1 "spu_mem_operand" "")
+ [(match_operand 0 "memory_operand" "")
+ (match_operand 1 "memory_operand" "")
(match_operand 2 "" "")]
""
{
@@ -5223,8 +5316,8 @@ DONE;
(define_insn "stack_protect_test_si"
[(set (match_operand:SI 0 "spu_reg_operand" "=&r")
- (unspec:SI [(match_operand:SI 1 "spu_mem_operand" "m")
- (match_operand:SI 2 "spu_mem_operand" "m")]
+ (unspec:SI [(match_operand:SI 1 "memory_operand" "m")
+ (match_operand:SI 2 "memory_operand" "m")]
UNSPEC_SP_TEST))
(set (match_scratch:SI 3 "=&r") (const_int 0))]
""
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 6029411f2ae..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
- $(CXX) -c $(ALL_CXXFLAGS) $(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)
- $(CXX) -c $(ALL_CXXFLAGS) $(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
- $(CXX) -c $(ALL_CXXFLAGS) $(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)
- $(CXX) -c $(ALL_CXXFLAGS) $(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-protos.h b/gcc/config/vax/vax-protos.h
index 86feccda732..e9cc61687ca 100644
--- a/gcc/config/vax/vax-protos.h
+++ b/gcc/config/vax/vax-protos.h
@@ -19,9 +19,9 @@ along with GCC; see the file COPYING3. If not see
extern void override_options (void);
-extern int legitimate_constant_address_p (rtx);
-extern int legitimate_constant_p (rtx);
-extern int vax_mode_dependent_address_p (rtx);
+extern bool legitimate_constant_address_p (rtx);
+extern bool legitimate_constant_p (rtx);
+extern bool vax_mode_dependent_address_p (rtx);
#ifdef RTX_CODE
extern const char *cond_name (rtx);
diff --git a/gcc/config/x-darwin b/gcc/config/x-darwin
index b7b653d96b4..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
- $(CXX) -c $(ALL_CXXFLAGS) $(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 56907723135..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)
- $(CXX) -c $(ALL_CXXFLAGS) $(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 96616b75e74..eb5606a905a 100755
--- a/gcc/configure
+++ b/gcc/configure
@@ -26022,6 +26022,22 @@ x:
tls_first_minor=16
tls_as_opt='-32 --fatal-warnings'
;;
+ m68k-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+foo:
+ move.l x@TLSGD(%a5),%a0
+ move.l x@TLSLDM(%a5),%a0
+ move.l x@TLSLDO(%a5),%a0
+ move.l x@TLSIE(%a5),%a0
+ move.l x@TLSLE(%a5),%a0'
+ tls_first_major=2
+ tls_first_minor=19
+ tls_as_opt='--fatal-warnings'
+ ;;
powerpc-*-*)
conftest_s='
.section ".tdata","awT",@progbits
@@ -26653,6 +26669,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
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 5b41a0c7b74..10b700661e1 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -2577,6 +2577,22 @@ x:
tls_first_minor=16
tls_as_opt='-32 --fatal-warnings'
;;
+ m68k-*-*)
+ conftest_s='
+ .section .tdata,"awT",@progbits
+x:
+ .word 2
+ .text
+foo:
+ move.l x@TLSGD(%a5),%a0
+ move.l x@TLSLDM(%a5),%a0
+ move.l x@TLSLDO(%a5),%a0
+ move.l x@TLSIE(%a5),%a0
+ move.l x@TLSLE(%a5),%a0'
+ tls_first_major=2
+ tls_first_minor=19
+ tls_as_opt='--fatal-warnings'
+ ;;
powerpc-*-*)
conftest_s='
.section ".tdata","awT",@progbits
@@ -2945,6 +2961,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,
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 7bd5f934812..11be689a536 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,257 @@
+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
+ * typeck.c (cp_build_binary_op): Allow ENUMERAL_TYPE in
+ arithmetic comparisons.
+ (cp_common_type): Handle scoped enums.
+
+ * call.c (promoted_arithmetic_type_p): Don't use INTEGRAL_TYPE_P.
+ (add_builtin_candidate, add_builtin_candidates): Likewise.
+ (convert_like_real): Likewise.
+ * class.c (check_bitfield_decl): Likewise.
+ * decl.c (check_static_variable_definition): Likewise.
+ (compute_array_index_type): Likewise.
+ * decl2.c (grokbitfield): Likewise.
+ * init.c (build_new_1): Likewise.
+ * pt.c (convert_nontype_argument): Likewise.
+ (current_instantiation): Likewise.
+ * tree.c (pod_type_p): Likewise.
+ * typeck.c (build_static_cast_1): Likewise.
+ (build_reinterpret_cast_1): Likewise.
+
+2009-05-22 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/38964
+ * init.c (avoid_placement_new_aliasing): Remove.
+ (build_new_1): Do not call it.
+
+2009-05-22 Mark Mitchell <mark@codesourcery.com>
+
+ * decl2.c (decl_needed_p): Consider dllexport'd functions needed.
+ * semantics.c (expand_or_defer_fn): Similarly.
+
+2009-05-20 Ian Lance Taylor <iant@google.com>
+
+ * parser.c (cp_parser_postfix_expression): Change args to a vec.
+ Release it when done.
+ (tree_vector): Define typedef. Define VEC functions.
+ (cp_parser_parenthesized_expression_list): Change return type to
+ vec. Change all callers.
+ (cp_parser_new_expression): Change placement and initializer to
+ vecs. Release them when done.
+ (cp_parser_new_placement): Change return type to vec. Change all
+ callers.
+ (cp_parser_new_initializer): Likewise.
+ * typeck.c (build_function_call_vec): Just call
+ cp_build_function_call_vec.
+ (cp_build_function_call): Just build a vec and call
+ cp_build_function_call_vec.
+ (cp_build_function_call_vec): New function based on old
+ cp_build_function_call.
+ (convert_arguments): Remove nargs and argarray parameters. Change
+ values to a vec. Change caller.
+ (build_x_compound_expr_from_vec): New function.
+ (cp_build_modify_expr): Build vec to pass to
+ build_special_member_call.
+ * call.c (struct z_candidate): Add first_arg field. Change args
+ field to vec.
+ (convert_class_to_reference): Handle first argument separately.
+ (add_candidate): Add first_arg parameter. Change args parameter
+ to vec. Change all callers.
+ (add_function_candidate, add_conv_candidate): Likewise.
+ (add_template_candidate_real, add_template_candidate): Likewise.
+ (add_template_conv_candidate): Likewise.
+ (build_user_type_conversion_1): Handle first argument separately.
+ (resolve_args): Change return type and parameter type to vecs.
+ Change all callers.
+ (perform_overload_resolution): Change args parameter to vec.
+ Change all callers.
+ (build_new_function_call, build_operator_new_call): Likewise.
+ (add_candidates): Likewise.
+ (build_op_call): New globally visible function, built from and
+ replacing static function build_object_call.
+ (build_new_op): Don't handle CALL_EXPR. Build vec, not tree_list,
+ of arguments.
+ (build_op_delete_call): Build vec to pass to
+ cp_build_function_call_vec.
+ (build_temp): Build vec to pass to build_special_member_call.
+ (convert_like_real): Likewise.
+ (perform_direct_initialization_if_possible): Likewise.
+ (build_over_call): Handle first_arg field. Use build_call_array
+ rather than build_call_list.
+ (build_special_member_call): Change args parameter to vec. Change
+ all callers.
+ (build_new_method_call): Likewise.
+ * init.c (expand_default_init): Change parms to vec.
+ (build_raw_new_expr): Change placement and init to vecs. Change
+ all callers.
+ (build_new_1, build_new): Likewise.
+ * class.c (resolve_address_of_overloaded_function): Build array to
+ pass to fn_type_unification.
+ * pt.c (tsubst_copy_and_build): For NEW_EXPR build vecs to pass to
+ build_new. For CALL_EXPR create a vec rather than a tree_list;
+ expand a pack if necessary.
+ (fn_type_unification): Change args parameter to const tree *. Add
+ nargs parameter. Change all callers.
+ (type_unification_real): Likewise.
+ (unify): Build array to pass to type_unification_real.
+ (get_bindings): Build array to pass to fn_type_unification.
+ (any_type_dependent_arguments_p): Change args parameter to a vec.
+ Change all callers.
+ (make_args_non_dependent): Renamed from build_non_dependent_args.
+ Change return type to void. Change parameter type to vec. Change
+ all callers.
+ (do_auto_deduction): Pass an array to type_unification_real.
+ * semantics.c (perform_koenig_lookup): Change args to vec. Change
+ all callers.
+ (finish_call_expr): Change args to vec. Change all callers. Call
+ build_op_call instead of passing CALL_EXPR to build_new_op.
+ (cxx_omp_create_clause_info): Allocate vec to pass to
+ build_special_member_call.
+ * decl2.c (build_offset_ref_call_from_tree): Change args parameter
+ to vec. Change all callers.
+ * name-lookup.c (lookup_function_nonclass): Likewise.
+ (struct arg_lookup): Change args to vec.
+ (arg_assoc_namespace): Handle args as a vec.
+ (arg_assoc_args_vec): New static function.
+ (lookup_arg_dependent): Change args parameter to vec. Change all
+ callers.
+ * method.c (do_build_assign_ref): Allocate vec to pass to
+ build_special_member_call.
+ * except.c (build_throw): Likewise.
+ * typeck2.c (build_functional_cast): Likewise.
+ * cvt.c (ocp_convert): Likewise.
+ * tree.c (build_min_non_dep_call_vec): Change last parameter to
+ vec. Change all callers.
+ * cp-tree.h: Update declarations.
+ * name-lookup.h: Update declarations.
+
+2009-05-20 Sandra Loosemore <sandra@codesourcery.com>
+
+ * typeck.c (default_conversion): Check targetm.promoted_type.
+ * decl.c (grokdeclarator): Check targetm.invalid_return_type.
+ (grokparms): Check targetm.invalid_parameter_type.
+ * cvt.c (ocp_convert): Check targetm.convert_to_type.
+ (build_expr_type_conversion): Check targetm.promoted_type.
+
+2009-05-19 Andrew Pinski <andrew_pinski@playstation.sony.com>
+
+ * typeck.c (build_binary_op): Allow % on integal vectors.
+
+2009-05-18 Jason Merrill <jason@redhat.com>
+
+ Implement explicit conversions ops as specified in N2437.
+ * decl.c (grokdeclarator): Handle explicit conversion ops.
+ (check_initializer): Pass flags to store_init_value.
+ * decl2.c (maybe_emit_vtables): Likewise.
+ * init.c (expand_aggr_init_1): Likewise.
+ * call.c (convert_class_to_reference): Take flags parm,
+ check DECL_NONCONVERTING_P.
+ (build_user_type_conversion_1): Check DECL_NONCONVERTING_P.
+ (add_builtin_candidates): Simplify getting type of conversion.
+ (build_object_call): Likewise. Check DECL_NONCONVERTING_P.
+ (implicit_conversion): Pass through LOOKUP_ONLYCONVERTING.
+ (reference_binding): Take flags parm. Direct-initialize copy parm.
+ (add_function_candidate): Direct-initialize the copy parm.
+ (add_conv_candidate): Use LOOKUP_IMPLICIT, not LOOKUP_NORMAL.
+ (build_builtin_candidate): Add LOOKUP_ONLYCONVERTING.
+ (conditional_conversion): Likewise.
+ (convert_like_real): Only complain about DECL_NONCONVERTING_P
+ constructors.
+ (perform_implicit_conversion_flags): Add flags parm to
+ perform_implicit_conversion. Improve diagnostics.
+ * cp-tree.h (LOOKUP_IMPLICIT): New macro.
+ (LOOKUP_COPY_PARM): New bit macro.
+ * cvt.c (build_expr_type_conversion): Check DECL_NONCONVERTING_P.
+ * typeck.c (convert_for_assignment): Take flags parm, pass it to
+ perform_implicit_conversion_flags.
+ (cp_build_modify_expr): Pass flags to convert_for_assignment.
+ (convert_for_initialization): Likewise.
+ * typeck2.c (store_init_value): Take flags parm, pass to
+ digest_init_flags.
+ (digest_init_flags): Add flags parm to digest_init.
+ (digest_init_r): Take flags parm, pass to convert_for_initialization.
+ (process_init_constructor_array): Pass it.
+ (process_init_constructor_record): Likewise.
+ (process_init_constructor_union): Likewise.
+
+2009-05-16 Jason Merrill <jason@redhat.com>
+
+ PR c++/40139
+ * pt.c (tsubst_qualified_id): Retain the type if we aren't dealing
+ with a dependent type. Actually look up the destructor.
+ * semantics.c (finish_id_expression): Fix logic.
+ (finish_qualified_id_expr): Don't try to use 'this' if we aren't in
+ a function.
+ * typeck.c (build_x_unary_op): Diagnose taking the address of a
+ constructor or destructor.
+ * tree.c (get_first_fn): Handle OFFSET_REF.
+
+2009-05-17 Joseph Myers <joseph@codesourcery.com>
+
+ * tree.c (cxx_printable_name_internal): Allow consecutive
+ translated and untranslated cached copies of the name of the
+ current function.
+
2009-05-15 Ian Lance Taylor <iant@google.com>
* cp-tree.h (enum cp_lvalue_kind_flags): Rename from
diff --git a/gcc/cp/Make-lang.in b/gcc/cp/Make-lang.in
index d4ca5af69ab..bdc5192df15 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)'; \
- $(CXX) -c $(ALL_CXXFLAGS) $(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)
- $(CXX) $(ALL_CXXFLAGS) $(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)
- $(CXX) $(ALL_CXXFLAGS) $(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)
- $(CXX) $(ALL_CXXFLAGS) $(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 607e3edc4f5..138abe017fe 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -145,8 +145,7 @@ static tree convert_like_real (conversion *, tree, tree, int, int, bool,
bool, tsubst_flags_t);
static void op_error (enum tree_code, enum tree_code, tree, tree,
tree, const char *);
-static tree build_object_call (tree, tree, tsubst_flags_t);
-static tree resolve_args (tree);
+static VEC(tree,gc) *resolve_args (VEC(tree,gc) *);
static struct z_candidate *build_user_type_conversion_1 (tree, tree, int);
static void print_z_candidate (const char *, struct z_candidate *);
static void print_z_candidates (struct z_candidate *);
@@ -154,13 +153,14 @@ static tree build_this (tree);
static struct z_candidate *splice_viable (struct z_candidate *, bool, bool *);
static bool any_strictly_viable (struct z_candidate *);
static struct z_candidate *add_template_candidate
- (struct z_candidate **, tree, tree, tree, tree, tree,
- tree, tree, int, unification_kind_t);
+ (struct z_candidate **, tree, tree, tree, tree, const VEC(tree,gc) *,
+ tree, tree, tree, int, unification_kind_t);
static struct z_candidate *add_template_candidate_real
- (struct z_candidate **, tree, tree, tree, tree, tree,
- tree, tree, int, tree, unification_kind_t);
+ (struct z_candidate **, tree, tree, tree, tree, const VEC(tree,gc) *,
+ tree, tree, tree, int, tree, unification_kind_t);
static struct z_candidate *add_template_conv_candidate
- (struct z_candidate **, tree, tree, tree, tree, tree, tree);
+ (struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
+ tree, tree);
static void add_builtin_candidates
(struct z_candidate **, enum tree_code, enum tree_code,
tree, tree *, int);
@@ -172,9 +172,11 @@ static void build_builtin_candidate
(struct z_candidate **, tree, tree, tree, tree *, tree *,
int);
static struct z_candidate *add_conv_candidate
- (struct z_candidate **, tree, tree, tree, tree, tree);
+ (struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
+ tree);
static struct z_candidate *add_function_candidate
- (struct z_candidate **, tree, tree, tree, tree, tree, int);
+ (struct z_candidate **, tree, tree, tree, const VEC(tree,gc) *, tree,
+ tree, int);
static conversion *implicit_conversion (tree, tree, tree, bool, int);
static conversion *standard_conversion (tree, tree, tree, bool, int);
static conversion *reference_binding (tree, tree, tree, bool, int);
@@ -184,20 +186,20 @@ static bool is_subseq (conversion *, conversion *);
static conversion *maybe_handle_ref_bind (conversion **);
static void maybe_handle_implicit_object (conversion **);
static struct z_candidate *add_candidate
- (struct z_candidate **, tree, tree, size_t,
+ (struct z_candidate **, tree, tree, const VEC(tree,gc) *, size_t,
conversion **, tree, tree, int);
static tree source_type (conversion *);
static void add_warning (struct z_candidate *, struct z_candidate *);
static bool reference_related_p (tree, tree);
static bool reference_compatible_p (tree, tree);
-static conversion *convert_class_to_reference (tree, tree, tree);
+static conversion *convert_class_to_reference (tree, tree, tree, int);
static conversion *direct_reference_binding (tree, conversion *);
static bool promoted_arithmetic_type_p (tree);
static conversion *conditional_conversion (tree, tree);
static char *name_as_c_string (tree, tree, bool *);
static tree call_builtin_trap (void);
static tree prep_operand (tree);
-static void add_candidates (tree, tree, tree, bool, tree, tree,
+static void add_candidates (tree, const VEC(tree,gc) *, tree, bool, tree, tree,
int, struct z_candidate **);
static conversion *merge_conversion_sequences (conversion *, conversion *);
static bool magic_varargs_p (tree);
@@ -413,8 +415,13 @@ struct z_candidate {
/* The FUNCTION_DECL that will be called if this candidate is
selected by overload resolution. */
tree fn;
- /* The arguments to use when calling this function. */
- tree args;
+ /* If not NULL_TREE, the first argument to use when calling this
+ function. */
+ tree first_arg;
+ /* The rest of the arguments to use when calling this function. If
+ there are no further arguments this may be NULL or it may be an
+ empty vector. */
+ const VEC(tree,gc) *args;
/* The implicit conversion sequences for each of the arguments to
FN. */
conversion **convs;
@@ -993,10 +1000,10 @@ reference_compatible_p (tree t1, tree t2)
converted to T as in [over.match.ref]. */
static conversion *
-convert_class_to_reference (tree reference_type, tree s, tree expr)
+convert_class_to_reference (tree reference_type, tree s, tree expr, int flags)
{
tree conversions;
- tree arglist;
+ tree first_arg;
conversion *conv;
tree t;
struct z_candidate *candidates;
@@ -1029,12 +1036,11 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
error messages, which we should not issue now because we are just
trying to find a conversion operator. Therefore, we use NULL,
cast to the appropriate type. */
- arglist = build_int_cst (build_pointer_type (s), 0);
- arglist = build_tree_list (NULL_TREE, arglist);
+ first_arg = build_int_cst (build_pointer_type (s), 0);
t = TREE_TYPE (reference_type);
- while (conversions)
+ for (; conversions; conversions = TREE_CHAIN (conversions))
{
tree fns = TREE_VALUE (conversions);
@@ -1043,6 +1049,10 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
tree f = OVL_CURRENT (fns);
tree t2 = TREE_TYPE (TREE_TYPE (f));
+ if (DECL_NONCONVERTING_P (f)
+ && (flags & LOOKUP_ONLYCONVERTING))
+ continue;
+
cand = NULL;
/* If this is a template function, try to get an exact
@@ -1052,7 +1062,8 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
cand = add_template_candidate (&candidates,
f, s,
NULL_TREE,
- arglist,
+ first_arg,
+ NULL,
reference_type,
TYPE_BINFO (s),
TREE_PURPOSE (conversions),
@@ -1077,8 +1088,8 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
}
else if (TREE_CODE (t2) == REFERENCE_TYPE
&& reference_compatible_p (t, TREE_TYPE (t2)))
- cand = add_function_candidate (&candidates, f, s, arglist,
- TYPE_BINFO (s),
+ cand = add_function_candidate (&candidates, f, s, first_arg,
+ NULL, TYPE_BINFO (s),
TREE_PURPOSE (conversions),
LOOKUP_NORMAL);
@@ -1101,7 +1112,6 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
cand->second_conv->bad_p |= cand->convs[0]->bad_p;
}
}
- conversions = TREE_CHAIN (conversions);
}
candidates = splice_viable (candidates, pedantic, &any_viable_p);
@@ -1116,9 +1126,9 @@ convert_class_to_reference (tree reference_type, tree s, tree expr)
/* Now that we know that this is the function we're going to use fix
the dummy first argument. */
- cand->args = tree_cons (NULL_TREE,
- build_this (expr),
- TREE_CHAIN (cand->args));
+ gcc_assert (cand->first_arg == NULL_TREE
+ || integer_zerop (cand->first_arg));
+ cand->first_arg = build_this (expr);
/* Build a user-defined conversion sequence representing the
conversion. */
@@ -1303,7 +1313,7 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
the reference is bound to the lvalue result of the conversion
in the second case. */
- conv = convert_class_to_reference (rto, from, expr);
+ conv = convert_class_to_reference (rto, from, expr, flags);
if (conv)
return conv;
}
@@ -1347,6 +1357,12 @@ reference_binding (tree rto, tree rfrom, tree expr, bool c_cast_p, int flags)
conversion operator). */
flags |= LOOKUP_NO_TEMP_BIND;
+ /* Temporaries are copy-initialized, except for this hack to allow
+ explicit conversion ops to the copy ctor. See also
+ add_function_candidate. */
+ if (!(flags & LOOKUP_COPY_PARM))
+ flags |= LOOKUP_ONLYCONVERTING;
+
conv = implicit_conversion (to, from, expr, c_cast_p,
flags);
if (!conv)
@@ -1384,9 +1400,31 @@ 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 this is copy-initialization. Direct-initialization
+ would be something like int i({1}), which is invalid. */
+ if (SCALAR_TYPE_P (to) && CONSTRUCTOR_NELTS (expr) <= 1
+ && (flags & LOOKUP_ONLYCONVERTING))
+ {
+ tree elt;
+ if (CONSTRUCTOR_NELTS (expr) == 1)
+ elt = CONSTRUCTOR_ELT (expr, 0)->value;
+ else
+ elt = integer_zero_node;
+ conv = implicit_conversion (to, TREE_TYPE (elt), elt,
+ c_cast_p, flags);
+ if (conv)
+ {
+ conv->check_narrowing = true;
+ return conv;
+ }
+ }
+ }
if (expr != NULL_TREE
&& (MAYBE_CLASS_TYPE_P (from)
@@ -1394,8 +1432,7 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
&& (flags & LOOKUP_NO_CONVERSION) == 0)
{
struct z_candidate *cand;
- int convflags = ((flags & LOOKUP_NO_TEMP_BIND)
- |LOOKUP_ONLYCONVERTING);
+ int convflags = (flags & (LOOKUP_NO_TEMP_BIND|LOOKUP_ONLYCONVERTING));
if (CLASS_TYPE_P (to)
&& !CLASSTYPE_NON_AGGREGATE (complete_type (to))
@@ -1416,11 +1453,12 @@ implicit_conversion (tree to, tree from, tree expr, bool c_cast_p,
}
/* Add a new entry to the list of candidates. Used by the add_*_candidate
- functions. */
+ functions. ARGS will not be changed until a single candidate is
+ selected. */
static struct z_candidate *
add_candidate (struct z_candidate **candidates,
- tree fn, tree args,
+ tree fn, tree first_arg, const VEC(tree,gc) *args,
size_t num_convs, conversion **convs,
tree access_path, tree conversion_path,
int viable)
@@ -1429,6 +1467,7 @@ add_candidate (struct z_candidate **candidates,
conversion_obstack_alloc (sizeof (struct z_candidate));
cand->fn = fn;
+ cand->first_arg = first_arg;
cand->args = args;
cand->convs = convs;
cand->num_convs = num_convs;
@@ -1441,24 +1480,27 @@ add_candidate (struct z_candidate **candidates,
return cand;
}
-/* Create an overload candidate for the function or method FN called with
- the argument list ARGLIST and add it to CANDIDATES. FLAGS is passed on
- to implicit_conversion.
+/* Create an overload candidate for the function or method FN called
+ with the argument list FIRST_ARG/ARGS and add it to CANDIDATES.
+ FLAGS is passed on to implicit_conversion.
+
+ This does not change ARGS.
CTYPE, if non-NULL, is the type we want to pretend this function
comes from for purposes of overload resolution. */
static struct z_candidate *
add_function_candidate (struct z_candidate **candidates,
- tree fn, tree ctype, tree arglist,
- tree access_path, tree conversion_path,
- int flags)
+ tree fn, tree ctype, tree first_arg,
+ const VEC(tree,gc) *args, tree access_path,
+ tree conversion_path, int flags)
{
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (fn));
int i, len;
conversion **convs;
- tree parmnode, argnode;
- tree orig_arglist;
+ tree parmnode;
+ tree orig_first_arg = first_arg;
+ int skip;
int viable = 1;
/* At this point we should not see any functions which haven't been
@@ -1471,13 +1513,17 @@ add_function_candidate (struct z_candidate **candidates,
if (DECL_CONSTRUCTOR_P (fn))
{
parmlist = skip_artificial_parms_for (fn, parmlist);
- orig_arglist = arglist;
- arglist = skip_artificial_parms_for (fn, arglist);
+ skip = num_artificial_parms_for (fn);
+ if (skip > 0 && first_arg != NULL_TREE)
+ {
+ --skip;
+ first_arg = NULL_TREE;
+ }
}
else
- orig_arglist = arglist;
+ skip = 0;
- len = list_length (arglist);
+ len = VEC_length (tree, args) - skip + (first_arg != NULL_TREE ? 1 : 0);
convs = alloc_conversions (len);
/* 13.3.2 - Viable functions [over.match.viable]
@@ -1510,18 +1556,23 @@ add_function_candidate (struct z_candidate **candidates,
to the corresponding parameter of F. */
parmnode = parmlist;
- argnode = arglist;
for (i = 0; i < len; ++i)
{
- tree arg = TREE_VALUE (argnode);
- tree argtype = lvalue_type (arg);
+ tree arg, argtype;
conversion *t;
int is_this;
if (parmnode == void_list_node)
break;
+ if (i == 0 && first_arg != NULL_TREE)
+ arg = first_arg;
+ else
+ arg = VEC_index (tree, args,
+ i + skip - (first_arg != NULL_TREE ? 1 : 0));
+ argtype = lvalue_type (arg);
+
is_this = (i == 0 && DECL_NONSTATIC_MEMBER_FUNCTION_P (fn)
&& ! DECL_CONSTRUCTOR_P (fn));
@@ -1547,9 +1598,17 @@ add_function_candidate (struct z_candidate **candidates,
parmtype = build_pointer_type (parmtype);
}
- if ((flags & LOOKUP_NO_COPY_CTOR_CONVERSION)
- && ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn))
- lflags |= LOOKUP_NO_CONVERSION;
+ if (ctype && i == 0 && DECL_COPY_CONSTRUCTOR_P (fn))
+ {
+ /* Hack: Direct-initialize copy parm (i.e. suppress
+ LOOKUP_ONLYCONVERTING) to make explicit conversion ops
+ work. See also reference_binding. */
+ lflags |= LOOKUP_COPY_PARM;
+ if (flags & LOOKUP_NO_COPY_CTOR_CONVERSION)
+ lflags |= LOOKUP_NO_CONVERSION;
+ }
+ else
+ lflags |= LOOKUP_ONLYCONVERTING;
t = implicit_conversion (parmtype, argtype, arg,
/*c_cast_p=*/false, lflags);
@@ -1575,18 +1634,18 @@ add_function_candidate (struct z_candidate **candidates,
if (parmnode)
parmnode = TREE_CHAIN (parmnode);
- argnode = TREE_CHAIN (argnode);
}
out:
- return add_candidate (candidates, fn, orig_arglist, len, convs,
+ return add_candidate (candidates, fn, orig_first_arg, args, len, convs,
access_path, conversion_path, viable);
}
/* Create an overload candidate for the conversion function FN which will
be invoked for expression OBJ, producing a pointer-to-function which
- will in turn be called with the argument list ARGLIST, and add it to
- CANDIDATES. FLAGS is passed on to implicit_conversion.
+ will in turn be called with the argument list FIRST_ARG/ARGLIST,
+ and add it to CANDIDATES. This does not change ARGLIST. FLAGS is
+ passed on to implicit_conversion.
Actually, we don't really care about FN; we care about the type it
converts to. There may be multiple conversion functions that will
@@ -1596,23 +1655,23 @@ add_function_candidate (struct z_candidate **candidates,
static struct z_candidate *
add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
- tree arglist, tree access_path, tree conversion_path)
+ tree first_arg, const VEC(tree,gc) *arglist,
+ tree access_path, tree conversion_path)
{
tree totype = TREE_TYPE (TREE_TYPE (fn));
int i, len, viable, flags;
- tree parmlist, parmnode, argnode;
+ tree parmlist, parmnode;
conversion **convs;
for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; )
parmlist = TREE_TYPE (parmlist);
parmlist = TYPE_ARG_TYPES (parmlist);
- len = list_length (arglist) + 1;
+ len = VEC_length (tree, arglist) + (first_arg != NULL_TREE ? 1 : 0) + 1;
convs = alloc_conversions (len);
parmnode = parmlist;
- argnode = arglist;
viable = 1;
- flags = LOOKUP_NORMAL;
+ flags = LOOKUP_IMPLICIT;
/* Don't bother looking up the same type twice. */
if (*candidates && (*candidates)->fn == totype)
@@ -1620,11 +1679,19 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
for (i = 0; i < len; ++i)
{
- tree arg = i == 0 ? obj : TREE_VALUE (argnode);
- tree argtype = lvalue_type (arg);
+ tree arg, argtype;
conversion *t;
if (i == 0)
+ arg = obj;
+ else if (i == 1 && first_arg != NULL_TREE)
+ arg = first_arg;
+ else
+ arg = VEC_index (tree, arglist,
+ i - (first_arg != NULL_TREE ? 1 : 0) - 1);
+ argtype = lvalue_type (arg);
+
+ if (i == 0)
t = implicit_conversion (totype, argtype, arg, /*c_cast_p=*/false,
flags);
else if (parmnode == void_list_node)
@@ -1650,7 +1717,6 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
if (parmnode)
parmnode = TREE_CHAIN (parmnode);
- argnode = TREE_CHAIN (argnode);
}
if (i < len)
@@ -1659,7 +1725,7 @@ add_conv_candidate (struct z_candidate **candidates, tree fn, tree obj,
if (!sufficient_parms_p (parmnode))
viable = 0;
- return add_candidate (candidates, totype, arglist, len, convs,
+ return add_candidate (candidates, totype, first_arg, arglist, len, convs,
access_path, conversion_path, viable);
}
@@ -1679,6 +1745,7 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
num_convs = args[2] ? 3 : (args[1] ? 2 : 1);
convs = alloc_conversions (num_convs);
+ flags |= LOOKUP_ONLYCONVERTING;
for (i = 0; i < 2; ++i)
{
@@ -1711,7 +1778,7 @@ build_builtin_candidate (struct z_candidate **candidates, tree fnname,
viable = 0;
}
- add_candidate (candidates, fnname, /*args=*/NULL_TREE,
+ add_candidate (candidates, fnname, /*first_arg=*/NULL_TREE, /*args=*/NULL,
num_convs, convs,
/*access_path=*/NULL_TREE,
/*conversion_path=*/NULL_TREE,
@@ -1736,7 +1803,7 @@ promoted_arithmetic_type_p (tree type)
(including e.g. int and long but excluding e.g. char).
Similarly, the term promoted arithmetic type refers to promoted
integral types plus floating types. */
- return ((INTEGRAL_TYPE_P (type)
+ return ((CP_INTEGRAL_TYPE_P (type)
&& same_type_p (type_promotes_to (type), type))
|| TREE_CODE (type) == REAL_TYPE);
}
@@ -1838,7 +1905,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
T operator~(T); */
case BIT_NOT_EXPR:
- if (INTEGRAL_TYPE_P (type1))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1))
break;
return;
@@ -1908,7 +1975,8 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
case MINUS_EXPR:
if (TYPE_PTROB_P (type1) && TYPE_PTROB_P (type2))
break;
- if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (TYPE_PTROB_P (type1)
+ && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
@@ -1968,12 +2036,12 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
case ARRAY_REF:
- if (INTEGRAL_TYPE_P (type1) && TYPE_PTROB_P (type2))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1) && TYPE_PTROB_P (type2))
{
type1 = ptrdiff_type_node;
break;
}
- if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (TYPE_PTROB_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
@@ -1997,7 +2065,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
case BIT_XOR_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
- if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
break;
return;
@@ -2042,7 +2110,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
{
case PLUS_EXPR:
case MINUS_EXPR:
- if (TYPE_PTROB_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (TYPE_PTROB_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
{
type2 = ptrdiff_type_node;
break;
@@ -2059,7 +2127,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
case BIT_XOR_EXPR:
case LSHIFT_EXPR:
case RSHIFT_EXPR:
- if (INTEGRAL_TYPE_P (type1) && INTEGRAL_TYPE_P (type2))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type1) && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type2))
break;
return;
@@ -2268,7 +2336,7 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
for (; convs; convs = TREE_CHAIN (convs))
{
- type = TREE_TYPE (TREE_TYPE (OVL_CURRENT (TREE_VALUE (convs))));
+ type = TREE_TYPE (convs);
if (i == 0 && ref1
&& (TREE_CODE (type) != REFERENCE_TYPE
@@ -2284,7 +2352,7 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
type = TYPE_MAIN_VARIANT (type_decays_to (type));
if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
types[i] = tree_cons (NULL_TREE, type, types[i]);
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
type = type_promotes_to (type);
}
@@ -2301,9 +2369,9 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
if (i != 0 || ! ref1)
{
type = TYPE_MAIN_VARIANT (type_decays_to (type));
- if (enum_p && TREE_CODE (type) == ENUMERAL_TYPE)
+ if (enum_p && UNSCOPED_ENUM_P (type))
types[i] = tree_cons (NULL_TREE, type, types[i]);
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
type = type_promotes_to (type);
}
types[i] = tree_cons (NULL_TREE, type, types[i]);
@@ -2332,37 +2400,79 @@ add_builtin_candidates (struct z_candidate **candidates, enum tree_code code,
TMPL is the template. EXPLICIT_TARGS are any explicit template
arguments. ARGLIST is the arguments provided at the call-site.
- The RETURN_TYPE is the desired type for conversion operators. If
- OBJ is NULL_TREE, FLAGS and CTYPE are as for add_function_candidate.
- If an OBJ is supplied, FLAGS and CTYPE are ignored, and OBJ is as for
- add_conv_candidate. */
+ This does not change ARGLIST. The RETURN_TYPE is the desired type
+ for conversion operators. If OBJ is NULL_TREE, FLAGS and CTYPE are
+ as for add_function_candidate. If an OBJ is supplied, FLAGS and
+ CTYPE are ignored, and OBJ is as for add_conv_candidate. */
static struct z_candidate*
add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
- tree ctype, tree explicit_targs, tree arglist,
- tree return_type, tree access_path,
- tree conversion_path, int flags, tree obj,
- unification_kind_t strict)
+ tree ctype, tree explicit_targs, tree first_arg,
+ const VEC(tree,gc) *arglist, tree return_type,
+ tree access_path, tree conversion_path,
+ int flags, tree obj, unification_kind_t strict)
{
int ntparms = DECL_NTPARMS (tmpl);
tree targs = make_tree_vec (ntparms);
- tree args_without_in_chrg = arglist;
+ unsigned int nargs;
+ int skip_without_in_chrg;
+ tree first_arg_without_in_chrg;
+ tree *args_without_in_chrg;
+ unsigned int nargs_without_in_chrg;
+ unsigned int ia, ix;
+ tree arg;
struct z_candidate *cand;
int i;
tree fn;
+ nargs = (first_arg == NULL_TREE ? 0 : 1) + VEC_length (tree, arglist);
+
+ skip_without_in_chrg = 0;
+
+ first_arg_without_in_chrg = first_arg;
+
/* We don't do deduction on the in-charge parameter, the VTT
parameter or 'this'. */
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (tmpl))
- args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
+ {
+ if (first_arg_without_in_chrg != NULL_TREE)
+ first_arg_without_in_chrg = NULL_TREE;
+ else
+ ++skip_without_in_chrg;
+ }
if ((DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (tmpl)
|| DECL_BASE_CONSTRUCTOR_P (tmpl))
&& CLASSTYPE_VBASECLASSES (DECL_CONTEXT (tmpl)))
- args_without_in_chrg = TREE_CHAIN (args_without_in_chrg);
+ {
+ if (first_arg_without_in_chrg != NULL_TREE)
+ first_arg_without_in_chrg = NULL_TREE;
+ else
+ ++skip_without_in_chrg;
+ }
+
+ nargs_without_in_chrg = ((first_arg_without_in_chrg != NULL_TREE ? 1 : 0)
+ + (VEC_length (tree, arglist)
+ - skip_without_in_chrg));
+ args_without_in_chrg = XALLOCAVEC (tree, nargs_without_in_chrg);
+ ia = 0;
+ if (first_arg_without_in_chrg != NULL_TREE)
+ {
+ args_without_in_chrg[ia] = first_arg_without_in_chrg;
+ ++ia;
+ }
+ for (ix = skip_without_in_chrg;
+ VEC_iterate (tree, arglist, ix, arg);
+ ++ix)
+ {
+ args_without_in_chrg[ia] = arg;
+ ++ia;
+ }
+ gcc_assert (ia == nargs_without_in_chrg);
i = fn_type_unification (tmpl, explicit_targs, targs,
args_without_in_chrg,
+ nargs_without_in_chrg,
return_type, strict, flags);
if (i != 0)
@@ -2394,7 +2504,7 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
class type, and a logical interpretation is that the intent was
to forbid the instantiation of member templates which would then
have that form. */
- if (DECL_CONSTRUCTOR_P (fn) && list_length (arglist) == 2)
+ if (DECL_CONSTRUCTOR_P (fn) && nargs == 2)
{
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (fn);
if (arg_types && same_type_p (TYPE_MAIN_VARIANT (TREE_VALUE (arg_types)),
@@ -2404,11 +2514,11 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
if (obj != NULL_TREE)
/* Aha, this is a conversion function. */
- cand = add_conv_candidate (candidates, fn, obj, access_path,
- conversion_path, arglist);
+ cand = add_conv_candidate (candidates, fn, obj, first_arg, arglist,
+ access_path, conversion_path);
else
cand = add_function_candidate (candidates, fn, ctype,
- arglist, access_path,
+ first_arg, arglist, access_path,
conversion_path, flags);
if (DECL_TI_TEMPLATE (fn) != tmpl)
/* This situation can occur if a member template of a template
@@ -2438,26 +2548,29 @@ add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
static struct z_candidate *
add_template_candidate (struct z_candidate **candidates, tree tmpl, tree ctype,
- tree explicit_targs, tree arglist, tree return_type,
+ tree explicit_targs, tree first_arg,
+ const VEC(tree,gc) *arglist, tree return_type,
tree access_path, tree conversion_path, int flags,
unification_kind_t strict)
{
return
add_template_candidate_real (candidates, tmpl, ctype,
- explicit_targs, arglist, return_type,
- access_path, conversion_path,
+ explicit_targs, first_arg, arglist,
+ return_type, access_path, conversion_path,
flags, NULL_TREE, strict);
}
static struct z_candidate *
add_template_conv_candidate (struct z_candidate **candidates, tree tmpl,
- tree obj, tree arglist, tree return_type,
- tree access_path, tree conversion_path)
+ tree obj, tree first_arg,
+ const VEC(tree,gc) *arglist,
+ tree return_type, tree access_path,
+ tree conversion_path)
{
return
add_template_candidate_real (candidates, tmpl, NULL_TREE, NULL_TREE,
- arglist, return_type, access_path,
+ first_arg, arglist, return_type, access_path,
conversion_path, 0, obj, DEDUCE_CONV);
}
@@ -2664,7 +2777,8 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
tree ctors = NULL_TREE;
tree conv_fns = NULL_TREE;
conversion *conv = NULL;
- tree args = NULL_TREE;
+ tree first_arg = NULL_TREE;
+ VEC(tree,gc) *args = NULL;
bool any_viable_p;
int convflags;
@@ -2704,15 +2818,13 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
if (ctors)
{
- tree t;
-
ctors = BASELINK_FUNCTIONS (ctors);
- t = build_int_cst (build_pointer_type (totype), 0);
+ first_arg = build_int_cst (build_pointer_type (totype), 0);
if (BRACE_ENCLOSED_INITIALIZER_P (expr)
&& !TYPE_HAS_LIST_CTOR (totype))
{
- args = ctor_to_list (expr);
+ args = ctor_to_vec (expr);
/* We still allow more conversions within an init-list. */
flags = ((flags & ~LOOKUP_NO_CONVERSION)
/* But not for the copy ctor. */
@@ -2720,12 +2832,12 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
|LOOKUP_NO_NARROWING);
}
else
- args = build_tree_list (NULL_TREE, expr);
+ args = make_tree_vector_single (expr);
+
/* We should never try to call the abstract or base constructor
from here. */
gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (OVL_CURRENT (ctors))
&& !DECL_HAS_VTT_PARM_P (OVL_CURRENT (ctors)));
- args = tree_cons (NULL_TREE, t, args);
}
for (; ctors; ctors = OVL_NEXT (ctors))
{
@@ -2736,14 +2848,14 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
if (TREE_CODE (ctor) == TEMPLATE_DECL)
cand = add_template_candidate (&candidates, ctor, totype,
- NULL_TREE, args, NULL_TREE,
+ NULL_TREE, first_arg, args, NULL_TREE,
TYPE_BINFO (totype),
TYPE_BINFO (totype),
flags,
DEDUCE_CALL);
else
cand = add_function_candidate (&candidates, ctor, totype,
- args, TYPE_BINFO (totype),
+ first_arg, args, TYPE_BINFO (totype),
TYPE_BINFO (totype),
flags);
@@ -2767,7 +2879,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
}
if (conv_fns)
- args = build_tree_list (NULL_TREE, build_this (expr));
+ first_arg = build_this (expr);
for (; conv_fns; conv_fns = TREE_CHAIN (conv_fns))
{
@@ -2785,6 +2897,10 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
{
tree fn = OVL_CURRENT (fns);
+ if (DECL_NONCONVERTING_P (fn)
+ && (flags & LOOKUP_ONLYCONVERTING))
+ continue;
+
/* [over.match.funcs] For conversion functions, the function
is considered to be a member of the class of the implicit
object argument for the purpose of defining the type of
@@ -2795,14 +2911,14 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
if (TREE_CODE (fn) == TEMPLATE_DECL)
cand = add_template_candidate (&candidates, fn, fromtype,
NULL_TREE,
- args, totype,
+ first_arg, NULL, totype,
TYPE_BINFO (fromtype),
conversion_path,
flags,
DEDUCE_CONV);
else
cand = add_function_candidate (&candidates, fn, fromtype,
- args,
+ first_arg, NULL,
TYPE_BINFO (fromtype),
conversion_path,
flags);
@@ -2905,23 +3021,23 @@ build_user_type_conversion (tree totype, tree expr, int flags)
/* Do any initial processing on the arguments to a function call. */
-static tree
-resolve_args (tree args)
+static VEC(tree,gc) *
+resolve_args (VEC(tree,gc) *args)
{
- tree t;
- for (t = args; t; t = TREE_CHAIN (t))
- {
- tree arg = TREE_VALUE (t);
+ unsigned int ix;
+ tree arg;
+ for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+ {
if (error_operand_p (arg))
- return error_mark_node;
+ return NULL;
else if (VOID_TYPE_P (TREE_TYPE (arg)))
{
error ("invalid use of void expression");
- return error_mark_node;
+ return NULL;
}
else if (invalid_nonstatic_memfn_p (arg, tf_warning_or_error))
- return error_mark_node;
+ return NULL;
}
return args;
}
@@ -2940,7 +3056,7 @@ resolve_args (tree args)
static struct z_candidate *
perform_overload_resolution (tree fn,
- tree args,
+ const VEC(tree,gc) *args,
struct z_candidate **candidates,
bool *any_viable_p)
{
@@ -2951,12 +3067,11 @@ perform_overload_resolution (tree fn,
*candidates = NULL;
*any_viable_p = true;
- /* Check FN and ARGS. */
+ /* Check FN. */
gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
|| TREE_CODE (fn) == TEMPLATE_DECL
|| TREE_CODE (fn) == OVERLOAD
|| TREE_CODE (fn) == TEMPLATE_ID_EXPR);
- gcc_assert (!args || TREE_CODE (args) == TREE_LIST);
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
{
@@ -2981,10 +3096,11 @@ perform_overload_resolution (tree fn,
}
/* Return an expression for a call to FN (a namespace-scope function,
- or a static member function) with the ARGS. */
+ or a static member function) with the ARGS. This may change
+ ARGS. */
tree
-build_new_function_call (tree fn, tree args, bool koenig_p,
+build_new_function_call (tree fn, VEC(tree,gc) **args, bool koenig_p,
tsubst_flags_t complain)
{
struct z_candidate *candidates, *cand;
@@ -2992,9 +3108,12 @@ build_new_function_call (tree fn, tree args, bool koenig_p,
void *p;
tree result;
- args = resolve_args (args);
- if (args == error_mark_node)
- return error_mark_node;
+ if (args != NULL && *args != NULL)
+ {
+ *args = resolve_args (*args);
+ if (*args == NULL)
+ return error_mark_node;
+ }
/* If this function was found without using argument dependent
lookup, then we want to ignore any undeclared friend
@@ -3008,7 +3127,8 @@ build_new_function_call (tree fn, tree args, bool koenig_p,
{
if (complain & tf_error)
error ("no matching function for call to %<%D(%A)%>",
- DECL_NAME (OVL_CURRENT (orig_fn)), args);
+ DECL_NAME (OVL_CURRENT (orig_fn)),
+ build_tree_list_vec (*args));
return error_mark_node;
}
}
@@ -3016,22 +3136,22 @@ build_new_function_call (tree fn, tree args, bool koenig_p,
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
- cand = perform_overload_resolution (fn, args, &candidates, &any_viable_p);
+ cand = perform_overload_resolution (fn, *args, &candidates, &any_viable_p);
if (!cand)
{
if (complain & tf_error)
{
if (!any_viable_p && candidates && ! candidates->next)
- return cp_build_function_call (candidates->fn, args, complain);
+ return cp_build_function_call_vec (candidates->fn, args, complain);
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
fn = TREE_OPERAND (fn, 0);
if (!any_viable_p)
error ("no matching function for call to %<%D(%A)%>",
- DECL_NAME (OVL_CURRENT (fn)), args);
+ DECL_NAME (OVL_CURRENT (fn)), build_tree_list_vec (*args));
else
error ("call of overloaded %<%D(%A)%> is ambiguous",
- DECL_NAME (OVL_CURRENT (fn)), args);
+ DECL_NAME (OVL_CURRENT (fn)), build_tree_list_vec (*args));
if (candidates)
print_z_candidates (candidates);
}
@@ -3048,15 +3168,16 @@ build_new_function_call (tree fn, tree args, bool koenig_p,
/* Build a call to a global operator new. FNNAME is the name of the
operator (either "operator new" or "operator new[]") and ARGS are
- the arguments provided. *SIZE points to the total number of bytes
- required by the allocation, and is updated if that is changed here.
- *COOKIE_SIZE is non-NULL if a cookie should be used. If this
- function determines that no cookie should be used, after all,
- *COOKIE_SIZE is set to NULL_TREE. If FN is non-NULL, it will be
- set, upon return, to the allocation function called. */
+ the arguments provided. This may change ARGS. *SIZE points to the
+ total number of bytes required by the allocation, and is updated if
+ that is changed here. *COOKIE_SIZE is non-NULL if a cookie should
+ be used. If this function determines that no cookie should be
+ used, after all, *COOKIE_SIZE is set to NULL_TREE. If FN is
+ non-NULL, it will be set, upon return, to the allocation function
+ called. */
tree
-build_operator_new_call (tree fnname, tree args,
+build_operator_new_call (tree fnname, VEC(tree,gc) **args,
tree *size, tree *cookie_size,
tree *fn)
{
@@ -3067,10 +3188,10 @@ build_operator_new_call (tree fnname, tree args,
if (fn)
*fn = NULL_TREE;
- args = tree_cons (NULL_TREE, *size, args);
- args = resolve_args (args);
- if (args == error_mark_node)
- return args;
+ VEC_safe_insert (tree, gc, *args, 0, *size);
+ *args = resolve_args (*args);
+ if (*args == NULL)
+ return error_mark_node;
/* Based on:
@@ -3081,10 +3202,10 @@ build_operator_new_call (tree fnname, tree args,
up in the global scope.
we disregard block-scope declarations of "operator new". */
- fns = lookup_function_nonclass (fnname, args, /*block_p=*/false);
+ fns = lookup_function_nonclass (fnname, *args, /*block_p=*/false);
/* Figure out what function is being called. */
- cand = perform_overload_resolution (fns, args, &candidates, &any_viable_p);
+ cand = perform_overload_resolution (fns, *args, &candidates, &any_viable_p);
/* If no suitable function could be found, issue an error message
and give up. */
@@ -3092,10 +3213,10 @@ build_operator_new_call (tree fnname, tree args,
{
if (!any_viable_p)
error ("no matching function for call to %<%D(%A)%>",
- DECL_NAME (OVL_CURRENT (fns)), args);
+ DECL_NAME (OVL_CURRENT (fns)), build_tree_list_vec (*args));
else
error ("call of overloaded %<%D(%A)%> is ambiguous",
- DECL_NAME (OVL_CURRENT (fns)), args);
+ DECL_NAME (OVL_CURRENT (fns)), build_tree_list_vec (*args));
if (candidates)
print_z_candidates (candidates);
return error_mark_node;
@@ -3109,12 +3230,11 @@ build_operator_new_call (tree fnname, tree args,
bool use_cookie = true;
if (!abi_version_at_least (2))
{
- tree placement = TREE_CHAIN (args);
/* In G++ 3.2, the check was implemented incorrectly; it
looked at the placement expression, rather than the
type of the function. */
- if (placement && !TREE_CHAIN (placement)
- && same_type_p (TREE_TYPE (TREE_VALUE (placement)),
+ if (VEC_length (tree, *args) == 2
+ && same_type_p (TREE_TYPE (VEC_index (tree, *args, 1)),
ptr_type_node))
use_cookie = false;
}
@@ -3138,7 +3258,7 @@ build_operator_new_call (tree fnname, tree args,
/* Update the total size. */
*size = size_binop (PLUS_EXPR, *size, *cookie_size);
/* Update the argument list to reflect the adjusted size. */
- TREE_VALUE (args) = *size;
+ VEC_replace (tree, *args, 0, *size);
}
else
*cookie_size = NULL_TREE;
@@ -3152,16 +3272,23 @@ build_operator_new_call (tree fnname, tree args,
return build_over_call (cand, LOOKUP_NORMAL, tf_warning_or_error);
}
-static tree
-build_object_call (tree obj, tree args, tsubst_flags_t complain)
+/* Build a new call to operator(). This may change ARGS. */
+
+tree
+build_op_call (tree obj, VEC(tree,gc) **args, tsubst_flags_t complain)
{
struct z_candidate *candidates = 0, *cand;
- tree fns, convs, mem_args = NULL_TREE;
+ tree fns, convs, first_mem_arg = NULL_TREE;
tree type = TREE_TYPE (obj);
bool any_viable_p;
tree result = NULL_TREE;
void *p;
+ if (error_operand_p (obj))
+ return error_mark_node;
+
+ obj = prep_operand (obj);
+
if (TYPE_PTRMEMFUNC_P (type))
{
if (complain & tf_error)
@@ -3180,10 +3307,12 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain)
else
fns = NULL_TREE;
- args = resolve_args (args);
-
- if (args == error_mark_node)
- return error_mark_node;
+ if (args != NULL && *args != NULL)
+ {
+ *args = resolve_args (*args);
+ if (*args == NULL)
+ return error_mark_node;
+ }
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
@@ -3191,20 +3320,20 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain)
if (fns)
{
tree base = BINFO_TYPE (BASELINK_BINFO (fns));
- mem_args = tree_cons (NULL_TREE, build_this (obj), args);
+ first_mem_arg = build_this (obj);
for (fns = BASELINK_FUNCTIONS (fns); fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (TREE_CODE (fn) == TEMPLATE_DECL)
add_template_candidate (&candidates, fn, base, NULL_TREE,
- mem_args, NULL_TREE,
+ first_mem_arg, *args, NULL_TREE,
TYPE_BINFO (type),
TYPE_BINFO (type),
LOOKUP_NORMAL, DEDUCE_CALL);
else
add_function_candidate
- (&candidates, fn, base, mem_args, TYPE_BINFO (type),
+ (&candidates, fn, base, first_mem_arg, *args, TYPE_BINFO (type),
TYPE_BINFO (type), LOOKUP_NORMAL);
}
}
@@ -3214,7 +3343,7 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain)
for (; convs; convs = TREE_CHAIN (convs))
{
tree fns = TREE_VALUE (convs);
- tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
+ tree totype = TREE_TYPE (convs);
if ((TREE_CODE (totype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
@@ -3226,14 +3355,18 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain)
for (; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
+
+ if (DECL_NONCONVERTING_P (fn))
+ continue;
+
if (TREE_CODE (fn) == TEMPLATE_DECL)
add_template_conv_candidate
- (&candidates, fn, obj, args, totype,
+ (&candidates, fn, obj, NULL_TREE, *args, totype,
/*access_path=*/NULL_TREE,
/*conversion_path=*/NULL_TREE);
else
- add_conv_candidate (&candidates, fn, obj, args,
- /*conversion_path=*/NULL_TREE,
+ add_conv_candidate (&candidates, fn, obj, NULL_TREE,
+ *args, /*conversion_path=*/NULL_TREE,
/*access_path=*/NULL_TREE);
}
}
@@ -3243,7 +3376,8 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain)
{
if (complain & tf_error)
{
- error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj), args);
+ error ("no match for call to %<(%T) (%A)%>", TREE_TYPE (obj),
+ build_tree_list_vec (*args));
print_z_candidates (candidates);
}
result = error_mark_node;
@@ -3256,7 +3390,7 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain)
if (complain & tf_error)
{
error ("call of %<(%T) (%A)%> is ambiguous",
- TREE_TYPE (obj), args);
+ TREE_TYPE (obj), build_tree_list_vec (*args));
print_z_candidates (candidates);
}
result = error_mark_node;
@@ -3272,7 +3406,7 @@ build_object_call (tree obj, tree args, tsubst_flags_t complain)
obj = convert_like_with_context (cand->convs[0], obj, cand->fn, -1,
complain);
obj = convert_from_reference (obj);
- result = cp_build_function_call (obj, args, complain);
+ result = cp_build_function_call_vec (obj, args, complain);
}
}
@@ -3348,7 +3482,7 @@ conditional_conversion (tree e1, tree e2)
t1,
e1,
/*c_cast_p=*/false,
- LOOKUP_NO_TEMP_BIND);
+ LOOKUP_NO_TEMP_BIND|LOOKUP_ONLYCONVERTING);
if (conv)
return conv;
}
@@ -3386,7 +3520,7 @@ conditional_conversion (tree e1, tree e2)
converted to the type that expression E2 would have if E2 were
converted to an rvalue (or the type it has, if E2 is an rvalue). */
return implicit_conversion (t2, t1, e1, /*c_cast_p=*/false,
- LOOKUP_NORMAL);
+ LOOKUP_IMPLICIT);
}
/* Implement [expr.cond]. ARG1, ARG2, and ARG3 are the three
@@ -3824,29 +3958,33 @@ prep_operand (tree operand)
/* Add each of the viable functions in FNS (a FUNCTION_DECL or
OVERLOAD) to the CANDIDATES, returning an updated list of
CANDIDATES. The ARGS are the arguments provided to the call,
- without any implicit object parameter. The EXPLICIT_TARGS are
- explicit template arguments provided. TEMPLATE_ONLY is true if
- only template functions should be considered. CONVERSION_PATH,
- ACCESS_PATH, and FLAGS are as for add_function_candidate. */
+ without any implicit object parameter. This may change ARGS. The
+ EXPLICIT_TARGS are explicit template arguments provided.
+ TEMPLATE_ONLY is true if only template functions should be
+ considered. CONVERSION_PATH, ACCESS_PATH, and FLAGS are as for
+ add_function_candidate. */
static void
-add_candidates (tree fns, tree args,
+add_candidates (tree fns, const VEC(tree,gc) *args,
tree explicit_targs, bool template_only,
tree conversion_path, tree access_path,
int flags,
struct z_candidate **candidates)
{
tree ctype;
- tree non_static_args;
+ VEC(tree,gc) *non_static_args;
+ tree first_arg;
ctype = conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE;
/* Delay creating the implicit this parameter until it is needed. */
- non_static_args = NULL_TREE;
+ non_static_args = NULL;
+ first_arg = NULL_TREE;
while (fns)
{
tree fn;
- tree fn_args;
+ tree fn_first_arg;
+ const VEC(tree,gc) *fn_args;
fn = OVL_CURRENT (fns);
/* Figure out which set of arguments to use. */
@@ -3854,21 +3992,34 @@ add_candidates (tree fns, tree args,
{
/* If this function is a non-static member, prepend the implicit
object parameter. */
- if (!non_static_args)
- non_static_args = tree_cons (NULL_TREE,
- build_this (TREE_VALUE (args)),
- TREE_CHAIN (args));
+ if (non_static_args == NULL)
+ {
+ unsigned int ix;
+ tree arg;
+
+ non_static_args = VEC_alloc (tree, gc,
+ VEC_length (tree, args) - 1);
+ for (ix = 1; VEC_iterate (tree, args, ix, arg); ++ix)
+ VEC_quick_push (tree, non_static_args, arg);
+ }
+ if (first_arg == NULL_TREE)
+ first_arg = build_this (VEC_index (tree, args, 0));
+ fn_first_arg = first_arg;
fn_args = non_static_args;
}
else
- /* Otherwise, just use the list of arguments provided. */
- fn_args = args;
+ {
+ /* Otherwise, just use the list of arguments provided. */
+ fn_first_arg = NULL_TREE;
+ fn_args = args;
+ }
if (TREE_CODE (fn) == TEMPLATE_DECL)
add_template_candidate (candidates,
fn,
ctype,
explicit_targs,
+ fn_first_arg,
fn_args,
NULL_TREE,
access_path,
@@ -3879,6 +4030,7 @@ add_candidates (tree fns, tree args,
add_function_candidate (candidates,
fn,
ctype,
+ fn_first_arg,
fn_args,
access_path,
conversion_path,
@@ -3892,7 +4044,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
bool *overloaded_p, tsubst_flags_t complain)
{
struct z_candidate *candidates = 0, *cand;
- tree arglist, fnname;
+ VEC(tree,gc) *arglist;
+ tree fnname;
tree args[3];
tree result = NULL_TREE;
bool result_valid_p = false;
@@ -3930,7 +4083,8 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
gcc_unreachable ();
case CALL_EXPR:
- return build_object_call (arg1, arg2, complain);
+ /* Use build_op_call instead. */
+ gcc_unreachable ();
case TRUTH_ORIF_EXPR:
case TRUTH_ANDIF_EXPR:
@@ -3963,12 +4117,12 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
if (code == POSTINCREMENT_EXPR || code == POSTDECREMENT_EXPR)
arg2 = integer_zero_node;
- arglist = NULL_TREE;
- if (arg3)
- arglist = tree_cons (NULL_TREE, arg3, arglist);
- if (arg2)
- arglist = tree_cons (NULL_TREE, arg2, arglist);
- arglist = tree_cons (NULL_TREE, arg1, arglist);
+ arglist = VEC_alloc (tree, gc, 3);
+ VEC_quick_push (tree, arglist, arg1);
+ if (arg2 != NULL_TREE)
+ VEC_quick_push (tree, arglist, arg2);
+ if (arg3 != NULL_TREE)
+ VEC_quick_push (tree, arglist, arg3);
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
@@ -4108,7 +4262,7 @@ build_new_op (enum tree_code code, int flags, tree arg1, tree arg2, tree arg3,
if (overloaded_p)
*overloaded_p = true;
- if (resolve_args (arglist) == error_mark_node)
+ if (resolve_args (arglist) == NULL)
result = error_mark_node;
else
result = build_over_call (cand, LOOKUP_NORMAL, complain);
@@ -4409,13 +4563,14 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
}
else
{
- tree args;
- if (pass == 0)
- args = tree_cons (NULL_TREE, addr, NULL_TREE);
- else
- args = tree_cons (NULL_TREE, addr,
- build_tree_list (NULL_TREE, size));
- return cp_build_function_call (fn, args, tf_warning_or_error);
+ tree ret;
+ VEC(tree,gc) *args = VEC_alloc (tree, gc, 2);
+ VEC_quick_push (tree, args, addr);
+ if (pass != 0)
+ VEC_quick_push (tree, args, size);
+ ret = cp_build_function_call_vec (fn, &args, tf_warning_or_error);
+ VEC_free (tree, gc, args);
+ return ret;
}
}
@@ -4473,12 +4628,13 @@ build_temp (tree expr, tree type, int flags,
diagnostic_t *diagnostic_kind)
{
int savew, savee;
+ VEC(tree,gc) *args;
savew = warningcount, savee = errorcount;
- expr = build_special_member_call (NULL_TREE,
- complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr),
- type, flags, tf_warning_or_error);
+ args = make_tree_vector_single (expr);
+ expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ &args, type, flags, tf_warning_or_error);
+ release_tree_vector (args);
if (warningcount > savew)
*diagnostic_kind = DK_WARNING;
else if (errorcount > savee)
@@ -4535,6 +4691,7 @@ 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
@@ -4584,7 +4741,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
/* When converting from an init list we consider explicit
constructors, but actually trying to call one is an error. */
- if (DECL_NONCONVERTING_P (convfn))
+ if (DECL_NONCONVERTING_P (convfn) && DECL_CONSTRUCTOR_P (convfn))
{
if (complain & tf_error)
error ("converting to %qT from initializer list would use "
@@ -4614,6 +4771,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
@@ -4622,7 +4790,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
if (inner >= 0)
{
expr = decl_constant_value (expr);
- if (expr == null_node && INTEGRAL_TYPE_P (totype))
+ if (expr == null_node && INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (totype))
/* If __null has been converted to an integer type, we do not
want to warn about uses of EXPR as an integer, rather than
as a pointer. */
@@ -4640,7 +4808,8 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (totype), 0);
tree new_ctor = build_constructor (init_list_type_node, NULL);
unsigned len = CONSTRUCTOR_NELTS (expr);
- tree array, parms, val;
+ tree array, val;
+ VEC(tree,gc) *parms;
unsigned ix;
/* Convert all the elements. */
@@ -4659,12 +4828,14 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
array = build_array_of_n_type (elttype, len);
array = finish_compound_literal (array, new_ctor);
- parms = build_tree_list (NULL_TREE, size_int (len));
- parms = tree_cons (NULL_TREE, decay_conversion (array), parms);
+ parms = make_tree_vector ();
+ VEC_safe_push (tree, gc, parms, decay_conversion (array));
+ VEC_safe_push (tree, gc, parms, size_int (len));
/* Call the private constructor. */
push_deferring_access_checks (dk_no_check);
new_ctor = build_special_member_call
- (NULL_TREE, complete_ctor_identifier, parms, totype, 0, complain);
+ (NULL_TREE, complete_ctor_identifier, &parms, totype, 0, complain);
+ release_tree_vector (parms);
pop_deferring_access_checks ();
return build_cplus_new (totype, new_ctor);
}
@@ -5121,14 +5292,16 @@ static tree
build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
{
tree fn = cand->fn;
- tree args = cand->args;
+ const VEC(tree,gc) *args = cand->args;
+ tree first_arg = cand->first_arg;
conversion **convs = cand->convs;
conversion *conv;
tree parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
int parmlen;
- tree arg, val;
+ tree val;
int i = 0;
int j = 0;
+ unsigned int arg_index = 0;
int is_method = 0;
int nargs;
tree *argarray;
@@ -5142,8 +5315,28 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
{
tree expr;
tree return_type;
+ const tree *argarray;
+ unsigned int nargs;
+
return_type = TREE_TYPE (TREE_TYPE (fn));
- expr = build_call_list (return_type, build_addr_func (fn), args);
+ nargs = VEC_length (tree, args);
+ if (first_arg == NULL_TREE)
+ argarray = VEC_address (tree, CONST_CAST (VEC(tree,gc) *, args));
+ else
+ {
+ tree *alcarray;
+ unsigned int ix;
+ tree arg;
+
+ ++nargs;
+ alcarray = XALLOCAVEC (tree, nargs);
+ alcarray[0] = first_arg;
+ for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+ alcarray[ix + 1] = arg;
+ argarray = alcarray;
+ }
+ expr = build_call_array (return_type, build_addr_func (fn), nargs,
+ argarray);
if (TREE_THIS_VOLATILE (fn) && cfun)
current_function_returns_abnormally = 1;
if (!VOID_TYPE_P (return_type))
@@ -5198,13 +5391,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
perform_or_defer_access_check (cand->access_path, fn, fn);
}
- if (args && TREE_CODE (args) != TREE_LIST)
- args = build_tree_list (NULL_TREE, args);
- arg = args;
-
/* Find maximum size of vector to hold converted arguments. */
parmlen = list_length (parm);
- nargs = list_length (args);
+ nargs = VEC_length (tree, args) + (first_arg != NULL_TREE ? 1 : 0);
if (parmlen > nargs)
nargs = parmlen;
argarray = (tree *) alloca (nargs * sizeof (tree));
@@ -5213,16 +5402,24 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
resolution, and must be of the proper type. */
if (DECL_CONSTRUCTOR_P (fn))
{
- argarray[j++] = TREE_VALUE (arg);
- arg = TREE_CHAIN (arg);
+ if (first_arg != NULL_TREE)
+ {
+ argarray[j++] = first_arg;
+ first_arg = NULL_TREE;
+ }
+ else
+ {
+ argarray[j++] = VEC_index (tree, args, arg_index);
+ ++arg_index;
+ }
parm = TREE_CHAIN (parm);
/* We should never try to call the abstract constructor. */
gcc_assert (!DECL_HAS_IN_CHARGE_PARM_P (fn));
if (DECL_HAS_VTT_PARM_P (fn))
{
- argarray[j++] = TREE_VALUE (arg);
- arg = TREE_CHAIN (arg);
+ argarray[j++] = VEC_index (tree, args, arg_index);
+ ++arg_index;
parm = TREE_CHAIN (parm);
}
}
@@ -5230,7 +5427,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
else if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
{
tree parmtype = TREE_VALUE (parm);
- tree argtype = TREE_TYPE (TREE_VALUE (arg));
+ tree arg = (first_arg != NULL_TREE
+ ? first_arg
+ : VEC_index (tree, args, arg_index));
+ tree argtype = TREE_TYPE (arg);
tree converted_arg;
tree base_binfo;
@@ -5253,7 +5453,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
/* Convert to the base in which the function was declared. */
gcc_assert (cand->conversion_path != NULL_TREE);
converted_arg = build_base_path (PLUS_EXPR,
- TREE_VALUE (arg),
+ arg,
cand->conversion_path,
1);
/* Check that the base class is accessible. */
@@ -5272,13 +5472,17 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
argarray[j++] = converted_arg;
parm = TREE_CHAIN (parm);
- arg = TREE_CHAIN (arg);
+ if (first_arg != NULL_TREE)
+ first_arg = NULL_TREE;
+ else
+ ++arg_index;
++i;
is_method = 1;
}
- for (; arg && parm;
- parm = TREE_CHAIN (parm), arg = TREE_CHAIN (arg), ++i)
+ gcc_assert (first_arg == NULL_TREE);
+ for (; arg_index < VEC_length (tree, args) && parm;
+ parm = TREE_CHAIN (parm), ++arg_index, ++i)
{
tree type = TREE_VALUE (parm);
@@ -5291,7 +5495,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
conv = conv->u.next;
val = convert_like_with_context
- (conv, TREE_VALUE (arg), fn, i - is_method, complain);
+ (conv, VEC_index (tree, args, arg_index), fn, i - is_method,
+ complain);
val = convert_for_arg_passing (type, val);
if (val == error_mark_node)
@@ -5306,9 +5511,9 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
TREE_PURPOSE (parm),
fn, i - is_method);
/* Ellipsis */
- for (; arg; arg = TREE_CHAIN (arg))
+ for (; arg_index < VEC_length (tree, args); ++arg_index)
{
- tree a = TREE_VALUE (arg);
+ tree a = VEC_index (tree, args, arg_index);
if (magic_varargs_p (fn))
/* Do no conversions for magic varargs. */;
else
@@ -5332,7 +5537,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|| DECL_MOVE_CONSTRUCTOR_P (fn)))
{
tree targ;
- arg = argarray[num_artificial_parms_for (fn)];
+ tree arg = argarray[num_artificial_parms_for (fn)];
+ tree fa;
/* Pull out the real argument, disregarding const-correctness. */
targ = arg;
@@ -5373,7 +5579,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
INIT_EXPR to collapse the temp into our target. Otherwise, if the
ctor is trivial, do a bitwise copy with a simple TARGET_EXPR for a
temp or an INIT_EXPR otherwise. */
- if (integer_zerop (TREE_VALUE (args)))
+ fa = (cand->first_arg != NULL_TREE
+ ? cand->first_arg
+ : VEC_index (tree, args, 0));
+ if (integer_zerop (fa))
{
if (TREE_CODE (arg) == TARGET_EXPR)
return arg;
@@ -5384,8 +5593,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
|| (TYPE_HAS_TRIVIAL_INIT_REF (DECL_CONTEXT (fn))
&& !move_fn_p (fn)))
{
- tree to = stabilize_reference
- (cp_build_indirect_ref (TREE_VALUE (args), 0, complain));
+ tree to = stabilize_reference (cp_build_indirect_ref (fa, 0,
+ complain));
val = build2 (INIT_EXPR, DECL_CONTEXT (fn), to, arg);
return val;
@@ -5399,8 +5608,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
(cp_build_indirect_ref (argarray[0], 0, complain));
tree type = TREE_TYPE (to);
tree as_base = CLASSTYPE_AS_BASE (type);
+ tree arg = argarray[1];
- arg = argarray[1];
if (tree_int_cst_equal (TYPE_SIZE (type), TYPE_SIZE (as_base)))
{
arg = cp_build_indirect_ref (arg, 0, complain);
@@ -5606,9 +5815,10 @@ in_charge_arg_for_name (tree name)
/* Build a call to a constructor, destructor, or an assignment
operator for INSTANCE, an expression with class type. NAME
- indicates the special member function to call; ARGS are the
- arguments. BINFO indicates the base of INSTANCE that is to be
- passed as the `this' parameter to the member function called.
+ indicates the special member function to call; *ARGS are the
+ arguments. ARGS may be NULL. This may change ARGS. BINFO
+ indicates the base of INSTANCE that is to be passed as the `this'
+ parameter to the member function called.
FLAGS are the LOOKUP_* flags to use when processing the call.
@@ -5617,12 +5827,14 @@ in_charge_arg_for_name (tree name)
store the newly constructed object into a VAR_DECL. */
tree
-build_special_member_call (tree instance, tree name, tree args,
+build_special_member_call (tree instance, tree name, VEC(tree,gc) **args,
tree binfo, int flags, tsubst_flags_t complain)
{
tree fns;
/* The type of the subobject to be constructed or destroyed. */
tree class_type;
+ VEC(tree,gc) *allocated = NULL;
+ tree ret;
gcc_assert (name == complete_ctor_identifier
|| name == base_ctor_identifier
@@ -5654,7 +5866,7 @@ build_special_member_call (tree instance, tree name, tree args,
if (name == complete_dtor_identifier
|| name == base_dtor_identifier
|| name == deleting_dtor_identifier)
- gcc_assert (args == NULL_TREE);
+ gcc_assert (args == NULL || VEC_empty (tree, *args));
/* Convert to the base class, if necessary. */
if (!same_type_ignoring_top_level_qualifiers_p
@@ -5703,13 +5915,24 @@ build_special_member_call (tree instance, tree name, tree args,
sub_vtt = build2 (POINTER_PLUS_EXPR, TREE_TYPE (vtt), vtt,
BINFO_SUBVTT_INDEX (binfo));
- args = tree_cons (NULL_TREE, sub_vtt, args);
+ if (args == NULL)
+ {
+ allocated = make_tree_vector ();
+ args = &allocated;
+ }
+
+ VEC_safe_insert (tree, gc, *args, 0, sub_vtt);
}
- return build_new_method_call (instance, fns, args,
- TYPE_BINFO (BINFO_TYPE (binfo)),
- flags, /*fn=*/NULL,
- complain);
+ ret = build_new_method_call (instance, fns, args,
+ TYPE_BINFO (BINFO_TYPE (binfo)),
+ flags, /*fn=*/NULL,
+ complain);
+
+ if (allocated != NULL)
+ release_tree_vector (allocated);
+
+ return ret;
}
/* Return the NAME, as a C string. The NAME indicates a function that
@@ -5758,10 +5981,11 @@ name_as_c_string (tree name, tree type, bool *free_p)
}
/* Build a call to "INSTANCE.FN (ARGS)". If FN_P is non-NULL, it will
- be set, upon return, to the function called. */
+ be set, upon return, to the function called. ARGS may be NULL.
+ This may change ARGS. */
tree
-build_new_method_call (tree instance, tree fns, tree args,
+build_new_method_call (tree instance, tree fns, VEC(tree,gc) **args,
tree conversion_path, int flags,
tree *fn_p, tsubst_flags_t complain)
{
@@ -5770,9 +5994,11 @@ build_new_method_call (tree instance, tree fns, tree args,
tree basetype = NULL_TREE;
tree access_binfo;
tree optype;
- tree mem_args = NULL_TREE, instance_ptr;
+ tree first_mem_arg = NULL_TREE;
+ tree instance_ptr;
tree name;
- tree user_args;
+ bool skip_first_for_error;
+ VEC(tree,gc) *user_args;
tree call;
tree fn;
tree class_type;
@@ -5780,7 +6006,7 @@ build_new_method_call (tree instance, tree fns, tree args,
bool any_viable_p;
tree orig_instance;
tree orig_fns;
- tree orig_args;
+ VEC(tree,gc) *orig_args = NULL;
void *p;
gcc_assert (instance != NULL_TREE);
@@ -5790,8 +6016,7 @@ build_new_method_call (tree instance, tree fns, tree args,
*fn_p = NULL_TREE;
if (error_operand_p (instance)
- || error_operand_p (fns)
- || args == error_mark_node)
+ || error_operand_p (fns))
return error_mark_node;
if (!BASELINK_P (fns))
@@ -5803,7 +6028,6 @@ build_new_method_call (tree instance, tree fns, tree args,
orig_instance = instance;
orig_fns = fns;
- orig_args = args;
/* Dismantle the baselink to collect all the information we need. */
if (!conversion_path)
@@ -5828,16 +6052,20 @@ build_new_method_call (tree instance, tree fns, tree args,
if (processing_template_decl)
{
+ orig_args = args == NULL ? NULL : make_tree_vector_copy (*args);
instance = build_non_dependent_expr (instance);
- args = build_non_dependent_args (orig_args);
- }
-
- /* The USER_ARGS are the arguments we will display to users if an
- error occurs. The USER_ARGS should not include any
- compiler-generated arguments. The "this" pointer hasn't been
- added yet. However, we must remove the VTT pointer if this is a
- call to a base-class constructor or destructor. */
- user_args = args;
+ if (args != NULL)
+ make_args_non_dependent (*args);
+ }
+
+ /* Figure out whether to skip the first argument for the error
+ message we will display to users if an error occurs. We don't
+ want to display any compiler-generated arguments. The "this"
+ pointer hasn't been added yet. However, we must remove the VTT
+ pointer if this is a call to a base-class constructor or
+ destructor. */
+ skip_first_for_error = false;
+ user_args = args == NULL ? NULL : *args;
if (IDENTIFIER_CTOR_OR_DTOR_P (name))
{
/* Callers should explicitly indicate whether they want to construct
@@ -5848,13 +6076,16 @@ build_new_method_call (tree instance, tree fns, tree args,
/* Remove the VTT pointer, if present. */
if ((name == base_ctor_identifier || name == base_dtor_identifier)
&& CLASSTYPE_VBASECLASSES (basetype))
- user_args = TREE_CHAIN (user_args);
+ skip_first_for_error = true;
}
/* Process the argument list. */
- args = resolve_args (args);
- if (args == error_mark_node)
- return error_mark_node;
+ if (args != NULL && *args != NULL)
+ {
+ *args = resolve_args (*args);
+ if (*args == NULL)
+ return error_mark_node;
+ }
instance_ptr = build_this (instance);
@@ -5874,17 +6105,17 @@ build_new_method_call (tree instance, tree fns, tree args,
/* If CONSTRUCTOR_IS_DIRECT_INIT is set, this was a T{ } form
initializer, not T({ }). If the type doesn't have a list ctor,
break apart the list into separate ctor args. */
- if (DECL_CONSTRUCTOR_P (fn) && args
- && BRACE_ENCLOSED_INITIALIZER_P (TREE_VALUE (args))
- && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (args))
+ if (DECL_CONSTRUCTOR_P (fn) && args != NULL && !VEC_empty (tree, *args)
+ && BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *args, 0))
+ && CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0))
&& !TYPE_HAS_LIST_CTOR (basetype))
{
- gcc_assert (TREE_CHAIN (args) == NULL_TREE);
- args = ctor_to_list (TREE_VALUE (args));
+ gcc_assert (VEC_length (tree, *args) == 1);
+ *args = ctor_to_vec (VEC_index (tree, *args, 0));
}
class_type = (conversion_path ? BINFO_TYPE (conversion_path) : NULL_TREE);
- mem_args = tree_cons (NULL_TREE, instance_ptr, args);
+ first_mem_arg = instance_ptr;
/* Get the high-water mark for the CONVERSION_OBSTACK. */
p = conversion_obstack_alloc (0);
@@ -5892,7 +6123,7 @@ build_new_method_call (tree instance, tree fns, tree args,
for (fn = fns; fn; fn = OVL_NEXT (fn))
{
tree t = OVL_CURRENT (fn);
- tree this_arglist;
+ tree this_first_arg;
/* We can end up here for copy-init of same or base class. */
if ((flags & LOOKUP_ONLYCONVERTING)
@@ -5900,16 +6131,18 @@ build_new_method_call (tree instance, tree fns, tree args,
continue;
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (t))
- this_arglist = mem_args;
+ this_first_arg = first_mem_arg;
else
- this_arglist = args;
+ this_first_arg = NULL_TREE;
if (TREE_CODE (t) == TEMPLATE_DECL)
/* A member template. */
add_template_candidate (&candidates, t,
class_type,
explicit_targs,
- this_arglist, optype,
+ this_first_arg,
+ args == NULL ? NULL : *args,
+ optype,
access_binfo,
conversion_path,
flags,
@@ -5917,7 +6150,8 @@ build_new_method_call (tree instance, tree fns, tree args,
else if (! template_only)
add_function_candidate (&candidates, t,
class_type,
- this_arglist,
+ this_first_arg,
+ args == NULL ? NULL : *args,
access_binfo,
conversion_path,
flags);
@@ -5934,10 +6168,14 @@ build_new_method_call (tree instance, tree fns, tree args,
{
char *pretty_name;
bool free_p;
+ tree arglist;
pretty_name = name_as_c_string (name, basetype, &free_p);
+ arglist = build_tree_list_vec (user_args);
+ if (skip_first_for_error)
+ arglist = TREE_CHAIN (arglist);
error ("no matching function for call to %<%T::%s(%A)%#V%>",
- basetype, pretty_name, user_args,
+ basetype, pretty_name, arglist,
TREE_TYPE (TREE_TYPE (instance_ptr)));
if (free_p)
free (pretty_name);
@@ -5953,12 +6191,16 @@ build_new_method_call (tree instance, tree fns, tree args,
{
char *pretty_name;
bool free_p;
+ tree arglist;
if (complain & tf_error)
{
pretty_name = name_as_c_string (name, basetype, &free_p);
+ arglist = build_tree_list_vec (user_args);
+ if (skip_first_for_error)
+ arglist = TREE_CHAIN (arglist);
error ("call of overloaded %<%s(%A)%> is ambiguous", pretty_name,
- user_args);
+ arglist);
print_z_candidates (candidates);
if (free_p)
free (pretty_name);
@@ -6039,7 +6281,7 @@ build_new_method_call (tree instance, tree fns, tree args,
}
if (TREE_CODE (call) == INDIRECT_REF)
call = TREE_OPERAND (call, 0);
- call = (build_min_non_dep_call_list
+ call = (build_min_non_dep_call_vec
(call,
build_min (COMPONENT_REF, TREE_TYPE (CALL_EXPR_FN (call)),
orig_instance, orig_fns, NULL_TREE),
@@ -6052,6 +6294,9 @@ build_new_method_call (tree instance, tree fns, tree args,
/* Free all the conversions we allocated. */
obstack_free (&conversion_obstack, p);
+ if (orig_args != NULL)
+ release_tree_vector (orig_args);
+
return call;
}
@@ -6974,7 +7219,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. */
@@ -7002,7 +7247,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;
@@ -7011,7 +7256,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);
@@ -7025,7 +7270,7 @@ can_convert_arg_bad (tree to, tree from, tree arg)
doing a bad conversion, convert_like will complain. */
tree
-perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
+perform_implicit_conversion_flags (tree type, tree expr, tsubst_flags_t complain, int flags)
{
conversion *conv;
void *p;
@@ -7038,11 +7283,21 @@ perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
conv = implicit_conversion (type, TREE_TYPE (expr), expr,
/*c_cast_p=*/false,
- LOOKUP_NORMAL);
+ flags);
+
if (!conv)
{
if (complain & tf_error)
- error ("could not convert %qE to %qT", expr, type);
+ {
+ /* If expr has unknown type, then it is an overloaded function.
+ Call instantiate_type to get good error messages. */
+ if (TREE_TYPE (expr) == unknown_type_node)
+ instantiate_type (type, expr, complain);
+ else if (invalid_nonstatic_memfn_p (expr, complain))
+ /* We gave an error. */;
+ else
+ error ("could not convert %qE to %qT", expr, type);
+ }
expr = error_mark_node;
}
else if (processing_template_decl)
@@ -7062,6 +7317,12 @@ perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
return expr;
}
+tree
+perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
+{
+ return perform_implicit_conversion_flags (type, expr, complain, LOOKUP_IMPLICIT);
+}
+
/* Convert EXPR to TYPE (as a direct-initialization) if that is
permitted. If the conversion is valid, the converted expression is
returned. Otherwise, NULL_TREE is returned, except in the case
@@ -7091,9 +7352,10 @@ perform_direct_initialization_if_possible (tree type,
ill-formed. */
if (CLASS_TYPE_P (type))
{
+ VEC(tree,gc) *args = make_tree_vector_single (expr);
expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr),
- type, LOOKUP_NORMAL, complain);
+ &args, type, LOOKUP_NORMAL, complain);
+ release_tree_vector (args);
return build_cplus_new (type, expr);
}
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index ad50a4eb47d..20ceb6540c4 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -2705,7 +2705,7 @@ check_bitfield_decl (tree field)
DECL_INITIAL (field) = NULL_TREE;
/* Detect invalid bit-field type. */
- if (!INTEGRAL_TYPE_P (type))
+ if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
error ("bit-field %q+#D with non-integral type", field);
w = error_mark_node;
@@ -6072,6 +6072,9 @@ resolve_address_of_overloaded_function (tree target_type,
tree target_arg_types;
tree target_ret_type;
tree fns;
+ tree *args;
+ unsigned int nargs, ia;
+ tree arg;
if (is_ptrmem)
target_fn_type
@@ -6085,6 +6088,14 @@ resolve_address_of_overloaded_function (tree target_type,
if (TREE_CODE (target_fn_type) == METHOD_TYPE)
target_arg_types = TREE_CHAIN (target_arg_types);
+ nargs = list_length (target_arg_types);
+ args = XALLOCAVEC (tree, nargs);
+ for (arg = target_arg_types, ia = 0;
+ arg != NULL_TREE && arg != void_list_node;
+ arg = TREE_CHAIN (arg), ++ia)
+ args[ia] = TREE_VALUE (arg);
+ nargs = ia;
+
for (fns = overload; fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
@@ -6104,9 +6115,9 @@ resolve_address_of_overloaded_function (tree target_type,
/* Try to do argument deduction. */
targs = make_tree_vec (DECL_NTPARMS (fn));
- if (fn_type_unification (fn, explicit_targs, targs,
- target_arg_types, target_ret_type,
- DEDUCE_EXACT, LOOKUP_NORMAL))
+ if (fn_type_unification (fn, explicit_targs, targs, args, nargs,
+ target_ret_type, DEDUCE_EXACT,
+ LOOKUP_NORMAL))
/* Argument deduction failed. */
continue;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index e6545f650f0..e31726cfdb1 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1963,8 +1963,8 @@ struct GTY(()) lang_decl {
is mutable. */
#define DECL_MUTABLE_P(NODE) (DECL_LANG_FLAG_0 (NODE))
-/* Nonzero for _DECL means that this constructor is a non-converting
- constructor. */
+/* Nonzero for _DECL means that this constructor or conversion function is
+ non-converting. */
#define DECL_NONCONVERTING_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.nonconverting)
@@ -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))
@@ -3758,8 +3756,10 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
/* Even if the function found by lookup is a virtual function, it
should be called directly. */
#define LOOKUP_NONVIRTUAL (1 << 2)
-/* Non-converting (i.e., "explicit") constructors are not tried. */
+/* Non-converting (i.e., "explicit") constructors are not tried. This flag
+ indicates that we are not performing direct-initialization. */
#define LOOKUP_ONLYCONVERTING (1 << 3)
+#define LOOKUP_IMPLICIT (LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING)
/* If a temporary is created, it should be created so that it lives
as long as the current variable bindings; otherwise it only lives
until the end of the complete-expression. It also forces
@@ -3793,6 +3793,8 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, OP_FLAG, TYPENAME_FLAG };
/* Avoid user-defined conversions for the first parameter of a copy
constructor. */
#define LOOKUP_NO_COPY_CTOR_CONVERSION (LOOKUP_NO_NARROWING << 1)
+/* This is the first parameter of a copy constructor. */
+#define LOOKUP_COPY_PARM (LOOKUP_NO_COPY_CTOR_CONVERSION << 1)
#define LOOKUP_NAMESPACES_ONLY(F) \
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
@@ -4172,21 +4174,24 @@ extern bool null_ptr_cst_p (tree);
extern bool sufficient_parms_p (const_tree);
extern tree type_decays_to (tree);
extern tree build_user_type_conversion (tree, tree, int);
-extern tree build_new_function_call (tree, tree, bool,
+extern tree build_new_function_call (tree, VEC(tree,gc) **, bool,
tsubst_flags_t);
-extern tree build_operator_new_call (tree, tree, tree *, tree *,
- tree *);
-extern tree build_new_method_call (tree, tree, tree, tree, int,
- tree *, tsubst_flags_t);
-extern tree build_special_member_call (tree, tree, tree, tree, int,
- tsubst_flags_t);
+extern tree build_operator_new_call (tree, VEC(tree,gc) **, tree *,
+ tree *, tree *);
+extern tree build_new_method_call (tree, tree, VEC(tree,gc) **,
+ tree, int, tree *,
+ tsubst_flags_t);
+extern tree build_special_member_call (tree, tree, VEC(tree,gc) **,
+ tree, int, tsubst_flags_t);
extern tree build_new_op (enum tree_code, int, tree,
tree, tree, bool *,
tsubst_flags_t);
+extern tree build_op_call (tree, VEC(tree,gc) **,
+ tsubst_flags_t);
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);
@@ -4200,6 +4205,7 @@ extern tree initialize_reference (tree, tree, tree, tree *);
extern tree make_temporary_var_for_ref_to_temp (tree, tree);
extern tree strip_top_quals (tree);
extern tree perform_implicit_conversion (tree, tree, tsubst_flags_t);
+extern tree perform_implicit_conversion_flags (tree, tree, tsubst_flags_t, int);
extern tree perform_direct_initialization_if_possible (tree, tree, bool,
tsubst_flags_t);
extern tree in_charge_arg_for_name (tree);
@@ -4403,7 +4409,7 @@ extern void determine_visibility (tree);
extern void constrain_class_visibility (tree);
extern void import_export_decl (tree);
extern tree build_cleanup (tree);
-extern tree build_offset_ref_call_from_tree (tree, tree);
+extern tree build_offset_ref_call_from_tree (tree, VEC(tree,gc) **);
extern void check_default_args (tree);
extern void mark_used (tree);
extern void finish_static_data_member_decl (tree, tree, bool, tree, int);
@@ -4467,7 +4473,8 @@ extern tree build_zero_init (tree, tree, bool);
extern tree build_value_init (tree);
extern tree build_value_init_noctor (tree);
extern tree build_offset_ref (tree, tree, bool);
-extern tree build_new (tree, tree, tree, tree, int,
+extern tree build_new (VEC(tree,gc) **, tree, tree,
+ VEC(tree,gc) **, int,
tsubst_flags_t);
extern tree build_vec_init (tree, tree, tree, bool, int,
tsubst_flags_t);
@@ -4549,7 +4556,8 @@ extern int uses_template_parms (tree);
extern int uses_template_parms_level (tree, int);
extern tree instantiate_class_template (tree);
extern tree instantiate_template (tree, tree, tsubst_flags_t);
-extern int fn_type_unification (tree, tree, tree, tree,
+extern int fn_type_unification (tree, tree, tree,
+ const tree *, unsigned int,
tree, unification_kind_t, int);
extern void mark_decl_instantiated (tree, int);
extern int more_specialized_fn (tree, tree, int);
@@ -4562,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);
@@ -4587,7 +4596,7 @@ extern bool any_dependent_template_arguments_p (const_tree);
extern bool dependent_template_p (tree);
extern bool dependent_template_id_p (tree, tree);
extern bool type_dependent_expression_p (tree);
-extern bool any_type_dependent_arguments_p (const_tree);
+extern bool any_type_dependent_arguments_p (const VEC(tree,gc) *);
extern bool type_dependent_expression_p_push (tree);
extern bool value_dependent_expression_p (tree);
extern bool any_value_dependent_elements_p (const_tree);
@@ -4595,7 +4604,7 @@ extern bool dependent_omp_for_p (tree, tree, tree, tree);
extern tree resolve_typename_type (tree, bool);
extern tree template_for_substitution (tree);
extern tree build_non_dependent_expr (tree);
-extern tree build_non_dependent_args (tree);
+extern void make_args_non_dependent (VEC(tree,gc) *);
extern bool reregister_specialization (tree, tree, tree);
extern tree fold_non_dependent_expr (tree);
extern bool explicit_class_specialization_p (tree);
@@ -4743,9 +4752,9 @@ extern tree begin_stmt_expr (void);
extern tree finish_stmt_expr_expr (tree, tree);
extern tree finish_stmt_expr (tree, bool);
extern tree stmt_expr_value_expr (tree);
-extern tree perform_koenig_lookup (tree, tree);
-extern tree finish_call_expr (tree, tree, bool, bool,
- tsubst_flags_t);
+extern tree perform_koenig_lookup (tree, VEC(tree,gc) *);
+extern tree finish_call_expr (tree, VEC(tree,gc) **, bool,
+ bool, tsubst_flags_t);
extern tree finish_increment_expr (tree, enum tree_code);
extern tree finish_this_expr (void);
extern tree finish_pseudo_destructor_expr (tree, tree, tree);
@@ -4818,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);
@@ -4827,7 +4836,7 @@ extern bool builtin_valid_in_constant_expr_p (const_tree);
extern tree build_min (enum tree_code, tree, ...);
extern tree build_min_nt (enum tree_code, ...);
extern tree build_min_non_dep (enum tree_code, tree, ...);
-extern tree build_min_non_dep_call_list (tree, tree, tree);
+extern tree build_min_non_dep_call_vec (tree, tree, VEC(tree,gc) *);
extern tree build_cplus_new (tree, tree);
extern tree build_aggr_init_expr (tree, tree);
extern tree get_target_expr (tree);
@@ -4927,6 +4936,8 @@ extern tree cp_build_indirect_ref (tree, const char *,
extern tree build_array_ref (tree, tree, location_t);
extern tree get_member_function_from_ptrfunc (tree *, tree);
extern tree cp_build_function_call (tree, tree, tsubst_flags_t);
+extern tree cp_build_function_call_vec (tree, VEC(tree,gc) **,
+ tsubst_flags_t);
extern tree build_x_binary_op (enum tree_code, tree,
enum tree_code, tree,
enum tree_code, bool *,
@@ -4940,6 +4951,7 @@ extern tree unary_complex_lvalue (enum tree_code, tree);
extern tree build_x_conditional_expr (tree, tree, tree,
tsubst_flags_t);
extern tree build_x_compound_expr_from_list (tree, const char *);
+extern tree build_x_compound_expr_from_vec (VEC(tree,gc) *, const char *);
extern tree build_x_compound_expr (tree, tree, tsubst_flags_t);
extern tree build_compound_expr (tree, tree);
extern tree cp_build_compound_expr (tree, tree, tsubst_flags_t);
@@ -5001,9 +5013,10 @@ extern void readonly_error (tree, const char *);
extern void complete_type_check_abstract (tree);
extern int abstract_virtuals_error (tree, tree);
-extern tree store_init_value (tree, tree);
+extern tree store_init_value (tree, tree, int);
extern void check_narrowing (tree, tree);
extern tree digest_init (tree, tree);
+extern tree digest_init_flags (tree, tree, int);
extern tree build_scoped_ref (tree, tree, tree *);
extern tree build_x_arrow (tree);
extern tree build_m_component_ref (tree, tree);
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index f179dbe36fa..fe243ff75d4 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -1,6 +1,6 @@
/* Language-level data type conversion for GNU C++.
Copyright (C) 1987, 1988, 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.
Hacked by Michael Tiemann (tiemann@cygnus.com)
@@ -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,
@@ -581,6 +581,7 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
tree e = expr;
enum tree_code code = TREE_CODE (type);
const char *invalid_conv_diag;
+ tree e1;
if (error_operand_p (e) || type == error_mark_node)
return error_mark_node;
@@ -629,6 +630,10 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
}
}
+ e1 = targetm.convert_to_type (type, e);
+ if (e1)
+ return e1;
+
if (code == VOID_TYPE && (convtype & CONV_STATIC))
{
e = convert_to_void (e, /*implicit=*/NULL, tf_warning_or_error);
@@ -750,11 +755,15 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
the target with the temp (see [dcl.init]). */
ctor = build_user_type_conversion (type, ctor, flags);
else
- ctor = build_special_member_call (NULL_TREE,
- complete_ctor_identifier,
- build_tree_list (NULL_TREE, ctor),
- type, flags,
- tf_warning_or_error);
+ {
+ VEC(tree,gc) *ctor_vec = make_tree_vector_single (ctor);
+ ctor = build_special_member_call (NULL_TREE,
+ complete_ctor_identifier,
+ &ctor_vec,
+ type, flags,
+ tf_warning_or_error);
+ release_tree_vector (ctor_vec);
+ }
if (ctor)
return build_cplus_new (type, ctor);
}
@@ -1182,6 +1191,9 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
if (winner && winner == cand)
continue;
+ if (DECL_NONCONVERTING_P (cand))
+ continue;
+
candidate = non_reference (TREE_TYPE (TREE_TYPE (cand)));
switch (TREE_CODE (candidate))
@@ -1249,11 +1261,18 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
tree
type_promotes_to (tree type)
{
+ tree promoted_type;
+
if (type == error_mark_node)
return error_mark_node;
type = TYPE_MAIN_VARIANT (type);
+ /* Check for promotions of target-defined types first. */
+ promoted_type = targetm.promoted_type (type);
+ if (promoted_type)
+ return promoted_type;
+
/* bool always promotes to int (not unsigned), even if it's the same
size. */
if (type == boolean_type_node)
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ed76dc397e4..a626a71fc34 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5176,7 +5176,7 @@ check_initializer (tree decl, tree init, int flags, tree *cleanup)
return build_aggr_init_full_exprs (decl, init, flags);
else if (TREE_CODE (init) != TREE_VEC)
{
- init_code = store_init_value (decl, init);
+ init_code = store_init_value (decl, init, flags);
if (pedantic && TREE_CODE (type) == ARRAY_TYPE
&& DECL_INITIAL (decl)
&& TREE_CODE (DECL_INITIAL (decl)) == STRING_CST
@@ -7154,7 +7154,7 @@ check_static_variable_definition (tree decl, tree type)
error ("ISO C++ forbids in-class initialization of non-const "
"static member %qD",
decl);
- else if (!INTEGRAL_TYPE_P (type))
+ else if (!INTEGRAL_OR_ENUMERATION_TYPE_P (type))
pedwarn (input_location, OPT_pedantic, "ISO C++ forbids initialization of member constant "
"%qD of non-integral type %qT", decl, type);
@@ -7177,7 +7177,7 @@ compute_array_index_type (tree name, tree size)
type = TREE_TYPE (size);
/* The array bound must be an integer type. */
- if (!dependent_type_p (type) && !INTEGRAL_TYPE_P (type))
+ if (!dependent_type_p (type) && !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type))
{
if (name)
error ("size of array %qD has non-integral type %qT", name, type);
@@ -7606,6 +7606,7 @@ grokdeclarator (const cp_declarator *declarator,
bool parameter_pack_p = declarator? declarator->parameter_pack_p : false;
bool set_no_warning = false;
bool template_type_arg = false;
+ const char *errmsg;
signed_p = declspecs->specs[(int)ds_signed];
unsigned_p = declspecs->specs[(int)ds_unsigned];
@@ -8285,6 +8286,12 @@ grokdeclarator (const cp_declarator *declarator,
type_quals = TYPE_UNQUALIFIED;
set_no_warning = true;
}
+ errmsg = targetm.invalid_return_type (type);
+ if (errmsg)
+ {
+ error (errmsg);
+ type = integer_type_node;
+ }
/* Error about some types functions can't return. */
@@ -8413,6 +8420,14 @@ grokdeclarator (const cp_declarator *declarator,
"class definition",
name);
}
+ else if (ctype && sfk == sfk_conversion)
+ {
+ if (explicitp == 1)
+ {
+ maybe_warn_cpp0x ("explicit conversion operators");
+ explicitp = 2;
+ }
+ }
arg_types = grokparms (declarator->u.function.parameters,
&parms);
@@ -9669,6 +9684,7 @@ grokparms (tree parmlist, tree *parms)
tree type = NULL_TREE;
tree init = TREE_PURPOSE (parm);
tree decl = TREE_VALUE (parm);
+ const char *errmsg;
if (parm == void_list_node)
break;
@@ -9702,6 +9718,14 @@ grokparms (tree parmlist, tree *parms)
init = NULL_TREE;
}
+ if (type != error_mark_node
+ && (errmsg = targetm.invalid_parameter_type (type)))
+ {
+ error (errmsg);
+ type = error_mark_node;
+ TREE_TYPE (decl) = error_mark_node;
+ }
+
if (type != error_mark_node)
{
if (deprecated_state != DEPRECATED_SUPPRESS)
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 78fcc6f2702..fbe8f0daf60 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -964,7 +964,7 @@ grokbitfield (const cp_declarator *declarator,
if (TREE_CODE (value) == VOID_TYPE)
return void_type_node;
- if (!INTEGRAL_TYPE_P (TREE_TYPE (value))
+ if (!INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value))
&& (POINTER_TYPE_P (value)
|| !dependent_type_p (TREE_TYPE (value))))
{
@@ -1713,6 +1713,10 @@ decl_needed_p (tree decl)
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))))
return true;
+ /* Functions marked "dllexport" must be emitted so that they are
+ visible to other DLLs. */
+ if (lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))
+ return true;
/* Otherwise, DECL does not need to be emitted -- yet. A subsequent
reference to DECL might cause it to be emitted later. */
return false;
@@ -1770,7 +1774,7 @@ maybe_emit_vtables (tree ctype)
if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
{
- tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl));
+ tree expr = store_init_value (vtbl, DECL_INITIAL (vtbl), LOOKUP_NORMAL);
/* It had better be all done at compile-time. */
gcc_assert (!expr);
@@ -3686,18 +3690,18 @@ cp_write_global_declarations (void)
/* FN is an OFFSET_REF, DOTSTAR_EXPR or MEMBER_REF indicating the
function to call in parse-tree form; it has not yet been
semantically analyzed. ARGS are the arguments to the function.
- They have already been semantically analyzed. */
+ They have already been semantically analyzed. This may change
+ ARGS. */
tree
-build_offset_ref_call_from_tree (tree fn, tree args)
+build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
{
tree orig_fn;
- tree orig_args;
+ VEC(tree,gc) *orig_args = NULL;
tree expr;
tree object;
orig_fn = fn;
- orig_args = args;
object = TREE_OPERAND (fn, 0);
if (processing_template_decl)
@@ -3705,17 +3709,19 @@ build_offset_ref_call_from_tree (tree fn, tree args)
gcc_assert (TREE_CODE (fn) == DOTSTAR_EXPR
|| TREE_CODE (fn) == MEMBER_REF);
if (type_dependent_expression_p (fn)
- || any_type_dependent_arguments_p (args))
- return build_nt_call_list (fn, args);
+ || any_type_dependent_arguments_p (*args))
+ return build_nt_call_vec (fn, *args);
+
+ orig_args = make_tree_vector_copy (*args);
/* Transform the arguments and add the implicit "this"
parameter. That must be done before the FN is transformed
because we depend on the form of FN. */
- args = build_non_dependent_args (args);
+ make_args_non_dependent (*args);
object = build_non_dependent_expr (object);
if (TREE_CODE (fn) == DOTSTAR_EXPR)
object = cp_build_unary_op (ADDR_EXPR, object, 0, tf_warning_or_error);
- args = tree_cons (NULL_TREE, object, args);
+ VEC_safe_insert (tree, gc, *args, 0, object);
/* Now that the arguments are done, transform FN. */
fn = build_non_dependent_expr (fn);
}
@@ -3732,12 +3738,16 @@ build_offset_ref_call_from_tree (tree fn, tree args)
tf_warning_or_error);
fn = TREE_OPERAND (fn, 1);
fn = get_member_function_from_ptrfunc (&object_addr, fn);
- args = tree_cons (NULL_TREE, object_addr, args);
+ VEC_safe_insert (tree, gc, *args, 0, object_addr);
}
- expr = cp_build_function_call (fn, args, tf_warning_or_error);
+ expr = cp_build_function_call_vec (fn, args, tf_warning_or_error);
if (processing_template_decl && expr != error_mark_node)
- return build_min_non_dep_call_list (expr, orig_fn, orig_args);
+ expr = build_min_non_dep_call_vec (expr, orig_fn, orig_args);
+
+ if (orig_args != NULL)
+ release_tree_vector (orig_args);
+
return expr;
}
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
index 4a900a86d4a..004543dd210 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);
}
}
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index 2638ccc90d9..99c70361045 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -1,6 +1,6 @@
/* Handle exceptional things in C++.
Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
- 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+ 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Michael Tiemann <tiemann@cygnus.com>
Rewritten by Mike Stump <mrs@cygnus.com>, based upon an
@@ -736,6 +736,7 @@ build_throw (tree exp)
if (CLASS_TYPE_P (temp_type))
{
int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
+ VEC(tree,gc) *exp_vec;
/* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
treated as an rvalue for the purposes of overload resolution
@@ -749,11 +750,11 @@ build_throw (tree exp)
flags = flags | LOOKUP_PREFER_RVALUE;
/* Call the copy constructor. */
+ exp_vec = make_tree_vector_single (exp);
exp = (build_special_member_call
- (object, complete_ctor_identifier,
- build_tree_list (NULL_TREE, exp),
- TREE_TYPE (object),
- flags, tf_warning_or_error));
+ (object, complete_ctor_identifier, &exp_vec,
+ TREE_TYPE (object), flags, tf_warning_or_error));
+ release_tree_vector (exp_vec);
if (exp == error_mark_node)
{
error (" in thrown expression");
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index d40a5e7e53f..a99983e18ee 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -302,7 +302,7 @@ build_value_init (tree type)
return build_aggr_init_expr
(type,
build_special_member_call (NULL_TREE, complete_ctor_identifier,
- NULL_TREE, type, LOOKUP_NORMAL,
+ NULL, type, LOOKUP_NORMAL,
tf_warning_or_error));
else if (TREE_CODE (type) != UNION_TYPE && TYPE_NEEDS_CONSTRUCTING (type))
{
@@ -312,7 +312,7 @@ build_value_init (tree type)
This will be handled in simplify_aggr_init_expr. */
tree ctor = build_special_member_call
(NULL_TREE, complete_ctor_identifier,
- NULL_TREE, type, LOOKUP_NORMAL, tf_warning_or_error);
+ NULL, type, LOOKUP_NORMAL, tf_warning_or_error);
ctor = build_aggr_init_expr (type, ctor);
AGGR_INIT_ZERO_FIRST (ctor) = 1;
@@ -951,7 +951,7 @@ expand_cleanup_for_base (tree binfo, tree flag)
/* Call the destructor. */
expr = build_special_member_call (current_class_ref,
base_dtor_identifier,
- NULL_TREE,
+ NULL,
binfo,
LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
tf_warning_or_error);
@@ -1285,7 +1285,7 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
followed by initialization by X. If neither of these work
out, then look hard. */
tree rval;
- tree parms;
+ VEC(tree,gc) *parms;
if (init && TREE_CODE (init) != TREE_LIST
&& (flags & LOOKUP_ONLYCONVERTING))
@@ -1325,23 +1325,28 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
return;
}
- if (init == NULL_TREE
- || (TREE_CODE (init) == TREE_LIST && ! TREE_TYPE (init)))
+ if (init == NULL_TREE)
+ parms = NULL;
+ else if (TREE_CODE (init) == TREE_LIST && !TREE_TYPE (init))
{
- parms = init;
- if (parms)
- init = TREE_VALUE (parms);
+ parms = make_tree_vector ();
+ for (; init != NULL_TREE; init = TREE_CHAIN (init))
+ VEC_safe_push (tree, gc, parms, TREE_VALUE (init));
}
else
- parms = build_tree_list (NULL_TREE, init);
+ parms = make_tree_vector_single (init);
if (true_exp == exp)
ctor_name = complete_ctor_identifier;
else
ctor_name = base_ctor_identifier;
- rval = build_special_member_call (exp, ctor_name, parms, binfo, flags,
+ rval = build_special_member_call (exp, ctor_name, &parms, binfo, flags,
complain);
+
+ if (parms != NULL)
+ release_tree_vector (parms);
+
if (TREE_SIDE_EFFECTS (rval))
finish_expr_stmt (convert_to_void (rval, NULL, complain));
}
@@ -1387,7 +1392,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags,
/* If store_init_value returns NULL_TREE, the INIT has been
recorded as the DECL_INITIAL for EXP. That means there's
nothing more we have to do. */
- init = store_init_value (exp, init);
+ init = store_init_value (exp, init, flags);
if (init)
finish_expr_stmt (init);
return;
@@ -1706,81 +1711,46 @@ build_builtin_delete_call (tree addr)
the type of the object being allocated; otherwise, it's just TYPE.
INIT is the initializer, if any. USE_GLOBAL_NEW is true if the
user explicitly wrote "::operator new". PLACEMENT, if non-NULL, is
- the TREE_LIST of arguments to be provided as arguments to a
- placement new operator. This routine performs no semantic checks;
- it just creates and returns a NEW_EXPR. */
+ a vector of arguments to be provided as arguments to a placement
+ new operator. This routine performs no semantic checks; it just
+ creates and returns a NEW_EXPR. */
static tree
-build_raw_new_expr (tree placement, tree type, tree nelts, tree init,
- int use_global_new)
+build_raw_new_expr (VEC(tree,gc) *placement, tree type, tree nelts,
+ VEC(tree,gc) *init, int use_global_new)
{
+ tree init_list;
tree new_expr;
- new_expr = build4 (NEW_EXPR, build_pointer_type (type), placement, type,
- nelts, init);
+ /* If INIT is NULL, the we want to store NULL_TREE in the NEW_EXPR.
+ If INIT is not NULL, then we want to store VOID_ZERO_NODE. This
+ permits us to distinguish the case of a missing initializer "new
+ int" from an empty initializer "new int()". */
+ if (init == NULL)
+ init_list = NULL_TREE;
+ else if (VEC_empty (tree, init))
+ init_list = void_zero_node;
+ else
+ init_list = build_tree_list_vec (init);
+
+ new_expr = build4 (NEW_EXPR, build_pointer_type (type),
+ build_tree_list_vec (placement), type, nelts,
+ init_list);
NEW_EXPR_USE_GLOBAL (new_expr) = use_global_new;
TREE_SIDE_EFFECTS (new_expr) = 1;
return new_expr;
}
-/* Make sure that there are no aliasing issues with T, a placement new
- expression applied to PLACEMENT, by recording the change in dynamic
- type. If placement new is inlined, as it is with libstdc++, and if
- the type of the placement new differs from the type of the
- placement location itself, then alias analysis may think it is OK
- to interchange writes to the location from before the placement new
- and from after the placement new. We have to prevent type-based
- alias analysis from applying. PLACEMENT may be NULL, which means
- that we couldn't capture it in a temporary variable, in which case
- we use a memory clobber. */
-
-static tree
-avoid_placement_new_aliasing (tree t, tree placement)
-{
- tree type_change;
-
- if (processing_template_decl)
- return t;
-
- /* If we are not using type based aliasing, we don't have to do
- anything. */
- if (!flag_strict_aliasing)
- return t;
-
- /* If we have a pointer and a location, record the change in dynamic
- type. Otherwise we need a general memory clobber. */
- if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE
- && placement != NULL_TREE
- && TREE_CODE (TREE_TYPE (placement)) == POINTER_TYPE)
- type_change = build_stmt (CHANGE_DYNAMIC_TYPE_EXPR,
- TREE_TYPE (t),
- placement);
- else
- {
- /* Build a memory clobber. */
- type_change = build_stmt (ASM_EXPR,
- build_string (0, ""),
- NULL_TREE,
- NULL_TREE,
- tree_cons (NULL_TREE,
- build_string (6, "memory"),
- NULL_TREE));
-
- ASM_VOLATILE_P (type_change) = 1;
- }
-
- return build2 (COMPOUND_EXPR, TREE_TYPE (t), type_change, t);
-}
-
/* Generate code for a new-expression, including calling the "operator
new" function, initializing the object, and, if an exception occurs
during construction, cleaning up. The arguments are as for
- build_raw_new_expr. */
+ build_raw_new_expr. This may change PLACEMENT and INIT. */
static tree
-build_new_1 (tree placement, tree type, tree nelts, tree init,
- bool globally_qualified_p, tsubst_flags_t complain)
+build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
+ VEC(tree,gc) **init, bool globally_qualified_p,
+ tsubst_flags_t complain)
{
tree size, rval;
/* True iff this is a call to "operator new[]" instead of just
@@ -1807,11 +1777,11 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
beginning of the storage allocated for an array-new expression in
order to store the number of elements. */
tree cookie_size = NULL_TREE;
+ tree placement_first;
tree placement_expr = NULL_TREE;
/* True if the function we are calling is a placement allocation
function. */
bool placement_allocation_fn_p;
- tree args = NULL_TREE;
/* True if the storage must be initialized, either by a constructor
or due to an explicit new-initializer. */
bool is_initialized;
@@ -1855,9 +1825,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
if (abstract_virtuals_error (NULL_TREE, elt_type))
return error_mark_node;
- is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || init);
+ is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL);
- if (CP_TYPE_CONST_P (elt_type) && !init
+ if (CP_TYPE_CONST_P (elt_type) && *init == NULL
&& !type_has_user_provided_default_constructor (elt_type))
{
if (complain & tf_error)
@@ -1871,8 +1841,17 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
alloc_fn = NULL_TREE;
+ /* If PLACEMENT is a single simple pointer type not passed by
+ reference, prepare to capture it in a temporary variable. Do
+ this now, since PLACEMENT will change in the calls below. */
+ placement_first = NULL_TREE;
+ if (VEC_length (tree, *placement) == 1
+ && (TREE_CODE (TREE_TYPE (VEC_index (tree, *placement, 0)))
+ == POINTER_TYPE))
+ placement_first = VEC_index (tree, *placement, 0);
+
/* Allocate the object. */
- if (! placement && TYPE_FOR_JAVA (elt_type))
+ if (VEC_empty (tree, *placement) && TYPE_FOR_JAVA (elt_type))
{
tree class_addr;
tree class_decl = build_java_class_ref (elt_type);
@@ -1928,7 +1907,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
size = size_binop (PLUS_EXPR, size, cookie_size);
}
/* Create the argument list. */
- args = tree_cons (NULL_TREE, size, placement);
+ VEC_safe_insert (tree, gc, *placement, 0, size);
/* Do name-lookup to find the appropriate operator. */
fns = lookup_fnfields (elt_type, fnname, /*protect=*/2);
if (fns == NULL_TREE)
@@ -1947,7 +1926,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
return error_mark_node;
}
alloc_call = build_new_method_call (build_dummy_object (elt_type),
- fns, args,
+ fns, placement,
/*conversion_path=*/NULL_TREE,
LOOKUP_NORMAL,
&alloc_fn,
@@ -1973,12 +1952,10 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
gcc_assert (alloc_fn != NULL_TREE);
- /* If PLACEMENT is a simple pointer type and is not passed by reference,
- then copy it into PLACEMENT_EXPR. */
+ /* If we found a simple case of PLACEMENT_EXPR above, then copy it
+ into a temporary variable. */
if (!processing_template_decl
- && placement != NULL_TREE
- && TREE_CHAIN (placement) == NULL_TREE
- && TREE_CODE (TREE_TYPE (TREE_VALUE (placement))) == POINTER_TYPE
+ && placement_first != NULL_TREE
&& TREE_CODE (alloc_call) == CALL_EXPR
&& call_expr_nargs (alloc_call) == 2
&& TREE_CODE (TREE_TYPE (CALL_EXPR_ARG (alloc_call, 0))) == INTEGER_TYPE
@@ -1986,10 +1963,10 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
{
tree placement_arg = CALL_EXPR_ARG (alloc_call, 1);
- if (INTEGRAL_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg)))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg)))
|| VOID_TYPE_P (TREE_TYPE (TREE_TYPE (placement_arg))))
{
- placement_expr = get_target_expr (TREE_VALUE (placement));
+ placement_expr = get_target_expr (placement_first);
CALL_EXPR_ARG (alloc_call, 1)
= convert (TREE_TYPE (placement_arg), placement_expr);
}
@@ -1998,12 +1975,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
/* In the simple case, we can stop now. */
pointer_type = build_pointer_type (type);
if (!cookie_size && !is_initialized)
- {
- rval = build_nop (pointer_type, alloc_call);
- if (placement != NULL)
- rval = avoid_placement_new_aliasing (rval, placement_expr);
- return rval;
- }
+ return build_nop (pointer_type, alloc_call);
/* Store the result of the allocation call in a variable so that we can
use it more than once. */
@@ -2109,15 +2081,15 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
bool stable;
bool explicit_value_init_p = false;
- if (init == void_zero_node)
+ if (*init != NULL && VEC_empty (tree, *init))
{
- init = NULL_TREE;
+ *init = NULL;
explicit_value_init_p = true;
}
if (array_p)
{
- if (init)
+ if (*init)
{
if (complain & tf_error)
permerror (input_location, "ISO C++ forbids initialization in array new");
@@ -2130,7 +2102,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
MINUS_EXPR, outer_nelts,
integer_one_node,
complain),
- init,
+ build_tree_list_vec (*init),
explicit_value_init_p,
/*from_array=*/0,
complain);
@@ -2160,17 +2132,13 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
}
else
{
+ tree ie;
+
/* We are processing something like `new int (10)', which
means allocate an int, and initialize it with 10. */
- if (TREE_CODE (init) == TREE_LIST)
- init = build_x_compound_expr_from_list (init,
- "new initializer");
- else
- gcc_assert (TREE_CODE (init) != CONSTRUCTOR
- || TREE_TYPE (init) != NULL_TREE);
-
- init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, init,
+ ie = build_x_compound_expr_from_vec (*init, "new initializer");
+ init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, ie,
complain);
}
stable = stabilize_init (init_expr, &init_preeval_expr);
@@ -2283,60 +2251,55 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
/* A new-expression is never an lvalue. */
gcc_assert (!lvalue_p (rval));
- if (placement != NULL)
- rval = avoid_placement_new_aliasing (rval, placement_expr);
-
return rval;
}
-/* Generate a representation for a C++ "new" expression. PLACEMENT is
- a TREE_LIST of placement-new arguments (or NULL_TREE if none). If
- NELTS is NULL, TYPE is the type of the storage to be allocated. If
- NELTS is not NULL, then this is an array-new allocation; TYPE is
- the type of the elements in the array and NELTS is the number of
- elements in the array. INIT, if non-NULL, is the initializer for
- the new object, or void_zero_node to indicate an initializer of
- "()". If USE_GLOBAL_NEW is true, then the user explicitly wrote
- "::new" rather than just "new". */
+/* Generate a representation for a C++ "new" expression. *PLACEMENT
+ is a vector of placement-new arguments (or NULL if none). If NELTS
+ is NULL, TYPE is the type of the storage to be allocated. If NELTS
+ is not NULL, then this is an array-new allocation; TYPE is the type
+ of the elements in the array and NELTS is the number of elements in
+ the array. *INIT, if non-NULL, is the initializer for the new
+ object, or an empty vector to indicate an initializer of "()". If
+ USE_GLOBAL_NEW is true, then the user explicitly wrote "::new"
+ rather than just "new". This may change PLACEMENT and INIT. */
tree
-build_new (tree placement, tree type, tree nelts, tree init,
- int use_global_new, tsubst_flags_t complain)
+build_new (VEC(tree,gc) **placement, tree type, tree nelts,
+ VEC(tree,gc) **init, int use_global_new, tsubst_flags_t complain)
{
tree rval;
- tree orig_placement;
- tree orig_nelts;
- tree orig_init;
+ VEC(tree,gc) *orig_placement = NULL;
+ tree orig_nelts = NULL_TREE;
+ VEC(tree,gc) *orig_init = NULL;
- if (placement == error_mark_node || type == error_mark_node
- || init == error_mark_node)
+ if (type == error_mark_node)
return error_mark_node;
- orig_placement = placement;
- orig_nelts = nelts;
- orig_init = init;
-
- if (nelts == NULL_TREE && init != void_zero_node && list_length (init) == 1)
+ if (nelts == NULL_TREE && VEC_length (tree, *init) == 1)
{
tree auto_node = type_uses_auto (type);
- if (auto_node && describable_type (TREE_VALUE (init)))
- type = do_auto_deduction (type, TREE_VALUE (init), auto_node);
+ if (auto_node && describable_type (VEC_index (tree, *init, 0)))
+ type = do_auto_deduction (type, VEC_index (tree, *init, 0), auto_node);
}
if (processing_template_decl)
{
if (dependent_type_p (type)
- || any_type_dependent_arguments_p (placement)
+ || any_type_dependent_arguments_p (*placement)
|| (nelts && type_dependent_expression_p (nelts))
- || (init != void_zero_node
- && any_type_dependent_arguments_p (init)))
- return build_raw_new_expr (placement, type, nelts, init,
+ || any_type_dependent_arguments_p (*init))
+ return build_raw_new_expr (*placement, type, nelts, *init,
use_global_new);
- placement = build_non_dependent_args (placement);
+
+ orig_placement = make_tree_vector_copy (*placement);
+ orig_nelts = nelts;
+ orig_init = make_tree_vector_copy (*init);
+
+ make_args_non_dependent (*placement);
if (nelts)
nelts = build_non_dependent_expr (nelts);
- if (init != void_zero_node)
- init = build_non_dependent_args (init);
+ make_args_non_dependent (*init);
}
if (nelts)
@@ -2381,8 +2344,13 @@ build_new (tree placement, tree type, tree nelts, tree init,
return error_mark_node;
if (processing_template_decl)
- return build_raw_new_expr (orig_placement, type, orig_nelts, orig_init,
- use_global_new);
+ {
+ tree ret = build_raw_new_expr (orig_placement, type, orig_nelts,
+ orig_init, use_global_new);
+ release_tree_vector (orig_placement);
+ release_tree_vector (orig_init);
+ return ret;
+ }
/* Wrap it in a NOP_EXPR so warn_if_unused_value doesn't complain. */
rval = build1 (NOP_EXPR, TREE_TYPE (rval), rval);
@@ -2954,7 +2922,7 @@ build_dtor_call (tree exp, special_function_kind dtor_kind, int flags)
}
fn = lookup_fnfields (TREE_TYPE (exp), name, /*protect=*/2);
return build_new_method_call (exp, fn,
- /*args=*/NULL_TREE,
+ /*args=*/NULL,
/*conversion_path=*/NULL_TREE,
flags,
/*fn_p=*/NULL,
@@ -3172,7 +3140,7 @@ push_base_cleanups (void)
{
expr = build_special_member_call (current_class_ref,
base_dtor_identifier,
- NULL_TREE,
+ NULL,
base_binfo,
(LOOKUP_NORMAL
| LOOKUP_NONVIRTUAL),
@@ -3194,7 +3162,7 @@ push_base_cleanups (void)
expr = build_special_member_call (current_class_ref,
base_dtor_identifier,
- NULL_TREE, base_binfo,
+ NULL, base_binfo,
LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
tf_warning_or_error);
finish_decl_cleanup (NULL_TREE, expr);
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/method.c b/gcc/cp/method.c
index e632fe0c9e6..410503d05e1 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -1,7 +1,7 @@
/* Handle the hair of processing (but not expanding) inline functions.
Also manage function and variable name overloading.
Copyright (C) 1987, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com)
@@ -661,19 +661,21 @@ do_build_assign_ref (tree fndecl)
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
tree converted_parm;
+ VEC(tree,gc) *parmvec;
/* We must convert PARM directly to the base class
explicitly since the base class may be ambiguous. */
converted_parm = build_base_path (PLUS_EXPR, parm, base_binfo, 1);
/* Call the base class assignment operator. */
+ parmvec = make_tree_vector_single (converted_parm);
finish_expr_stmt
(build_special_member_call (current_class_ref,
ansi_assopname (NOP_EXPR),
- build_tree_list (NULL_TREE,
- converted_parm),
+ &parmvec,
base_binfo,
LOOKUP_NORMAL | LOOKUP_NONVIRTUAL,
tf_warning_or_error));
+ release_tree_vector (parmvec);
}
/* Assign to each of the non-static data members. */
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index e499edeabba..215750f5b40 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -4235,7 +4235,7 @@ lookup_name_nonclass (tree name)
}
tree
-lookup_function_nonclass (tree name, tree args, bool block_p)
+lookup_function_nonclass (tree name, VEC(tree,gc) *args, bool block_p)
{
return
lookup_arg_dependent (name,
@@ -4427,7 +4427,7 @@ lookup_type_current_level (tree name)
struct arg_lookup
{
tree name;
- tree args;
+ VEC(tree,gc) *args;
tree namespaces;
tree classes;
tree functions;
@@ -4435,6 +4435,7 @@ struct arg_lookup
static bool arg_assoc (struct arg_lookup*, tree);
static bool arg_assoc_args (struct arg_lookup*, tree);
+static bool arg_assoc_args_vec (struct arg_lookup*, VEC(tree,gc) *);
static bool arg_assoc_type (struct arg_lookup*, tree);
static bool add_function (struct arg_lookup *, tree);
static bool arg_assoc_namespace (struct arg_lookup *, tree);
@@ -4589,13 +4590,13 @@ arg_assoc_namespace (struct arg_lookup *k, tree scope)
classes. */
if (hidden_name_p (OVL_CURRENT (value)))
{
- tree args;
+ unsigned int ix;
+ tree arg;
- for (args = k->args; args; args = TREE_CHAIN (args))
- if (friend_of_associated_class_p (TREE_VALUE (args),
- OVL_CURRENT (value)))
+ for (ix = 0; VEC_iterate (tree, k->args, ix, arg); ++ix)
+ if (friend_of_associated_class_p (arg, OVL_CURRENT (value)))
break;
- if (!args)
+ if (ix >= VEC_length (tree, k->args))
continue;
}
@@ -4805,6 +4806,21 @@ arg_assoc_args (struct arg_lookup *k, tree args)
return false;
}
+/* Adds everything associated with an argument vector. Returns true
+ on error. */
+
+static bool
+arg_assoc_args_vec (struct arg_lookup *k, VEC(tree,gc) *args)
+{
+ unsigned int ix;
+ tree arg;
+
+ for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+ if (arg_assoc (k, arg))
+ return true;
+ return false;
+}
+
/* Adds everything associated with a given tree_node. Returns 1 on error. */
static bool
@@ -4884,7 +4900,7 @@ arg_assoc (struct arg_lookup *k, tree n)
are the functions found in normal lookup. */
tree
-lookup_arg_dependent (tree name, tree fns, tree args)
+lookup_arg_dependent (tree name, tree fns, VEC(tree,gc) *args)
{
struct arg_lookup k;
@@ -4907,7 +4923,7 @@ lookup_arg_dependent (tree name, tree fns, tree args)
picking up later definitions) in the second stage. */
k.namespaces = NULL_TREE;
- arg_assoc_args (&k, args);
+ arg_assoc_args_vec (&k, args);
fns = k.functions;
diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h
index 6de4cfa7d43..2203a8400bf 100644
--- a/gcc/cp/name-lookup.h
+++ b/gcc/cp/name-lookup.h
@@ -1,5 +1,6 @@
/* Declarations for C++ name lookup routines.
- Copyright (C) 2003, 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
+ Copyright (C) 2003, 2004, 2005, 2007, 2008, 2009
+ Free Software Foundation, Inc.
Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
This file is part of GCC.
@@ -317,7 +318,7 @@ extern tree remove_hidden_names (tree);
extern tree lookup_qualified_name (tree, tree, bool, bool);
extern tree lookup_name_nonclass (tree);
extern tree lookup_name_innermost_nonclass_level (tree);
-extern tree lookup_function_nonclass (tree, tree, bool);
+extern tree lookup_function_nonclass (tree, VEC(tree,gc) *, bool);
extern void push_local_binding (tree, tree, int);
extern bool pushdecl_class_level (tree);
extern tree pushdecl_namespace_level (tree, bool);
@@ -332,7 +333,7 @@ extern void do_toplevel_using_decl (tree, tree, tree);
extern void do_local_using_decl (tree, tree, tree);
extern tree do_class_using_decl (tree, tree);
extern void do_using_directive (tree);
-extern tree lookup_arg_dependent (tree, tree, tree);
+extern tree lookup_arg_dependent (tree, tree, VEC(tree,gc) *);
extern bool is_associated_namespace (tree, tree);
extern void parse_using_directive (tree, tree);
extern tree innermost_non_namespace_value (tree);
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 963f70204a4..701fbc01f75 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1584,7 +1584,7 @@ static tree cp_parser_postfix_open_square_expression
(cp_parser *, tree, bool);
static tree cp_parser_postfix_dot_deref_expression
(cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
-static tree cp_parser_parenthesized_expression_list
+static VEC(tree,gc) *cp_parser_parenthesized_expression_list
(cp_parser *, bool, bool, bool, bool *);
static void cp_parser_pseudo_destructor_name
(cp_parser *, tree *, tree *);
@@ -1594,7 +1594,7 @@ static enum tree_code cp_parser_unary_operator
(cp_token *);
static tree cp_parser_new_expression
(cp_parser *);
-static tree cp_parser_new_placement
+static VEC(tree,gc) *cp_parser_new_placement
(cp_parser *);
static tree cp_parser_new_type_id
(cp_parser *, tree *);
@@ -1602,7 +1602,7 @@ static cp_declarator *cp_parser_new_declarator_opt
(cp_parser *);
static cp_declarator *cp_parser_direct_new_declarator
(cp_parser *);
-static tree cp_parser_new_initializer
+static VEC(tree,gc) *cp_parser_new_initializer
(cp_parser *);
static tree cp_parser_delete_expression
(cp_parser *);
@@ -4685,7 +4685,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
bool is_builtin_constant_p;
bool saved_integral_constant_expression_p = false;
bool saved_non_integral_constant_expression_p = false;
- tree args;
+ VEC(tree,gc) *args;
is_member_access = false;
@@ -4713,7 +4713,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
= saved_non_integral_constant_expression_p;
}
- if (args == error_mark_node)
+ if (args == NULL)
{
postfix_expression = error_mark_node;
break;
@@ -4726,6 +4726,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
"a function call"))
{
postfix_expression = error_mark_node;
+ release_tree_vector (args);
break;
}
@@ -4735,7 +4736,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
{
if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
{
- if (args)
+ if (!VEC_empty (tree, args))
{
koenig_p = true;
if (!any_type_dependent_arguments_p (args))
@@ -4749,7 +4750,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
/* We do not perform argument-dependent lookup if
normal lookup finds a non-function, in accordance
with the expected resolution of DR 218. */
- else if (args && is_overloaded_fn (postfix_expression))
+ else if (!VEC_empty (tree, args)
+ && is_overloaded_fn (postfix_expression))
{
tree fn = get_first_fn (postfix_expression);
@@ -4782,7 +4784,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|| any_type_dependent_arguments_p (args)))
{
postfix_expression
- = build_nt_call_list (postfix_expression, args);
+ = build_nt_call_vec (postfix_expression, args);
+ release_tree_vector (args);
break;
}
@@ -4790,7 +4793,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
{
postfix_expression
= (build_new_method_call
- (instance, fn, args, NULL_TREE,
+ (instance, fn, &args, NULL_TREE,
(idk == CP_ID_KIND_QUALIFIED
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
/*fn_p=*/NULL,
@@ -4798,7 +4801,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
}
else
postfix_expression
- = finish_call_expr (postfix_expression, args,
+ = finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
tf_warning_or_error);
@@ -4807,25 +4810,27 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
|| TREE_CODE (postfix_expression) == MEMBER_REF
|| TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
postfix_expression = (build_offset_ref_call_from_tree
- (postfix_expression, args));
+ (postfix_expression, &args));
else if (idk == CP_ID_KIND_QUALIFIED)
/* A call to a static class member, or a namespace-scope
function. */
postfix_expression
- = finish_call_expr (postfix_expression, args,
+ = finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/true,
koenig_p,
tf_warning_or_error);
else
/* All other function calls. */
postfix_expression
- = finish_call_expr (postfix_expression, args,
+ = finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
koenig_p,
tf_warning_or_error);
/* The POSTFIX_EXPRESSION is certainly no longer an id. */
idk = CP_ID_KIND_NONE;
+
+ release_tree_vector (args);
}
break;
@@ -5132,24 +5137,22 @@ cp_parser_postfix_dot_deref_expression (cp_parser *parser,
ALLOW_EXPANSION_P is true if this expression allows expansion of an
argument pack.
- Returns a TREE_LIST. The TREE_VALUE of each node is a
- representation of an assignment-expression. Note that a TREE_LIST
- is returned even if there is only a single expression in the list.
- error_mark_node is returned if the ( and or ) are
- missing. NULL_TREE is returned on no expressions. The parentheses
- are eaten. IS_ATTRIBUTE_LIST is true if this is really an attribute
- list being parsed. If NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P
- indicates whether or not all of the expressions in the list were
- constant. */
+ Returns a vector of trees. Each element is a representation of an
+ assignment-expression. NULL is returned if the ( and or ) are
+ missing. An empty, but allocated, vector is returned on no
+ expressions. The parentheses are eaten. IS_ATTRIBUTE_LIST is true
+ if this is really an attribute list being parsed. If
+ NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P indicates whether or
+ not all of the expressions in the list were constant. */
-static tree
+static VEC(tree,gc) *
cp_parser_parenthesized_expression_list (cp_parser* parser,
bool is_attribute_list,
bool cast_p,
bool allow_expansion_p,
bool *non_constant_p)
{
- tree expression_list = NULL_TREE;
+ VEC(tree,gc) *expression_list;
bool fold_expr_p = is_attribute_list;
tree identifier = NULL_TREE;
bool saved_greater_than_is_operator_p;
@@ -5159,7 +5162,9 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
*non_constant_p = false;
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
- return error_mark_node;
+ return NULL;
+
+ expression_list = make_tree_vector ();
/* Within a parenthesized expression, a `>' token is always
the greater-than operator. */
@@ -5228,7 +5233,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
expressions to the list, so that we can still tell if
the correct form for a parenthesized expression-list
is found. That gives better errors. */
- expression_list = tree_cons (NULL_TREE, expr, expression_list);
+ VEC_safe_push (tree, gc, expression_list, expr);
if (expr == error_mark_node)
goto skip_comma;
@@ -5264,17 +5269,15 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
{
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
- return error_mark_node;
+ return NULL;
}
}
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
- /* We built up the list in reverse order so we must reverse it now. */
- expression_list = nreverse (expression_list);
if (identifier)
- expression_list = tree_cons (NULL_TREE, identifier, expression_list);
+ VEC_safe_insert (tree, gc, expression_list, 0, identifier);
return expression_list;
}
@@ -5618,10 +5621,11 @@ static tree
cp_parser_new_expression (cp_parser* parser)
{
bool global_scope_p;
- tree placement;
+ VEC(tree,gc) *placement;
tree type;
- tree initializer;
+ VEC(tree,gc) *initializer;
tree nelts;
+ tree ret;
/* Look for the optional `::' operator. */
global_scope_p
@@ -5637,7 +5641,11 @@ cp_parser_new_expression (cp_parser* parser)
placement = cp_parser_new_placement (parser);
/* If that didn't work out, there's no new-placement. */
if (!cp_parser_parse_definitely (parser))
- placement = NULL_TREE;
+ {
+ if (placement != NULL)
+ release_tree_vector (placement);
+ placement = NULL;
+ }
/* If the next token is a `(', then we have a parenthesized
type-id. */
@@ -5673,16 +5681,25 @@ cp_parser_new_expression (cp_parser* parser)
|| cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
initializer = cp_parser_new_initializer (parser);
else
- initializer = NULL_TREE;
+ initializer = NULL;
/* A new-expression may not appear in an integral constant
expression. */
if (cp_parser_non_integral_constant_expression (parser, "%<new%>"))
- return error_mark_node;
+ ret = error_mark_node;
+ else
+ {
+ /* Create a representation of the new-expression. */
+ ret = build_new (&placement, type, nelts, &initializer, global_scope_p,
+ tf_warning_or_error);
+ }
- /* Create a representation of the new-expression. */
- return build_new (placement, type, nelts, initializer, global_scope_p,
- tf_warning_or_error);
+ if (placement != NULL)
+ release_tree_vector (placement);
+ if (initializer != NULL)
+ release_tree_vector (initializer);
+
+ return ret;
}
/* Parse a new-placement.
@@ -5692,10 +5709,10 @@ cp_parser_new_expression (cp_parser* parser)
Returns the same representation as for an expression-list. */
-static tree
+static VEC(tree,gc) *
cp_parser_new_placement (cp_parser* parser)
{
- tree expression_list;
+ VEC(tree,gc) *expression_list;
/* Parse the expression-list. */
expression_list = (cp_parser_parenthesized_expression_list
@@ -5885,28 +5902,26 @@ cp_parser_direct_new_declarator (cp_parser* parser)
( expression-list [opt] )
braced-init-list
- Returns a representation of the expression-list. If there is no
- expression-list, VOID_ZERO_NODE is returned. */
+ Returns a representation of the expression-list. */
-static tree
+static VEC(tree,gc) *
cp_parser_new_initializer (cp_parser* parser)
{
- tree expression_list;
+ VEC(tree,gc) *expression_list;
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
+ tree t;
bool expr_non_constant_p;
maybe_warn_cpp0x ("extended initializer lists");
- expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
- CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
- expression_list = build_tree_list (NULL_TREE, expression_list);
+ t = cp_parser_braced_list (parser, &expr_non_constant_p);
+ CONSTRUCTOR_IS_DIRECT_INIT (t) = 1;
+ expression_list = make_tree_vector_single (t);
}
else
expression_list = (cp_parser_parenthesized_expression_list
(parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
/*non_constant_p=*/NULL));
- if (!expression_list)
- expression_list = void_zero_node;
return expression_list;
}
@@ -9244,11 +9259,18 @@ cp_parser_mem_initializer (cp_parser* parser)
expression_list = build_tree_list (NULL_TREE, expression_list);
}
else
- expression_list
- = cp_parser_parenthesized_expression_list (parser, false,
- /*cast_p=*/false,
- /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+ {
+ VEC(tree,gc)* vec;
+ vec = cp_parser_parenthesized_expression_list (parser, false,
+ /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
+ /*non_constant_p=*/NULL);
+ if (vec == NULL)
+ return error_mark_node;
+ expression_list = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
+
if (expression_list == error_mark_node)
return error_mark_node;
if (!expression_list)
@@ -14606,10 +14628,17 @@ cp_parser_initializer (cp_parser* parser, bool* is_direct_init,
init = cp_parser_initializer_clause (parser, non_constant_p);
}
else if (token->type == CPP_OPEN_PAREN)
- init = cp_parser_parenthesized_expression_list (parser, false,
- /*cast_p=*/false,
- /*allow_expansion_p=*/true,
- non_constant_p);
+ {
+ VEC(tree,gc) *vec;
+ vec = cp_parser_parenthesized_expression_list (parser, false,
+ /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
+ non_constant_p);
+ if (vec == NULL)
+ return error_mark_node;
+ init = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
else if (token->type == CPP_OPEN_BRACE)
{
maybe_warn_cpp0x ("extended initializer lists");
@@ -16871,10 +16900,18 @@ cp_parser_attribute_list (cp_parser* parser)
/* If it's an `(', then parse the attribute arguments. */
if (token->type == CPP_OPEN_PAREN)
{
- arguments = cp_parser_parenthesized_expression_list
- (parser, true, /*cast_p=*/false,
- /*allow_expansion_p=*/false,
- /*non_constant_p=*/NULL);
+ VEC(tree,gc) *vec;
+ vec = cp_parser_parenthesized_expression_list
+ (parser, true, /*cast_p=*/false,
+ /*allow_expansion_p=*/false,
+ /*non_constant_p=*/NULL);
+ if (vec == NULL)
+ arguments = error_mark_node;
+ else
+ {
+ arguments = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
/* Save the arguments away. */
TREE_VALUE (attribute) = arguments;
}
@@ -18002,6 +18039,7 @@ cp_parser_simple_cast_expression (cp_parser *parser)
static tree
cp_parser_functional_cast (cp_parser* parser, tree type)
{
+ VEC(tree,gc) *vec;
tree expression_list;
tree cast;
bool nonconst_p;
@@ -18016,11 +18054,18 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
return finish_compound_literal (type, expression_list);
}
- expression_list
- = cp_parser_parenthesized_expression_list (parser, false,
- /*cast_p=*/true,
- /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+
+ vec = cp_parser_parenthesized_expression_list (parser, false,
+ /*cast_p=*/true,
+ /*allow_expansion_p=*/true,
+ /*non_constant_p=*/NULL);
+ if (vec == NULL)
+ expression_list = error_mark_node;
+ else
+ {
+ expression_list = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
cast = build_functional_cast (type, expression_list,
tf_warning_or_error);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 3ae2dd126bf..7f22332041a 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -118,8 +118,8 @@ static tree add_outermost_template_args (tree, tree);
static bool check_instantiated_args (tree, tree, tsubst_flags_t);
static int maybe_adjust_types_for_deduction (unification_kind_t, tree*, tree*,
tree);
-static int type_unification_real (tree, tree, tree, tree,
- int, unification_kind_t, int);
+static int type_unification_real (tree, tree, tree, const tree *,
+ unsigned int, int, unification_kind_t, int);
static void note_template_header (int);
static tree convert_nontype_argument_function (tree, tree);
static tree convert_nontype_argument (tree, tree);
@@ -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
@@ -4415,9 +4416,9 @@ convert_nontype_argument (tree type, tree expr)
For a non-type template-parameter of integral or enumeration type,
integral promotions (_conv.prom_) and integral conversions
(_conv.integral_) are applied. */
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
- if (!INTEGRAL_TYPE_P (expr_type))
+ if (!INTEGRAL_OR_ENUMERATION_TYPE_P (expr_type))
return error_mark_node;
expr = fold_decl_constant_value (expr);
@@ -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 ();
@@ -9930,16 +9934,29 @@ tsubst_qualified_id (tree qualified_id, tree args,
expr = name;
if (dependent_type_p (scope))
- return build_qualified_name (/*type=*/NULL_TREE,
- scope, expr,
- QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
+ {
+ tree type = NULL_TREE;
+ if (DECL_P (expr) && !dependent_scope_p (scope))
+ type = TREE_TYPE (expr);
+ return build_qualified_name (type, scope, expr,
+ QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
+ }
if (!BASELINK_P (name) && !DECL_P (expr))
{
if (TREE_CODE (expr) == BIT_NOT_EXPR)
- /* If this were actually a destructor call, it would have been
- parsed as such by the parser. */
- expr = error_mark_node;
+ {
+ /* A BIT_NOT_EXPR is used to represent a destructor. */
+ if (!check_dtor_name (scope, TREE_OPERAND (expr, 0)))
+ {
+ error ("qualifying type %qT does not match destructor name ~%qT",
+ scope, TREE_OPERAND (expr, 0));
+ expr = error_mark_node;
+ }
+ else
+ expr = lookup_qualified_name (scope, complete_dtor_identifier,
+ /*is_type_p=*/0, false);
+ }
else
expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
if (TREE_CODE (TREE_CODE (expr) == TEMPLATE_DECL
@@ -11424,24 +11441,54 @@ tsubst_copy_and_build (tree t,
case NEW_EXPR:
{
+ tree placement = RECUR (TREE_OPERAND (t, 0));
tree init = RECUR (TREE_OPERAND (t, 3));
+ VEC(tree,gc) *placement_vec;
+ VEC(tree,gc) *init_vec;
+ tree ret;
- if (TREE_OPERAND (t, 3) && !init)
- /* If there was an initializer in the original tree, but
- it instantiated to an empty list, then we should pass on
- VOID_ZERO_NODE to tell build_new that it was an empty
- initializer () rather than no initializer. This can only
- happen when the initializer is a pack expansion whose
- parameter packs are of length zero. */
- init = void_zero_node;
+ if (placement == NULL_TREE)
+ placement_vec = NULL;
+ else
+ {
+ placement_vec = make_tree_vector ();
+ for (; placement != NULL_TREE; placement = TREE_CHAIN (placement))
+ VEC_safe_push (tree, gc, placement_vec, TREE_VALUE (placement));
+ }
- return build_new
- (RECUR (TREE_OPERAND (t, 0)),
- RECUR (TREE_OPERAND (t, 1)),
- RECUR (TREE_OPERAND (t, 2)),
- init,
- NEW_EXPR_USE_GLOBAL (t),
- complain);
+ /* If there was an initializer in the original tree, but it
+ instantiated to an empty list, then we should pass a
+ non-NULL empty vector to tell build_new that it was an
+ empty initializer() rather than no initializer. This can
+ only happen when the initializer is a pack expansion whose
+ parameter packs are of length zero. */
+ if (init == NULL_TREE && TREE_OPERAND (t, 3) == NULL_TREE)
+ init_vec = NULL;
+ else
+ {
+ init_vec = make_tree_vector ();
+ if (init == void_zero_node)
+ gcc_assert (init_vec != NULL);
+ else
+ {
+ for (; init != NULL_TREE; init = TREE_CHAIN (init))
+ VEC_safe_push (tree, gc, init_vec, TREE_VALUE (init));
+ }
+ }
+
+ ret = build_new (&placement_vec,
+ RECUR (TREE_OPERAND (t, 1)),
+ RECUR (TREE_OPERAND (t, 2)),
+ &init_vec,
+ NEW_EXPR_USE_GLOBAL (t),
+ complain);
+
+ if (placement_vec != NULL)
+ release_tree_vector (placement_vec);
+ if (init_vec != NULL)
+ release_tree_vector (init_vec);
+
+ return ret;
}
case DELETE_EXPR:
@@ -11459,9 +11506,11 @@ tsubst_copy_and_build (tree t,
case CALL_EXPR:
{
tree function;
- tree call_args;
+ VEC(tree,gc) *call_args;
+ unsigned int nargs, i;
bool qualified_p;
bool koenig_p;
+ tree ret;
function = CALL_EXPR_FN (t);
/* When we parsed the expression, we determined whether or
@@ -11496,8 +11545,40 @@ tsubst_copy_and_build (tree t,
qualified_p = true;
}
- /* FIXME: Rewrite this so as not to construct an arglist. */
- call_args = RECUR (CALL_EXPR_ARGS (t));
+ nargs = call_expr_nargs (t);
+ call_args = make_tree_vector ();
+ for (i = 0; i < nargs; ++i)
+ {
+ tree arg = CALL_EXPR_ARG (t, i);
+
+ if (!PACK_EXPANSION_P (arg))
+ VEC_safe_push (tree, gc, call_args,
+ RECUR (CALL_EXPR_ARG (t, i)));
+ else
+ {
+ /* Expand the pack expansion and push each entry onto
+ CALL_ARGS. */
+ arg = tsubst_pack_expansion (arg, args, complain, in_decl);
+ if (TREE_CODE (arg) == TREE_VEC)
+ {
+ unsigned int len, j;
+
+ len = TREE_VEC_LENGTH (arg);
+ for (j = 0; j < len; ++j)
+ {
+ tree value = TREE_VEC_ELT (arg, j);
+ if (value != NULL_TREE)
+ value = convert_from_reference (value);
+ VEC_safe_push (tree, gc, call_args, value);
+ }
+ }
+ else
+ {
+ /* A partial substitution. Add one entry. */
+ VEC_safe_push (tree, gc, call_args, arg);
+ }
+ }
+ }
/* We do not perform argument-dependent lookup if normal
lookup finds a non-function, in accordance with the
@@ -11518,6 +11599,7 @@ tsubst_copy_and_build (tree t,
if (TREE_CODE (function) == IDENTIFIER_NODE)
{
unqualified_name_lookup_error (function);
+ release_tree_vector (call_args);
return error_mark_node;
}
@@ -11526,27 +11608,32 @@ tsubst_copy_and_build (tree t,
mark_used (function);
if (TREE_CODE (function) == OFFSET_REF)
- return build_offset_ref_call_from_tree (function, call_args);
- if (TREE_CODE (function) == COMPONENT_REF)
+ ret = build_offset_ref_call_from_tree (function, &call_args);
+ else if (TREE_CODE (function) == COMPONENT_REF)
{
if (!BASELINK_P (TREE_OPERAND (function, 1)))
- return finish_call_expr (function, call_args,
+ ret = finish_call_expr (function, &call_args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
complain);
else
- return (build_new_method_call
+ ret = (build_new_method_call
(TREE_OPERAND (function, 0),
TREE_OPERAND (function, 1),
- call_args, NULL_TREE,
+ &call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
/*fn_p=*/NULL,
complain));
}
- return finish_call_expr (function, call_args,
- /*disallow_virtual=*/qualified_p,
- koenig_p,
- complain);
+ else
+ ret = finish_call_expr (function, &call_args,
+ /*disallow_virtual=*/qualified_p,
+ koenig_p,
+ complain);
+
+ release_tree_vector (call_args);
+
+ return ret;
}
case COND_EXPR:
@@ -12087,7 +12174,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 ();
@@ -12106,9 +12193,10 @@ instantiate_template (tree tmpl, tree targ_ptr, tsubst_flags_t complain)
return fndecl;
}
-/* The FN is a TEMPLATE_DECL for a function. The ARGS are the
- arguments that are being used when calling it. TARGS is a vector
- into which the deduced template arguments are placed.
+/* The FN is a TEMPLATE_DECL for a function. ARGS is an array with
+ NARGS elements of the arguments that are being used when calling
+ it. TARGS is a vector into which the deduced template arguments
+ are placed.
Return zero for success, 2 for an incomplete match that doesn't resolve
all the types, and 1 for complete failure. An error message will be
@@ -12140,7 +12228,8 @@ int
fn_type_unification (tree fn,
tree explicit_targs,
tree targs,
- tree args,
+ const tree *args,
+ unsigned int nargs,
tree return_type,
unification_kind_t strict,
int flags)
@@ -12257,8 +12346,14 @@ fn_type_unification (tree fn,
if (return_type)
{
+ tree *new_args;
+
parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms);
- args = tree_cons (NULL_TREE, return_type, args);
+ new_args = XALLOCAVEC (tree, nargs + 1);
+ new_args[0] = return_type;
+ memcpy (new_args + 1, args, nargs * sizeof (tree));
+ args = new_args;
+ ++nargs;
}
/* We allow incomplete unification without an error message here
@@ -12266,7 +12361,7 @@ fn_type_unification (tree fn,
callers must be ready to deal with unification failures in any
event. */
result = type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
- targs, parms, args, /*subr=*/0,
+ targs, parms, args, nargs, /*subr=*/0,
strict, flags);
if (result == 0 && incomplete_argument_packs_p)
@@ -12331,14 +12426,14 @@ fn_type_unification (tree fn,
parameters are used in non-deduced contexts. */
if (strict == DEDUCE_EXACT)
{
+ unsigned int i;
+
tree sarg
= skip_artificial_parms_for (fn, TYPE_ARG_TYPES (substed));
- tree arg = args;
if (return_type)
sarg = tree_cons (NULL_TREE, TREE_TYPE (substed), sarg);
- for (; arg && sarg;
- arg = TREE_CHAIN (arg), sarg = TREE_CHAIN (sarg))
- if (!same_type_p (TREE_VALUE (arg), TREE_VALUE (sarg)))
+ for (i = 0; i < nargs && sarg; ++i, sarg = TREE_CHAIN (sarg))
+ if (!same_type_p (args[i], TREE_VALUE (sarg)))
return 1;
}
}
@@ -12453,7 +12548,8 @@ static int
type_unification_real (tree tparms,
tree targs,
tree xparms,
- tree xargs,
+ const tree *xargs,
+ unsigned int xnargs,
int subr,
unification_kind_t strict,
int flags)
@@ -12463,11 +12559,13 @@ type_unification_real (tree tparms,
int ntparms = TREE_VEC_LENGTH (tparms);
int sub_strict;
int saw_undeduced = 0;
- tree parms, args;
+ tree parms;
+ const tree *args;
+ unsigned int nargs;
+ unsigned int ia;
gcc_assert (TREE_CODE (tparms) == TREE_VEC);
gcc_assert (xparms == NULL_TREE || TREE_CODE (xparms) == TREE_LIST);
- gcc_assert (!xargs || TREE_CODE (xargs) == TREE_LIST);
gcc_assert (ntparms > 0);
switch (strict)
@@ -12492,17 +12590,19 @@ type_unification_real (tree tparms,
again:
parms = xparms;
args = xargs;
+ nargs = xnargs;
+ ia = 0;
while (parms && parms != void_list_node
- && args && args != void_list_node)
+ && ia < nargs)
{
if (TREE_CODE (TREE_VALUE (parms)) == TYPE_PACK_EXPANSION)
break;
parm = TREE_VALUE (parms);
parms = TREE_CHAIN (parms);
- arg = TREE_VALUE (args);
- args = TREE_CHAIN (args);
+ arg = args[ia];
+ ++ia;
arg_expr = NULL;
if (arg == error_mark_node)
@@ -12581,20 +12681,11 @@ type_unification_real (tree tparms,
/* Unify the remaining arguments with the pack expansion type. */
tree argvec;
tree parmvec = make_tree_vec (1);
- int len = 0;
- tree t;
- /* Count the number of arguments that remain. */
- for (t = args; t && t != void_list_node; t = TREE_CHAIN (t))
- len++;
-
/* Allocate a TREE_VEC and copy in all of the arguments */
- argvec = make_tree_vec (len);
- for (i = 0; args && args != void_list_node; args = TREE_CHAIN (args))
- {
- TREE_VEC_ELT (argvec, i) = TREE_VALUE (args);
- ++i;
- }
+ argvec = make_tree_vec (nargs - ia);
+ for (i = 0; ia < nargs; ++ia, ++i)
+ TREE_VEC_ELT (argvec, i) = args[ia];
/* Copy the parameter into parmvec. */
TREE_VEC_ELT (parmvec, 0) = TREE_VALUE (parms);
@@ -12608,7 +12699,7 @@ type_unification_real (tree tparms,
/* Fail if we've reached the end of the parm list, and more args
are present, and the parm list isn't variadic. */
- if (args && args != void_list_node && parms == void_list_node)
+ if (ia < nargs && parms == void_list_node)
return 1;
/* Fail if parms are left and they don't have default values. */
if (parms && parms != void_list_node
@@ -13591,7 +13682,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
@@ -13890,26 +13981,42 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
case METHOD_TYPE:
case FUNCTION_TYPE:
- if (TREE_CODE (arg) != TREE_CODE (parm))
- return 1;
+ {
+ unsigned int nargs;
+ tree *args;
+ tree a;
+ unsigned int i;
- /* CV qualifications for methods can never be deduced, they must
- match exactly. We need to check them explicitly here,
- because type_unification_real treats them as any other
- cv-qualified parameter. */
- if (TREE_CODE (parm) == METHOD_TYPE
- && (!check_cv_quals_for_unify
- (UNIFY_ALLOW_NONE,
- TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))),
- TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm))))))
- return 1;
+ if (TREE_CODE (arg) != TREE_CODE (parm))
+ return 1;
- if (unify (tparms, targs, TREE_TYPE (parm),
- TREE_TYPE (arg), UNIFY_ALLOW_NONE))
- return 1;
- return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
- TYPE_ARG_TYPES (arg), 1, DEDUCE_EXACT,
- LOOKUP_NORMAL);
+ /* CV qualifications for methods can never be deduced, they must
+ match exactly. We need to check them explicitly here,
+ because type_unification_real treats them as any other
+ cv-qualified parameter. */
+ if (TREE_CODE (parm) == METHOD_TYPE
+ && (!check_cv_quals_for_unify
+ (UNIFY_ALLOW_NONE,
+ TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (arg))),
+ TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (parm))))))
+ return 1;
+
+ if (unify (tparms, targs, TREE_TYPE (parm),
+ TREE_TYPE (arg), UNIFY_ALLOW_NONE))
+ return 1;
+
+ nargs = list_length (TYPE_ARG_TYPES (arg));
+ args = XALLOCAVEC (tree, nargs);
+ for (a = TYPE_ARG_TYPES (arg), i = 0;
+ a != NULL_TREE && a != void_list_node;
+ a = TREE_CHAIN (a), ++i)
+ args[i] = TREE_VALUE (a);
+ nargs = i;
+
+ return type_unification_real (tparms, targs, TYPE_ARG_TYPES (parm),
+ args, nargs, 1, DEDUCE_EXACT,
+ LOOKUP_NORMAL);
+ }
case OFFSET_TYPE:
/* Unify a pointer to member with a pointer to member function, which
@@ -14463,6 +14570,9 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
tree targs = make_tree_vec (ntparms);
tree decl_type;
tree decl_arg_types;
+ tree *args;
+ unsigned int nargs, ix;
+ tree arg;
/* Substitute the explicit template arguments into the type of DECL.
The call to fn_type_unification will handle substitution into the
@@ -14497,8 +14607,15 @@ get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
decl_arg_types = skip_artificial_parms_for (decl,
TYPE_ARG_TYPES (decl_type));
+ nargs = list_length (decl_arg_types);
+ args = XALLOCAVEC (tree, nargs);
+ for (arg = decl_arg_types, ix = 0;
+ arg != NULL_TREE && arg != void_list_node;
+ arg = TREE_CHAIN (arg), ++ix)
+ args[ix] = TREE_VALUE (arg);
+
if (fn_type_unification (fn, explicit_args, targs,
- decl_arg_types,
+ args, ix,
(check_rettype || DECL_CONV_FN_P (fn)
? TREE_TYPE (decl_type) : NULL_TREE),
DEDUCE_EXACT, LOOKUP_NORMAL))
@@ -16047,7 +16164,7 @@ current_instantiation (void)
static int
invalid_nontype_parm_type_p (tree type, tsubst_flags_t complain)
{
- if (INTEGRAL_TYPE_P (type))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (type))
return 0;
else if (POINTER_TYPE_P (type))
return 0;
@@ -16574,19 +16691,18 @@ type_dependent_expression_p_push (tree expr)
return b;
}
-/* Returns TRUE if ARGS (a TREE_LIST of arguments to a function call)
- contains a type-dependent expression. */
+/* Returns TRUE if ARGS contains a type-dependent expression. */
bool
-any_type_dependent_arguments_p (const_tree args)
+any_type_dependent_arguments_p (const VEC(tree,gc) *args)
{
- while (args)
- {
- tree arg = TREE_VALUE (args);
+ unsigned int i;
+ tree arg;
+ for (i = 0; VEC_iterate (tree, args, i, arg); ++i)
+ {
if (type_dependent_expression_p (arg))
return true;
- args = TREE_CHAIN (args);
}
return false;
}
@@ -17006,22 +17122,22 @@ build_non_dependent_expr (tree expr)
return build1 (NON_DEPENDENT_EXPR, non_reference (TREE_TYPE (expr)), expr);
}
-/* ARGS is a TREE_LIST of expressions as arguments to a function call.
- Return a new TREE_LIST with the various arguments replaced with
- equivalent non-dependent expressions. */
+/* ARGS is a vector of expressions as arguments to a function call.
+ Replace the arguments with equivalent non-dependent expressions.
+ This modifies ARGS in place. */
-tree
-build_non_dependent_args (tree args)
+void
+make_args_non_dependent (VEC(tree,gc) *args)
{
- tree a;
- tree new_args;
+ unsigned int ix;
+ tree arg;
- new_args = NULL_TREE;
- for (a = args; a; a = TREE_CHAIN (a))
- new_args = tree_cons (NULL_TREE,
- build_non_dependent_expr (TREE_VALUE (a)),
- new_args);
- return nreverse (new_args);
+ for (ix = 0; VEC_iterate (tree, args, ix, arg); ++ix)
+ {
+ tree newarg = build_non_dependent_expr (arg);
+ if (newarg != arg)
+ VEC_replace (tree, args, ix, newarg);
+ }
}
/* Returns a type which represents 'auto'. We use a TEMPLATE_TYPE_PARM
@@ -17078,7 +17194,8 @@ listify_autos (tree type, tree auto_node)
tree
do_auto_deduction (tree type, tree init, tree auto_node)
{
- tree parms, args, tparms, targs;
+ tree parms, tparms, targs;
+ tree args[1];
int val;
/* [dcl.spec.auto]: Obtain P from T by replacing the occurrences of auto
@@ -17089,12 +17206,12 @@ do_auto_deduction (tree type, tree init, tree auto_node)
type = listify_autos (type, auto_node);
parms = build_tree_list (NULL_TREE, type);
- args = build_tree_list (NULL_TREE, init);
+ args[0] = init;
tparms = make_tree_vec (1);
targs = make_tree_vec (1);
TREE_VEC_ELT (tparms, 0)
= build_tree_list (NULL_TREE, TYPE_NAME (auto_node));
- val = type_unification_real (tparms, targs, parms, args, 0,
+ val = type_unification_real (tparms, targs, parms, args, 1, 0,
DEDUCE_CALL, LOOKUP_NORMAL);
if (val > 0)
{
@@ -17161,33 +17278,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))
{
@@ -17198,9 +17390,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/semantics.c b/gcc/cp/semantics.c
index d48db9c9cce..85eb6bdf004 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1666,11 +1666,10 @@ finish_qualified_id_expr (tree qualifying_class,
fns = BASELINK_FUNCTIONS (expr);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
fns = TREE_OPERAND (fns, 0);
- /* If so, the expression may be relative to the current
- class. */
+ /* If so, the expression may be relative to 'this'. */
if (!shared_member_p (fns)
- && current_class_type
- && DERIVED_FROM_P (qualifying_class, current_class_type))
+ && current_class_ref
+ && DERIVED_FROM_P (qualifying_class, TREE_TYPE (current_class_ref)))
expr = (build_class_member_access_expr
(maybe_dummy_object (qualifying_class, NULL),
expr,
@@ -1823,7 +1822,7 @@ stmt_expr_value_expr (tree stmt_expr)
resolution. */
tree
-perform_koenig_lookup (tree fn, tree args)
+perform_koenig_lookup (tree fn, VEC(tree,gc) *args)
{
tree identifier = NULL_TREE;
tree functions = NULL_TREE;
@@ -1868,7 +1867,8 @@ perform_koenig_lookup (tree fn, tree args)
return fn;
}
-/* Generate an expression for `FN (ARGS)'.
+/* Generate an expression for `FN (ARGS)'. This may change the
+ contents of ARGS.
If DISALLOW_VIRTUAL is true, the call to FN will be not generated
as a virtual call, even if FN is virtual. (This flag is set when
@@ -1879,29 +1879,26 @@ perform_koenig_lookup (tree fn, tree args)
Returns code for the call. */
tree
-finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p,
- tsubst_flags_t complain)
+finish_call_expr (tree fn, VEC(tree,gc) **args, bool disallow_virtual,
+ bool koenig_p, tsubst_flags_t complain)
{
tree result;
tree orig_fn;
- tree orig_args;
+ VEC(tree,gc) *orig_args = NULL;
- if (fn == error_mark_node || args == error_mark_node)
+ if (fn == error_mark_node)
return error_mark_node;
- /* ARGS should be a list of arguments. */
- gcc_assert (!args || TREE_CODE (args) == TREE_LIST);
gcc_assert (!TYPE_P (fn));
orig_fn = fn;
- orig_args = args;
if (processing_template_decl)
{
if (type_dependent_expression_p (fn)
- || any_type_dependent_arguments_p (args))
+ || any_type_dependent_arguments_p (*args))
{
- result = build_nt_call_list (fn, args);
+ result = build_nt_call_vec (fn, *args);
KOENIG_LOOKUP_P (result) = koenig_p;
if (cfun)
{
@@ -1919,11 +1916,12 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p,
}
return result;
}
+ orig_args = make_tree_vector_copy (*args);
if (!BASELINK_P (fn)
&& TREE_CODE (fn) != PSEUDO_DTOR_EXPR
&& TREE_TYPE (fn) != unknown_type_node)
fn = build_non_dependent_expr (fn);
- args = build_non_dependent_args (orig_args);
+ make_args_non_dependent (*args);
}
if (is_overloaded_fn (fn))
@@ -1972,7 +1970,11 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p,
if (processing_template_decl)
{
if (type_dependent_expression_p (object))
- return build_nt_call_list (orig_fn, orig_args);
+ {
+ tree ret = build_nt_call_vec (orig_fn, orig_args);
+ release_tree_vector (orig_args);
+ return ret;
+ }
object = build_non_dependent_expr (object);
}
@@ -1988,15 +1990,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p,
if (TREE_CODE (fn) == FUNCTION_DECL
&& (DECL_BUILT_IN_CLASS (fn) == BUILT_IN_NORMAL
|| DECL_BUILT_IN_CLASS (fn) == BUILT_IN_MD))
- {
- VEC(tree,gc)* vec = VEC_alloc (tree, gc, list_length (args));
- tree p;
-
- for (p = args; p != NULL_TREE; p = TREE_CHAIN (p))
- VEC_quick_push (tree, vec, TREE_VALUE (p));
- result = resolve_overloaded_builtin (fn, vec);
- VEC_free (tree, gc, vec);
- }
+ result = resolve_overloaded_builtin (fn, *args);
if (!result)
/* A call to a namespace-scope function. */
@@ -2004,7 +1998,7 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p,
}
else if (TREE_CODE (fn) == PSEUDO_DTOR_EXPR)
{
- if (args)
+ if (!VEC_empty (tree, *args))
error ("arguments to destructor are not allowed");
/* Mark the pseudo-destructor call as having side-effects so
that we do not issue warnings about its use. */
@@ -2016,18 +2010,19 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual, bool koenig_p,
else if (CLASS_TYPE_P (TREE_TYPE (fn)))
/* If the "function" is really an object of class type, it might
have an overloaded `operator ()'. */
- result = build_new_op (CALL_EXPR, LOOKUP_NORMAL, fn, args, NULL_TREE,
- /*overloaded_p=*/NULL, complain);
+ result = build_op_call (fn, args, complain);
if (!result)
/* A call where the function is unknown. */
- result = cp_build_function_call (fn, args, complain);
+ result = cp_build_function_call_vec (fn, args, complain);
if (processing_template_decl)
{
- result = build_call_list (TREE_TYPE (result), orig_fn, orig_args);
+ result = build_call_vec (TREE_TYPE (result), orig_fn, orig_args);
KOENIG_LOOKUP_P (result) = koenig_p;
+ release_tree_vector (orig_args);
}
+
return result;
}
@@ -2873,16 +2868,16 @@ finish_id_expression (tree id_expression,
done, address_p,
template_p,
template_arg_p);
- else if (dependent_scope_p (scope))
- decl = build_qualified_name (/*type=*/NULL_TREE,
- scope,
- id_expression,
- template_p);
- else if (DECL_P (decl))
- decl = build_qualified_name (TREE_TYPE (decl),
- scope,
- id_expression,
- template_p);
+ else
+ {
+ tree type = NULL_TREE;
+ if (DECL_P (decl) && !dependent_scope_p (scope))
+ type = TREE_TYPE (decl);
+ decl = build_qualified_name (type,
+ scope,
+ id_expression,
+ template_p);
+ }
}
if (TREE_TYPE (decl))
decl = convert_from_reference (decl);
@@ -3275,8 +3270,10 @@ expand_or_defer_fn (tree fn)
/* If the user wants us to keep all inline functions, then mark
this function as needed so that finish_file will make sure to
- output it later. */
- if (flag_keep_inline_functions && DECL_DECLARED_INLINE_P (fn))
+ output it later. Similarly, all dllexport'd functions must
+ be emitted; there may be callers in other DLLs. */
+ if ((flag_keep_inline_functions && DECL_DECLARED_INLINE_P (fn))
+ || lookup_attribute ("dllexport", DECL_ATTRIBUTES (fn)))
mark_needed (fn);
}
@@ -3426,18 +3423,23 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
if (need_default_ctor
|| (need_copy_ctor && !TYPE_HAS_TRIVIAL_INIT_REF (type)))
{
+ VEC(tree,gc) *vec;
+
if (need_default_ctor)
- t = NULL;
+ vec = NULL;
else
{
t = build_int_cst (build_pointer_type (type), 0);
t = build1 (INDIRECT_REF, type, t);
- t = build_tree_list (NULL, t);
+ vec = make_tree_vector_single (t);
}
t = build_special_member_call (NULL_TREE, complete_ctor_identifier,
- t, type, LOOKUP_NORMAL,
+ &vec, type, LOOKUP_NORMAL,
tf_warning_or_error);
+ if (vec != NULL)
+ release_tree_vector (vec);
+
if (targetm.cxx.cdtor_returns_this () || errorcount)
/* Because constructors and destructors return this,
the call will have been cast to "void". Remove the
@@ -3475,12 +3477,15 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
if (need_copy_assignment && !TYPE_HAS_TRIVIAL_ASSIGN_REF (type))
{
+ VEC(tree,gc) *vec;
+
t = build_int_cst (build_pointer_type (type), 0);
t = build1 (INDIRECT_REF, type, t);
+ vec = make_tree_vector_single (t);
t = build_special_member_call (t, ansi_assopname (NOP_EXPR),
- build_tree_list (NULL, t),
- type, LOOKUP_NORMAL,
+ &vec, type, LOOKUP_NORMAL,
tf_warning_or_error);
+ release_tree_vector (vec);
/* We'll have called convert_from_reference on the call, which
may well have added an indirect_ref. It's unneeded here,
@@ -4436,7 +4441,9 @@ void
finish_omp_barrier (void)
{
tree fn = built_in_decls[BUILT_IN_GOMP_BARRIER];
- tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error);
+ VEC(tree,gc) *vec = make_tree_vector ();
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -4444,7 +4451,9 @@ void
finish_omp_flush (void)
{
tree fn = built_in_decls[BUILT_IN_SYNCHRONIZE];
- tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error);
+ VEC(tree,gc) *vec = make_tree_vector ();
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ release_tree_vector (vec);
finish_expr_stmt (stmt);
}
@@ -4452,7 +4461,9 @@ void
finish_omp_taskwait (void)
{
tree fn = built_in_decls[BUILT_IN_GOMP_TASKWAIT];
- tree stmt = finish_call_expr (fn, NULL, false, false, tf_warning_or_error);
+ VEC(tree,gc) *vec = make_tree_vector ();
+ tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
+ release_tree_vector (vec);
finish_expr_stmt (stmt);
}
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 9cc767da07c..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);
- return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), cp_type_quals (t));
+ 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);
+
+ 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,
@@ -1200,7 +1292,8 @@ get_first_fn (tree from)
{
gcc_assert (is_overloaded_fn (from));
/* A baselink is also considered an overloaded function. */
- if (TREE_CODE (from) == COMPONENT_REF)
+ if (TREE_CODE (from) == OFFSET_REF
+ || TREE_CODE (from) == COMPONENT_REF)
from = TREE_OPERAND (from, 1);
if (BASELINK_P (from))
from = BASELINK_FUNCTIONS (from);
@@ -1264,10 +1357,15 @@ cxx_printable_name_internal (tree decl, int v, bool translate)
if (current_function_decl != NULL_TREE)
{
- if (uid_ring[ring_counter] == DECL_UID (current_function_decl))
- ring_counter += 1;
- if (ring_counter == PRINT_RING_SIZE)
- ring_counter = 0;
+ /* There may be both translated and untranslated versions of the
+ name cached. */
+ for (i = 0; i < 2; i++)
+ {
+ if (uid_ring[ring_counter] == DECL_UID (current_function_decl))
+ ring_counter += 1;
+ if (ring_counter == PRINT_RING_SIZE)
+ ring_counter = 0;
+ }
gcc_assert (uid_ring[ring_counter] != DECL_UID (current_function_decl));
}
@@ -1713,9 +1811,9 @@ build_min_non_dep (enum tree_code code, tree non_dep, ...)
built. */
tree
-build_min_non_dep_call_list (tree non_dep, tree fn, tree arglist)
+build_min_non_dep_call_vec (tree non_dep, tree fn, VEC(tree,gc) *argvec)
{
- tree t = build_nt_call_list (fn, arglist);
+ tree t = build_nt_call_vec (fn, argvec);
TREE_TYPE (t) = TREE_TYPE (non_dep);
TREE_SIDE_EFFECTS (t) = TREE_SIDE_EFFECTS (non_dep);
return t;
@@ -2150,7 +2248,7 @@ pod_type_p (const_tree t)
if (t == error_mark_node)
return 1;
- if (INTEGRAL_TYPE_P (t))
+ if (INTEGRAL_OR_ENUMERATION_TYPE_P (t))
return 1; /* integral, character or enumeral type */
if (FLOAT_TYPE_P (t))
return 1;
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 1cc9c837cb3..3001cba7127 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -48,7 +48,7 @@ along with GCC; see the file COPYING3. If not see
static tree pfn_from_ptrmemfunc (tree);
static tree delta_from_ptrmemfunc (tree);
static tree convert_for_assignment (tree, tree, const char *, tree, int,
- tsubst_flags_t);
+ tsubst_flags_t, int);
static tree cp_pointer_int_sum (enum tree_code, tree, tree);
static tree rationalize_conditional_expr (enum tree_code, tree,
tsubst_flags_t);
@@ -61,7 +61,7 @@ static void casts_away_constness_r (tree *, tree *);
static bool casts_away_constness (tree, tree);
static void maybe_warn_about_returning_address_of_local (tree);
static tree lookup_destructor (tree, tree, tree);
-static int convert_arguments (int, tree *, tree, tree, tree, int,
+static int convert_arguments (tree, VEC(tree,gc) **, tree, int,
tsubst_flags_t);
/* Do `exp = require_complete_type (exp);' to make sure exp
@@ -260,6 +260,19 @@ cp_common_type (tree t1, tree t2)
enum tree_code code2 = TREE_CODE (t2);
tree attributes;
+ /* In what follows, we slightly generalize the rules given in [expr] so
+ as to deal with `long long' and `complex'. First, merge the
+ attributes. */
+ attributes = (*targetm.merge_type_attributes) (t1, t2);
+
+ if (SCOPED_ENUM_P (t1) || SCOPED_ENUM_P (t2))
+ {
+ if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+ return build_type_attribute_variant (t1, attributes);
+ else
+ return NULL_TREE;
+ }
+
/* FIXME: Attributes. */
gcc_assert (ARITHMETIC_TYPE_P (t1)
|| TREE_CODE (t1) == VECTOR_TYPE
@@ -268,11 +281,6 @@ cp_common_type (tree t1, tree t2)
|| TREE_CODE (t2) == VECTOR_TYPE
|| UNSCOPED_ENUM_P (t2));
- /* In what follows, we slightly generalize the rules given in [expr] so
- as to deal with `long long' and `complex'. First, merge the
- attributes. */
- attributes = (*targetm.merge_type_attributes) (t1, t2);
-
/* If one type is complex, form the common type of the non-complex
components, then make that complex. Use T1 or T2 if it is the
required type. */
@@ -1699,10 +1707,14 @@ decay_conversion (tree exp)
tree
default_conversion (tree exp)
{
+ /* Check for target-specific promotions. */
+ tree promoted_type = targetm.promoted_type (TREE_TYPE (exp));
+ if (promoted_type)
+ exp = cp_convert (promoted_type, exp);
/* Perform the integral promotions first so that bitfield
expressions (which may promote to "int", even if the bitfield is
declared "unsigned") are promoted correctly. */
- if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp)))
+ else if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (exp)))
exp = perform_integral_promotions (exp);
/* Perform the other conversions. */
exp = decay_conversion (exp);
@@ -2482,12 +2494,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)
@@ -2862,38 +2870,57 @@ tree
build_function_call_vec (tree function, VEC(tree,gc) *params,
VEC(tree,gc) *origtypes ATTRIBUTE_UNUSED)
{
- tree p;
- tree *pp;
- unsigned int i;
- tree t;
+ VEC(tree,gc) *orig_params = params;
+ tree ret = cp_build_function_call_vec (function, &params,
+ tf_warning_or_error);
- /* FIXME: Should just change cp_build_function_call to use a
- VEC. */
- p = NULL_TREE;
- pp = &p;
- for (i = 0; VEC_iterate (tree, params, i, t); ++i)
- {
- *pp = build_tree_list (NULL, t);
- pp = &TREE_CHAIN (*pp);
- }
- return cp_build_function_call (function, p, tf_warning_or_error);
+ /* cp_build_function_call_vec can reallocate PARAMS by adding
+ default arguments. That should never happen here. Verify
+ that. */
+ gcc_assert (params == orig_params);
+
+ return ret;
}
+/* Build a function call using a tree list of arguments. */
+
tree
cp_build_function_call (tree function, tree params, tsubst_flags_t complain)
{
+ VEC(tree,gc) *vec;
+ tree ret;
+
+ vec = make_tree_vector ();
+ for (; params != NULL_TREE; params = TREE_CHAIN (params))
+ VEC_safe_push (tree, gc, vec, TREE_VALUE (params));
+ ret = cp_build_function_call_vec (function, &vec, complain);
+ release_tree_vector (vec);
+ return ret;
+}
+
+/* Build a function call using a vector of arguments. PARAMS may be
+ NULL if there are no parameters. This changes the contents of
+ PARAMS. */
+
+tree
+cp_build_function_call_vec (tree function, VEC(tree,gc) **params,
+ tsubst_flags_t complain)
+{
tree fntype, fndecl;
tree name = NULL_TREE;
int is_method;
tree original = function;
- int nargs, parm_types_len;
+ int nargs;
tree *argarray;
tree parm_types;
+ VEC(tree,gc) *allocated = NULL;
+ tree ret;
/* For Objective-C, convert any calls via a cast to OBJC_TYPE_REF
expressions, like those used for ObjC messenger dispatches. */
- if (params != NULL_TREE)
- function = objc_rewrite_function_call (function, TREE_VALUE (params));
+ if (params != NULL && !VEC_empty (tree, *params))
+ function = objc_rewrite_function_call (function,
+ VEC_index (tree, *params, 0));
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs, since FUNCTION is used in non-lvalue context. */
@@ -2953,57 +2980,55 @@ cp_build_function_call (tree function, tree params, tsubst_flags_t complain)
fntype = TREE_TYPE (fntype);
parm_types = TYPE_ARG_TYPES (fntype);
- /* Allocate storage for converted arguments. */
- parm_types_len = list_length (parm_types);
- nargs = list_length (params);
- if (parm_types_len > nargs)
- nargs = parm_types_len;
- argarray = (tree *) alloca (nargs * sizeof (tree));
-
- /* Convert the parameters to the types declared in the
- function prototype, or apply default promotions. */
- nargs = convert_arguments (nargs, argarray, parm_types,
- params, fndecl, LOOKUP_NORMAL,
- complain);
+ if (params == NULL)
+ {
+ allocated = make_tree_vector ();
+ params = &allocated;
+ }
+
+ nargs = convert_arguments (parm_types, params, fndecl, LOOKUP_NORMAL,
+ complain);
if (nargs < 0)
return error_mark_node;
+ argarray = VEC_address (tree, *params);
+
/* Check for errors in format strings and inappropriately
null parameters. */
check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
parm_types);
- return build_cxx_call (function, nargs, argarray);
+ ret = build_cxx_call (function, nargs, argarray);
+
+ if (allocated != NULL)
+ release_tree_vector (allocated);
+
+ return ret;
}
-/* Convert the actual parameter expressions in the list VALUES
- to the types in the list TYPELIST.
+/* Convert the actual parameter expressions in the list VALUES to the
+ types in the list TYPELIST. The converted expressions are stored
+ back in the VALUES vector.
If parmdecls is exhausted, or when an element has NULL as its type,
perform the default conversions.
- Store the converted arguments in ARGARRAY. NARGS is the size of this array.
-
NAME is an IDENTIFIER_NODE or 0. It is used only for error messages.
This is also where warnings about wrong number of args are generated.
Returns the actual number of arguments processed (which might be less
- than NARGS), or -1 on error.
-
- VALUES is a chain of TREE_LIST nodes with the elements of the list
- in the TREE_VALUE slots of those nodes.
+ than the length of the vector), or -1 on error.
In C++, unspecified trailing parameters can be filled in with their
default arguments, if such were specified. Do so here. */
static int
-convert_arguments (int nargs, tree *argarray,
- tree typelist, tree values, tree fndecl, int flags,
- tsubst_flags_t complain)
+convert_arguments (tree typelist, VEC(tree,gc) **values, tree fndecl,
+ int flags, tsubst_flags_t complain)
{
- tree typetail, valtail;
+ tree typetail;
const char *called_thing = 0;
- int i = 0;
+ unsigned int i;
/* Argument passing is always copy-initialization. */
flags |= LOOKUP_ONLYCONVERTING;
@@ -3022,12 +3047,12 @@ convert_arguments (int nargs, tree *argarray,
called_thing = "function";
}
- for (valtail = values, typetail = typelist;
- valtail;
- valtail = TREE_CHAIN (valtail), i++)
+ for (i = 0, typetail = typelist;
+ i < VEC_length (tree, *values);
+ i++)
{
tree type = typetail ? TREE_VALUE (typetail) : 0;
- tree val = TREE_VALUE (valtail);
+ tree val = VEC_index (tree, *values, i);
if (val == error_mark_node || type == error_mark_node)
return -1;
@@ -3096,7 +3121,7 @@ convert_arguments (int nargs, tree *argarray,
if (parmval == error_mark_node)
return -1;
- argarray[i] = parmval;
+ VEC_replace (tree, *values, i, parmval);
}
else
{
@@ -3109,7 +3134,7 @@ convert_arguments (int nargs, tree *argarray,
else
val = convert_arg_to_ellipsis (val);
- argarray[i] = val;
+ VEC_replace (tree, *values, i, val);
}
if (typetail)
@@ -3138,7 +3163,7 @@ convert_arguments (int nargs, tree *argarray,
if (parmval == error_mark_node)
return -1;
- argarray[i] = parmval;
+ VEC_safe_push (tree, gc, *values, parmval);
typetail = TREE_CHAIN (typetail);
/* ends with `...'. */
if (typetail == NULL_TREE)
@@ -3162,8 +3187,7 @@ convert_arguments (int nargs, tree *argarray,
}
}
- gcc_assert (i <= nargs);
- return i;
+ return (int) i;
}
/* Build a binary-operation expression, after performing default
@@ -3492,7 +3516,11 @@ cp_build_binary_op (location_t location,
case FLOOR_MOD_EXPR:
warn_for_div_by_zero (location, op1);
- if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
+ if (code0 == VECTOR_TYPE && code1 == VECTOR_TYPE
+ && TREE_CODE (TREE_TYPE (type0)) == INTEGER_TYPE
+ && TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
+ common = 1;
+ else if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
/* Although it would be tempting to shorten always here, that loses
on some targets, since the modulo instruction is undefined if the
@@ -3613,9 +3641,9 @@ cp_build_binary_op (location_t location,
build_type = boolean_type_node;
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == COMPLEX_TYPE)
+ || code0 == COMPLEX_TYPE || code0 == ENUMERAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE))
+ || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE))
short_compare = 1;
else if ((code0 == POINTER_TYPE && code1 == POINTER_TYPE)
|| (TYPE_PTRMEM_P (type0) && TYPE_PTRMEM_P (type1)))
@@ -3887,9 +3915,10 @@ cp_build_binary_op (location_t location,
break;
}
- if (((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE)
+ if (((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE
+ || code0 == ENUMERAL_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE)))
+ || code1 == COMPLEX_TYPE || code1 == ENUMERAL_TYPE)))
arithmetic_types_p = 1;
else
{
@@ -4142,8 +4171,20 @@ build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain)
/*overloaded_p=*/NULL, complain);
if (!exp && code == ADDR_EXPR)
{
- /* A pointer to member-function can be formed only by saying
- &X::mf. */
+ if (is_overloaded_fn (xarg))
+ {
+ tree fn = get_first_fn (xarg);
+ if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn))
+ {
+ const char *type =
+ (DECL_CONSTRUCTOR_P (fn) ? "constructor" : "destructor");
+ error ("taking address of %s %qE", type, xarg);
+ return error_mark_node;
+ }
+ }
+
+ /* A pointer to member-function can be formed only by saying
+ &X::mf. */
if (!flag_ms_extensions && TREE_CODE (TREE_TYPE (xarg)) == METHOD_TYPE
&& (TREE_CODE (xarg) != OFFSET_REF || !PTRMEM_OK_P (xarg)))
{
@@ -4975,6 +5016,34 @@ tree build_x_compound_expr_from_list (tree list, const char *msg)
return expr;
}
+/* Like build_x_compound_expr_from_list, but using a VEC. */
+
+tree
+build_x_compound_expr_from_vec (VEC(tree,gc) *vec, const char *msg)
+{
+ if (VEC_empty (tree, vec))
+ return NULL_TREE;
+ else if (VEC_length (tree, vec) == 1)
+ return VEC_index (tree, vec, 0);
+ else
+ {
+ tree expr;
+ unsigned int ix;
+ tree t;
+
+ if (msg != NULL)
+ permerror (input_location,
+ "%s expression list treated as compound expression",
+ msg);
+
+ expr = VEC_index (tree, vec, 0);
+ for (ix = 1; VEC_iterate (tree, vec, ix, t); ++ix)
+ expr = build_x_compound_expr (expr, t, tf_warning_or_error);
+
+ return expr;
+ }
+}
+
/* Handle overloading of the ',' operator when needed. */
tree
@@ -5285,8 +5354,10 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
/* The effect of all that is that any conversion between any two
types which are integral, floating, or enumeration types can be
performed. */
- if ((INTEGRAL_TYPE_P (type) || SCALAR_FLOAT_TYPE_P (type))
- && (INTEGRAL_TYPE_P (intype) || SCALAR_FLOAT_TYPE_P (intype)))
+ if ((INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+ || SCALAR_FLOAT_TYPE_P (type))
+ && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
+ || SCALAR_FLOAT_TYPE_P (intype)))
{
expr = ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL);
@@ -5586,7 +5657,8 @@ build_reinterpret_cast_1 (tree type, tree expr, bool c_cast_p,
}
else if (TREE_CODE (type) == VECTOR_TYPE)
return fold_if_not_in_template (convert_to_vector (type, expr));
- else if (TREE_CODE (intype) == VECTOR_TYPE && INTEGRAL_TYPE_P (type))
+ else if (TREE_CODE (intype) == VECTOR_TYPE
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (type))
return fold_if_not_in_template (convert_to_integer (type, expr));
else
{
@@ -6019,10 +6091,11 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
/* Do the default thing. */;
else
{
+ VEC(tree,gc) *rhs_vec = make_tree_vector_single (rhs);
result = build_special_member_call (lhs, complete_ctor_identifier,
- build_tree_list (NULL_TREE, rhs),
- lhstype, LOOKUP_NORMAL,
+ &rhs_vec, lhstype, LOOKUP_NORMAL,
complain);
+ release_tree_vector (rhs_vec);
if (result == NULL_TREE)
return error_mark_node;
return result;
@@ -6146,12 +6219,14 @@ cp_build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs,
}
if (modifycode == INIT_EXPR)
+ /* Calls with INIT_EXPR are all direct-initialization, so don't set
+ LOOKUP_ONLYCONVERTING. */
newrhs = convert_for_initialization (lhs, olhstype, newrhs, LOOKUP_NORMAL,
"initialization", NULL_TREE, 0,
complain);
else
newrhs = convert_for_assignment (olhstype, newrhs, "assignment",
- NULL_TREE, 0, complain);
+ NULL_TREE, 0, complain, LOOKUP_IMPLICIT);
if (!same_type_p (lhstype, olhstype))
newrhs = cp_convert_and_check (lhstype, newrhs);
@@ -6557,7 +6632,7 @@ delta_from_ptrmemfunc (tree t)
static tree
convert_for_assignment (tree type, tree rhs,
const char *errtype, tree fndecl, int parmnum,
- tsubst_flags_t complain)
+ tsubst_flags_t complain, int flags)
{
tree rhstype;
enum tree_code coder;
@@ -6624,7 +6699,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
@@ -6678,7 +6753,8 @@ convert_for_assignment (tree type, tree rhs,
TREE_NO_WARNING (rhs) = 1;
}
- return perform_implicit_conversion (strip_top_quals (type), rhs, complain);
+ return perform_implicit_conversion_flags (strip_top_quals (type), rhs,
+ complain, flags);
}
/* Convert RHS to be of type TYPE.
@@ -6769,7 +6845,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
return convert_for_assignment (type, rhs, errtype, fndecl, parmnum,
- complain);
+ complain, flags);
}
/* If RETVAL is the address of, or a reference to, a local variable or
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 5ed7818732f..e66842733a0 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -586,7 +586,7 @@ split_nonconstant_init (tree dest, tree init)
for static variable. In that case, caller must emit the code. */
tree
-store_init_value (tree decl, tree init)
+store_init_value (tree decl, tree init, int flags)
{
tree value, type;
@@ -628,7 +628,7 @@ store_init_value (tree decl, tree init)
/* End of special C++ code. */
/* Digest the specified initializer into an expression. */
- value = digest_init (type, init);
+ value = digest_init_flags (type, init, flags);
/* If the initializer is not a constant, fill in DECL_INITIAL with
the bits that are constant, and then return an expression that
will perform the dynamic initialization. */
@@ -717,7 +717,7 @@ check_narrowing (tree type, tree init)
NESTED is true iff we are being called for an element of a CONSTRUCTOR. */
static tree
-digest_init_r (tree type, tree init, bool nested)
+digest_init_r (tree type, tree init, bool nested, int flags)
{
enum tree_code code = TREE_CODE (type);
@@ -796,9 +796,9 @@ digest_init_r (tree type, tree init, bool nested)
if (cxx_dialect != cxx98 && nested)
check_narrowing (type, init);
- init = convert_for_initialization (0, type, init, LOOKUP_NORMAL,
+ init = convert_for_initialization (0, type, init, flags,
"initialization", NULL_TREE, 0,
- tf_warning_or_error);
+ tf_warning_or_error);
exp = &init;
/* Skip any conversions since we'll be outputting the underlying
@@ -842,7 +842,7 @@ digest_init_r (tree type, tree init, bool nested)
}
return convert_for_initialization (NULL_TREE, type, init,
- LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING,
+ flags,
"initialization", NULL_TREE, 0,
tf_warning_or_error);
}
@@ -851,7 +851,13 @@ digest_init_r (tree type, tree init, bool nested)
tree
digest_init (tree type, tree init)
{
- return digest_init_r (type, init, false);
+ return digest_init_r (type, init, false, LOOKUP_IMPLICIT);
+}
+
+tree
+digest_init_flags (tree type, tree init, int flags)
+{
+ return digest_init_r (type, init, false, flags);
}
/* Set of flags used within process_init_constructor to describe the
@@ -924,7 +930,7 @@ process_init_constructor_array (tree type, tree init)
else
ce->index = size_int (i);
gcc_assert (ce->value);
- ce->value = digest_init_r (TREE_TYPE (type), ce->value, true);
+ ce->value = digest_init_r (TREE_TYPE (type), ce->value, true, LOOKUP_IMPLICIT);
if (ce->value != error_mark_node)
gcc_assert (same_type_ignoring_top_level_qualifiers_p
@@ -1031,7 +1037,7 @@ process_init_constructor_record (tree type, tree init)
}
gcc_assert (ce->value);
- next = digest_init_r (type, ce->value, true);
+ next = digest_init_r (type, ce->value, true, LOOKUP_IMPLICIT);
++idx;
}
else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
@@ -1046,7 +1052,7 @@ process_init_constructor_record (tree type, tree init)
else
next = build_constructor (init_list_type_node, NULL);
- next = digest_init_r (TREE_TYPE (field), next, true);
+ next = digest_init_r (TREE_TYPE (field), next, true, LOOKUP_IMPLICIT);
/* Warn when some struct elements are implicitly initialized. */
warning (OPT_Wmissing_field_initializers,
@@ -1156,7 +1162,7 @@ process_init_constructor_union (tree type, tree init)
}
if (ce->value && ce->value != error_mark_node)
- ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, true);
+ ce->value = digest_init_r (TREE_TYPE (ce->index), ce->value, true, LOOKUP_IMPLICIT);
return picflag_from_initializer (ce->value);
}
@@ -1436,6 +1442,7 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
/* The type to which we are casting. */
tree type;
+ VEC(tree,gc) *parmvec;
if (exp == error_mark_node || parms == error_mark_node)
return error_mark_node;
@@ -1506,8 +1513,12 @@ build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
}
/* Call the constructor. */
- exp = build_special_member_call (NULL_TREE, complete_ctor_identifier, parms,
- type, LOOKUP_NORMAL, complain);
+ parmvec = make_tree_vector ();
+ for (; parms != NULL_TREE; parms = TREE_CHAIN (parms))
+ VEC_safe_push (tree, gc, parmvec, TREE_VALUE (parms));
+ exp = build_special_member_call (NULL_TREE, complete_ctor_identifier,
+ &parmvec, type, LOOKUP_NORMAL, complain);
+ release_tree_vector (parmvec);
if (exp == error_mark_node)
return error_mark_node;
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/dbxout.c b/gcc/dbxout.c
index eb0fceee52b..9ec0525d959 100644
--- a/gcc/dbxout.c
+++ b/gcc/dbxout.c
@@ -275,8 +275,6 @@ static const char *base_input_file;
#include "gstab.h"
-#define STAB_CODE_TYPE enum __stab_debug_code
-
/* 1 if PARM is passed to this function in memory. */
#define PARM_PASSED_IN_MEMORY(PARM) \
@@ -326,7 +324,7 @@ static void dbxout_type_name (tree);
static void dbxout_class_name_qualifiers (tree);
static int dbxout_symbol_location (tree, tree, const char *, rtx);
static void dbxout_symbol_name (tree, const char *, int);
-static void dbxout_common_name (tree, const char *, STAB_CODE_TYPE);
+static void dbxout_common_name (tree, const char *, stab_code_type);
static const char *dbxout_common_check (tree, int *);
static void dbxout_global_decl (tree);
static void dbxout_type_decl (tree, int);
@@ -842,7 +840,7 @@ do { \
to DBX_FINISH_STABS; see above for details. */
static void
-dbxout_finish_complex_stabs (tree sym, STAB_CODE_TYPE code,
+dbxout_finish_complex_stabs (tree sym, stab_code_type code,
rtx addr, const char *label, int number)
{
int line ATTRIBUTE_UNUSED;
@@ -2852,7 +2850,7 @@ static int
dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
{
int letter = 0;
- STAB_CODE_TYPE code;
+ stab_code_type code;
rtx addr = 0;
int number = 0;
int regno = -1;
@@ -3157,7 +3155,7 @@ dbxout_symbol_name (tree decl, const char *suffix, int letter)
emits the N_BCOMM and N_ECOMM stabs. */
static void
-dbxout_common_name (tree decl, const char *name, STAB_CODE_TYPE op)
+dbxout_common_name (tree decl, const char *name, stab_code_type op)
{
dbxout_begin_complex_stabs ();
stabstr_S (name);
@@ -3325,7 +3323,7 @@ dbxout_parms (tree parms)
{
tree eff_type;
char letter;
- STAB_CODE_TYPE code;
+ stab_code_type code;
int number;
/* Perform any necessary register eliminations on the parameter's rtl,
diff --git a/gcc/defaults.h b/gcc/defaults.h
index 8ed40d93b54..b41f60366d5 100644
--- a/gcc/defaults.h
+++ b/gcc/defaults.h
@@ -492,6 +492,181 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define LONG_LONG_ACCUM_TYPE_SIZE (LONG_LONG_FRACT_TYPE_SIZE * 2)
#endif
+/* We let tm.h override the types used here, to handle trivial differences
+ such as the choice of unsigned int or long unsigned int for size_t.
+ When machines start needing nontrivial differences in the size type,
+ it would be best to do something here to figure out automatically
+ from other information what type to use. */
+
+#ifndef SIZE_TYPE
+#define SIZE_TYPE "long unsigned int"
+#endif
+
+#ifndef PID_TYPE
+#define PID_TYPE "int"
+#endif
+
+/* If GCC knows the exact uint_least16_t and uint_least32_t types from
+ <stdint.h>, use them for char16_t and char32_t. Otherwise, use
+ these guesses; getting the wrong type of a given width will not
+ affect C++ name mangling because in C++ these are distinct types
+ not typedefs. */
+
+#ifdef UINT_LEAST16_TYPE
+#define CHAR16_TYPE UINT_LEAST16_TYPE
+#else
+#define CHAR16_TYPE "short unsigned int"
+#endif
+
+#ifdef UINT_LEAST32_TYPE
+#define CHAR32_TYPE UINT_LEAST32_TYPE
+#else
+#define CHAR32_TYPE "unsigned int"
+#endif
+
+#ifndef WCHAR_TYPE
+#define WCHAR_TYPE "int"
+#endif
+
+/* WCHAR_TYPE gets overridden by -fshort-wchar. */
+#define MODIFIED_WCHAR_TYPE \
+ (flag_short_wchar ? "short unsigned int" : WCHAR_TYPE)
+
+#ifndef PTRDIFF_TYPE
+#define PTRDIFF_TYPE "long int"
+#endif
+
+#ifndef WINT_TYPE
+#define WINT_TYPE "unsigned int"
+#endif
+
+#ifndef INTMAX_TYPE
+#define INTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "int" \
+ : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "long int" \
+ : "long long int"))
+#endif
+
+#ifndef UINTMAX_TYPE
+#define UINTMAX_TYPE ((INT_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "unsigned int" \
+ : ((LONG_TYPE_SIZE == LONG_LONG_TYPE_SIZE) \
+ ? "long unsigned int" \
+ : "long long unsigned int"))
+#endif
+
+
+/* There are no default definitions of these <stdint.h> types. */
+
+#ifndef SIG_ATOMIC_TYPE
+#define SIG_ATOMIC_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT8_TYPE
+#define INT8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT16_TYPE
+#define INT16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT32_TYPE
+#define INT32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT64_TYPE
+#define INT64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT8_TYPE
+#define UINT8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT16_TYPE
+#define UINT16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT32_TYPE
+#define UINT32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT64_TYPE
+#define UINT64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST8_TYPE
+#define INT_LEAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST16_TYPE
+#define INT_LEAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST32_TYPE
+#define INT_LEAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_LEAST64_TYPE
+#define INT_LEAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST8_TYPE
+#define UINT_LEAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST16_TYPE
+#define UINT_LEAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST32_TYPE
+#define UINT_LEAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_LEAST64_TYPE
+#define UINT_LEAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST8_TYPE
+#define INT_FAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST16_TYPE
+#define INT_FAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST32_TYPE
+#define INT_FAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INT_FAST64_TYPE
+#define INT_FAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST8_TYPE
+#define UINT_FAST8_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST16_TYPE
+#define UINT_FAST16_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST32_TYPE
+#define UINT_FAST32_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINT_FAST64_TYPE
+#define UINT_FAST64_TYPE ((const char *) NULL)
+#endif
+
+#ifndef INTPTR_TYPE
+#define INTPTR_TYPE ((const char *) NULL)
+#endif
+
+#ifndef UINTPTR_TYPE
+#define UINTPTR_TYPE ((const char *) NULL)
+#endif
+
/* Width in bits of a pointer. Mind the value of the macro `Pmode'. */
#ifndef POINTER_SIZE
#define POINTER_SIZE BITS_PER_WORD
diff --git a/gcc/doc/c-tree.texi b/gcc/doc/c-tree.texi
index 117b700ec08..35498583ccd 100644
--- a/gcc/doc/c-tree.texi
+++ b/gcc/doc/c-tree.texi
@@ -1995,7 +1995,6 @@ This macro returns the attributes on the type @var{type}.
@tindex TARGET_EXPR
@tindex AGGR_INIT_EXPR
@tindex VA_ARG_EXPR
-@tindex CHANGE_DYNAMIC_TYPE_EXPR
@tindex OMP_PARALLEL
@tindex OMP_FOR
@tindex OMP_SECTIONS
@@ -2708,13 +2707,6 @@ mechanism. It represents expressions like @code{va_arg (ap, type)}.
Its @code{TREE_TYPE} yields the tree representation for @code{type} and
its sole argument yields the representation for @code{ap}.
-@item CHANGE_DYNAMIC_TYPE_EXPR
-Indicates the special aliasing required by C++ placement new. It has
-two operands: a type and a location. It means that the dynamic type
-of the location is changing to be the specified type. The alias
-analysis code takes this into account when doing type based alias
-analysis.
-
@item OMP_PARALLEL
Represents @code{#pragma omp parallel [clause1 @dots{} clauseN]}. It
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/extend.texi b/gcc/doc/extend.texi
index 6b626e2add7..98df9d59447 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -5746,7 +5746,7 @@ produce code that uses 4 @code{SIs}.
The types defined in this manner can be used with a subset of normal C
operations. Currently, GCC will allow using the following operators
-on these types: @code{+, -, *, /, unary minus, ^, |, &, ~}@.
+on these types: @code{+, -, *, /, unary minus, ^, |, &, ~, %}@.
The operations behave like C++ @code{valarrays}. Addition is defined as
the addition of the corresponding elements of the operands. For
diff --git a/gcc/doc/gccint.texi b/gcc/doc/gccint.texi
index 265244b349e..4014d370da9 100644
--- a/gcc/doc/gccint.texi
+++ b/gcc/doc/gccint.texi
@@ -109,10 +109,10 @@ Additional tutorial information is linked to from
* Options:: Option specification files.
* Passes:: Order of passes, what they do, and what each file is for.
* Trees:: The source representation used by the C and C++ front ends.
-* RTL:: The intermediate representation that most passes work on.
* GENERIC:: Language-independent representation generated by Front Ends
* GIMPLE:: Tuple representation used by Tree SSA optimizers
* Tree SSA:: Analysis and optimization of GIMPLE
+* RTL:: Machine-dependent low-level intermediate representation.
* Control Flow:: Maintaining and manipulating the control flow graph.
* Loop Analysis and Representation:: Analysis and representation of loops
* Machine Desc:: How to write machine description instruction patterns.
diff --git a/gcc/doc/gimple.texi b/gcc/doc/gimple.texi
index cc1e8903fdb..a78c52dcafc 100644
--- a/gcc/doc/gimple.texi
+++ b/gcc/doc/gimple.texi
@@ -332,14 +332,13 @@ union gimple_statement_d
The following table briefly describes the GIMPLE instruction set.
-@multitable {@code{GIMPLE_CHANGE_DYNAMIC_TYPE}} {High GIMPLE} {Low GIMPLE}
+@multitable {@code{GIMPLE_OMP_SECTIONS_SWITCH}} {High GIMPLE} {Low GIMPLE}
@item Instruction @tab High GIMPLE @tab Low GIMPLE
@item @code{GIMPLE_ASM} @tab x @tab x
@item @code{GIMPLE_ASSIGN} @tab x @tab x
@item @code{GIMPLE_BIND} @tab x @tab
@item @code{GIMPLE_CALL} @tab x @tab x
@item @code{GIMPLE_CATCH} @tab x @tab
-@item @code{GIMPLE_CHANGE_DYNAMIC_TYPE} @tab x @tab x
@item @code{GIMPLE_COND} @tab x @tab x
@item @code{GIMPLE_EH_FILTER} @tab x @tab
@item @code{GIMPLE_GOTO} @tab x @tab x
@@ -885,7 +884,6 @@ Return a deep copy of statement @code{STMT}.
* @code{GIMPLE_BIND}::
* @code{GIMPLE_CALL}::
* @code{GIMPLE_CATCH}::
-* @code{GIMPLE_CHANGE_DYNAMIC_TYPE}::
* @code{GIMPLE_COND}::
* @code{GIMPLE_EH_FILTER}::
* @code{GIMPLE_LABEL}::
@@ -1295,45 +1293,6 @@ Set @code{T} to be the set of types handled by @code{GIMPLE_CATCH} @code{G}.
Set @code{HANDLER} to be the body of @code{GIMPLE_CATCH} @code{G}.
@end deftypefn
-@node @code{GIMPLE_CHANGE_DYNAMIC_TYPE}
-@subsection @code{GIMPLE_CHANGE_DYNAMIC_TYPE}
-@cindex @code{GIMPLE_CHANGE_DYNAMIC_TYPE}
-
-@deftypefn {GIMPLE function} gimple gimple_build_cdt (tree type, tree ptr)
-Build a @code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement. @code{TYPE} is the new
-type for the location @code{PTR}.
-@end deftypefn
-
-@deftypefn {GIMPLE function} tree gimple_cdt_new_type (gimple g)
-Return the new type set by @code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement
-@code{G}.
-@end deftypefn
-
-@deftypefn {GIMPLE function} tree *gimple_cdt_new_type_ptr (gimple g)
-Return a pointer to the new type set by
-@code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement @code{G}.
-@end deftypefn
-
-@deftypefn {GIMPLE function} void gimple_cdt_set_new_type (gimple g, tree new_type)
-Set @code{NEW_TYPE} to be the type returned by
-@code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement @code{G}.
-@end deftypefn
-
-@deftypefn {GIMPLE function} tree gimple_cdt_location (gimple g)
-Return the location affected by @code{GIMPLE_CHANGE_DYNAMIC_TYPE}
-statement @code{G}.
-@end deftypefn
-
-@deftypefn {GIMPLE function} tree *gimple_cdt_location_ptr (gimple g)
-Return a pointer to the location affected by
-@code{GIMPLE_CHANGE_DYNAMIC_TYPE} statement @code{G}.
-@end deftypefn
-
-@deftypefn {GIMPLE function} void gimple_cdt_set_location (gimple g, tree ptr)
-Set @code{PTR} to be the location affected by @code{GIMPLE_CHANGE_DYNAMIC_TYPE}
-statement @code{G}.
-@end deftypefn
-
@node @code{GIMPLE_COND}
@subsection @code{GIMPLE_COND}
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index 89d9b69bba6..ca059df9445 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -577,7 +577,7 @@ Objective-C and Objective-C++ Dialects}.
-mno-wide-multiply -mrtd -malign-double @gol
-mpreferred-stack-boundary=@var{num}
-mincoming-stack-boundary=@var{num}
--mcld -mcx16 -msahf -mrecip @gol
+-mcld -mcx16 -msahf -mmovbe -mrecip @gol
-mmmx -msse -msse2 -msse3 -mssse3 -msse4.1 -msse4.2 -msse4 -mavx @gol
-maes -mpclmul @gol
-msse4a -m3dnow -mpopcnt -mabm -msse5 @gol
@@ -593,21 +593,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
@@ -1594,7 +1599,7 @@ freestanding and hosted environments.
Enable handling of OpenMP directives @code{#pragma omp} in C/C++ and
@code{!$omp} in Fortran. When @option{-fopenmp} is specified, the
compiler generates parallel code according to the OpenMP Application
-Program Interface v2.5 @w{@uref{http://www.openmp.org/}}. This option
+Program Interface v3.0 @w{@uref{http://www.openmp.org/}}. This option
implies @option{-pthread}, and thus is only supported on targets that
have support for @option{-pthread}.
@@ -2806,7 +2811,6 @@ name is still supported, but the newer name is more descriptive.)
@gccoptlist{-Wclobbered @gol
-Wempty-body @gol
-Wignored-qualifiers @gol
--Wlogical-op @gol
-Wmissing-field-initializers @gol
-Wmissing-parameter-type @r{(C only)} @gol
-Wold-style-declaration @r{(C only)} @gol
@@ -3793,8 +3797,7 @@ programmer intended to use @code{strcmp}. This warning is enabled by
@opindex Wno-logical-op
Warn about suspicious uses of logical operators in expressions.
This includes using logical operators in contexts where a
-bit-wise operator is likely to be expected. This warning is enabled by
-@option{-Wextra}.
+bit-wise operator is likely to be expected.
@item -Waggregate-return
@opindex Waggregate-return
@@ -11460,6 +11463,11 @@ SAHF are load and store instructions, respectively, for certain status flags.
In 64-bit mode, SAHF instruction is used to optimize @code{fmod}, @code{drem}
or @code{remainder} built-in functions: see @ref{Other Builtins} for details.
+@item -mmovbe
+@opindex mmovbe
+This option will enable GCC to use movbe instruction to implement
+@code{__builtin_bswap32} and @code{__builtin_bswap64}.
+
@item -mrecip
@opindex mrecip
This option will enable GCC to use RCPSS and RSQRTSS instructions (and their
@@ -11720,6 +11728,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
@@ -11730,6 +11742,10 @@ using the minimum latency algorithm.
Generate code for inline divides of integer values
using the maximum throughput algorithm.
+@item -mno-inline-float-divide
+@opindex mno-inline-float-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
@@ -11740,6 +11756,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
@@ -11773,15 +11800,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
@@ -11846,31 +11864,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
@@ -11898,6 +11891,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
@@ -15675,6 +15705,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/passes.texi b/gcc/doc/passes.texi
index 3dcee398dd5..b28b87cb57a 100644
--- a/gcc/doc/passes.texi
+++ b/gcc/doc/passes.texi
@@ -21,7 +21,7 @@ where near complete.
* Parsing pass:: The language front end turns text into bits.
* Gimplification pass:: The bits are turned into something we can optimize.
* Pass manager:: Sequencing the optimization passes.
-* Tree-SSA passes:: Optimizations on a high-level representation.
+* Tree SSA passes:: Optimizations on a high-level representation.
* RTL passes:: Optimizations on a low-level representation.
@end menu
@@ -94,8 +94,8 @@ be passed to @code{rest_of_type_compilation}. Each function definition
should be passed to @code{cgraph_finalize_function}.
TODO: I know rest_of_compilation currently has all sorts of
-rtl-generation semantics. I plan to move all code generation
-bits (both tree and rtl) to compile_function. Should we hide
+RTL generation semantics. I plan to move all code generation
+bits (both Tree and RTL) to compile_function. Should we hide
cgraph from the front ends and move back to rest_of_compilation
as the official interface? Possibly we should rename all three
interfaces such that the names match in some meaningful way and
@@ -172,12 +172,12 @@ dump anything.
TODO: describe the global variables set up by the pass manager,
and a brief description of how a new pass should use it.
-I need to look at what info rtl passes use first@enddots{}
+I need to look at what info RTL passes use first@enddots{}
-@node Tree-SSA passes
-@section Tree-SSA passes
+@node Tree SSA passes
+@section Tree SSA passes
-The following briefly describes the tree optimization passes that are
+The following briefly describes the Tree optimization passes that are
run after gimplification and what source files they are located in.
@itemize @bullet
@@ -401,7 +401,7 @@ and described by @code{pass_loop}.
The optimizations performed by this pass are:
Loop invariant motion. This pass moves only invariants that
-would be hard to handle on rtl level (function calls, operations that expand to
+would be hard to handle on RTL level (function calls, operations that expand to
nontrivial sequences of insns). With @option{-funswitch-loops} it also moves
operands of conditions that are invariant out of the loop, so that we can use
just trivial invariantness analysis in loop unswitching. The pass also includes
@@ -422,8 +422,8 @@ Loop unswitching. This pass moves the conditional jumps that are invariant
out of the loops. To achieve this, a duplicate of the loop is created for
each possible outcome of conditional jump(s). The pass is implemented in
@file{tree-ssa-loop-unswitch.c}. This pass should eventually replace the
-rtl-level loop unswitching in @file{loop-unswitch.c}, but currently
-the rtl-level pass is not completely redundant yet due to deficiencies
+RTL level loop unswitching in @file{loop-unswitch.c}, but currently
+the RTL level pass is not completely redundant yet due to deficiencies
in tree level alias analysis.
The optimizations also use various utility functions contained in
@@ -438,11 +438,19 @@ conceptually unrolled by a factor @code{VF} (vectorization factor), which is
the number of elements operated upon in parallel in each iteration, and the
@code{VF} copies of each scalar operation are fused to form a vector operation.
Additional loop transformations such as peeling and versioning may take place
-to align the number of iterations, and to align the memory accesses in the loop.
-The pass is implemented in @file{tree-vectorizer.c} (the main driver and general
-utilities), @file{tree-vect-analyze.c} and @file{tree-vect-transform.c}.
+to align the number of iterations, and to align the memory accesses in the
+loop.
+The pass is implemented in @file{tree-vectorizer.c} (the main driver),
+@file{tree-vect-loop.c} and @file{tree-vect-loop-manip.c} (loop specific parts
+and general loop utilities), @file{tree-vect-slp} (loop-aware SLP
+functionality), @file{tree-vect-stmts.c} and @file{tree-vect-data-refs.c}.
Analysis of data references is in @file{tree-data-ref.c}.
+SLP Vectorization. This pass performs vectorization of straight-line code. The
+pass is implemented in @file{tree-vectorizer.c} (the main driver),
+@file{tree-vect-slp.c}, @file{tree-vect-stmts.c} and
+@file{tree-vect-data-refs.c}.
+
Autoparallelization. This pass splits the loop iteration space to run
into several threads. The pass is implemented in @file{tree-parloops.c}.
@@ -651,8 +659,8 @@ registers don't need to be saved. This pass is located in
@node RTL passes
@section RTL passes
-The following briefly describes the rtl generation and optimization
-passes that are run after tree optimization.
+The following briefly describes the RTL generation and optimization
+passes that are run after the Tree optimization passes.
@itemize @bullet
@item RTL generation
@@ -679,15 +687,15 @@ generated from the machine description by the programs @code{genflags}
and @code{gencodes}, tell this pass which standard names are available
for use and which patterns correspond to them.
-@item Generate exception handling landing pads
+@item Generation of exception landing pads
This pass generates the glue that handles communication between the
exception handling library routines and the exception handlers within
the function. Entry points in the function that are invoked by the
exception handling library are called @dfn{landing pads}. The code
-for this pass is located within @file{except.c}.
+for this pass is located in @file{except.c}.
-@item Cleanup control flow graph
+@item Control flow graph cleanup
This pass removes unreachable code, simplifies jumps to next, jumps to
jump, jumps across jumps, etc. The pass is run multiple times.
@@ -702,16 +710,16 @@ This pass attempts to remove redundant computation by substituting
variables that come from a single definition, and
seeing if the result can be simplified. It performs copy propagation
and addressing mode selection. The pass is run twice, with values
-being propagated into loops only on the second run. It is located in
-@file{fwprop.c}.
+being propagated into loops only on the second run. The code is
+located in @file{fwprop.c}.
@item Common subexpression elimination
This pass removes redundant computation within basic blocks, and
optimizes addressing modes based on cost. The pass is run twice.
-The source is located in @file{cse.c}.
+The code for this pass is located in @file{cse.c}.
-@item Global common subexpression elimination.
+@item Global common subexpression elimination
This pass performs two
different types of GCSE depending on whether you are optimizing for
@@ -755,22 +763,13 @@ This pass attempts to replace conditional branches and surrounding
assignments with arithmetic, boolean value producing comparison
instructions, and conditional move instructions. In the very last
invocation after reload, it will generate predicated instructions
-when supported by the target. The pass is located in @file{ifcvt.c}.
+when supported by the target. The code is located in @file{ifcvt.c}.
@item Web construction
This pass splits independent uses of each pseudo-register. This can
improve effect of the other transformation, such as CSE or register
-allocation. Its source files are @file{web.c}.
-
-@item Life analysis
-
-This pass computes which pseudo-registers are live at each point in
-the program, and makes the first instruction that uses a value point
-at the instruction that computed the value. It then deletes
-computations whose results are never used, and combines memory
-references with add or subtract instructions to make autoincrement or
-autodecrement addressing. The pass is located in @file{flow.c}.
+allocation. The code for this pass is located in @file{web.c}.
@item Instruction combination
@@ -778,23 +777,23 @@ This pass attempts to combine groups of two or three instructions that
are related by data flow into single instructions. It combines the
RTL expressions for the instructions by substitution, simplifies the
result using algebra, and then attempts to match the result against
-the machine description. The pass is located in @file{combine.c}.
+the machine description. The code is located in @file{combine.c}.
@item Register movement
This pass looks for cases where matching constraints would force an
instruction to need a reload, and this reload would be a
register-to-register move. It then attempts to change the registers
-used by the instruction to avoid the move instruction.
-The pass is located in @file{regmove.c}.
+used by the instruction to avoid the move instruction. The code is
+located in @file{regmove.c}.
-@item Optimize mode switching
+@item Mode switching optimization
This pass looks for instructions that require the processor to be in a
specific ``mode'' and minimizes the number of mode changes required to
satisfy all users. What these modes are, and what they apply to are
-completely target-specific.
-The source is located in @file{mode-switching.c}.
+completely target-specific. The code for this pass is located in
+@file{mode-switching.c}.
@cindex modulo scheduling
@cindex sms, swing, software pipelining
@@ -802,8 +801,8 @@ The source is located in @file{mode-switching.c}.
This pass looks at innermost loops and reorders their instructions
by overlapping different iterations. Modulo scheduling is performed
-immediately before instruction scheduling.
-The pass is located in (@file{modulo-sched.c}).
+immediately before instruction scheduling. The code for this pass is
+located in @file{modulo-sched.c}.
@item Instruction scheduling
@@ -813,7 +812,7 @@ floating point instructions often have this behavior on RISC machines.
It re-orders instructions within a basic block to try to separate the
definition and use of items that otherwise would cause pipeline
stalls. This pass is performed twice, before and after register
-allocation. The pass is located in @file{haifa-sched.c},
+allocation. The code for this pass is located in @file{haifa-sched.c},
@file{sched-deps.c}, @file{sched-ebb.c}, @file{sched-rgn.c} and
@file{sched-vis.c}.
@@ -884,13 +883,13 @@ This pass computes where the variables are stored at each
position in code and generates notes describing the variable locations
to RTL code. The location lists are then generated according to these
notes to debug information if the debugging information format supports
-location lists.
+location lists. The code is located in @file{var-tracking.c}.
@item Delayed branch scheduling
This optional pass attempts to find instructions that can go into the
-delay slots of other instructions, usually jumps and calls. The
-source file name is @file{reorg.c}.
+delay slots of other instructions, usually jumps and calls. The code
+for this pass is located in @file{reorg.c}.
@item Branch shortening
@@ -899,13 +898,14 @@ Thus, longer sequences of instructions must be used for long branches.
In this pass, the compiler figures out what how far each instruction
will be from each other instruction, and therefore whether the usual
instructions, or the longer sequences, must be used for each branch.
+The code for this pass is located in @file{final.c}.
@item Register-to-stack conversion
Conversion from usage of some hard registers to usage of a register
stack may be done at this point. Currently, this is supported only
-for the floating-point registers of the Intel 80387 coprocessor. The
-source file name is @file{reg-stack.c}.
+for the floating-point registers of the Intel 80387 coprocessor. The
+code for this pass is located in @file{reg-stack.c}.
@item Final
diff --git a/gcc/doc/plugins.texi b/gcc/doc/plugins.texi
index 1710395b50d..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
@@ -41,14 +43,49 @@ This function is called from @code{compile_file} right before invoking
the parser. The arguments to @code{plugin_init} are:
@itemize @bullet
-@item @code{plugin_name}: Name of the plugin.
-@item @code{argc}: Number of arguments specified with @option{-fplugin-arg-...}.
-@item @code{argv}: Array of @code{argc} key-value pairs.
+@item @code{plugin_info}: Plugin invocation information.
+@item @code{version}: GCC version.
@end itemize
+The @code{plugin_info} struct is defined as follows:
+
+@smallexample
+struct plugin_name_args
+@{
+ char *base_name; /* Short name of the plugin
+ (filename without .so suffix). */
+ const char *full_name; /* Path to the plugin as specified with
+ -fplugin=. */
+ int argc; /* Number of arguments specified with
+ -fplugin-arg-.... */
+ struct plugin_argument *argv; /* Array of ARGC key-value pairs. */
+ const char *version; /* Version string provided by plugin. */
+ const char *help; /* Help string provided by plugin. */
+@}
+@end smallexample
+
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:
@@ -71,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.
@@ -86,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
@@ -120,7 +167,8 @@ struct plugin_pass
/* Sample plugin code that registers a new pass. */
int
-plugin_init (const char *plugin_name, int argc, struct plugin_argument *argv)
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
@{
struct plugin_pass pass_info;
@@ -131,11 +179,55 @@ plugin_init (const char *plugin_name, int argc, struct plugin_argument *argv)
...
/* Register the new pass. */
- register_callback (plugin_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_info);
+ register_callback (plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, NULL, &pass_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/rtl.texi b/gcc/doc/rtl.texi
index 2567f10f4b0..79baa10e25d 100644
--- a/gcc/doc/rtl.texi
+++ b/gcc/doc/rtl.texi
@@ -10,10 +10,10 @@
@cindex representation of RTL
@cindex Register Transfer Language (RTL)
-Most of the work of the compiler is done on an intermediate representation
-called register transfer language. In this language, the instructions to be
-output are described, pretty much one by one, in an algebraic form that
-describes what the instruction does.
+The last part of the compiler work is done on a low-level intermediate
+representation called Register Transfer Language. In this language, the
+instructions to be output are described, pretty much one by one, in an
+algebraic form that describes what the instruction does.
RTL is inspired by Lisp lists. It has both an internal form, made up of
structures that point at other structures, and a textual form that is used
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 7f8a5d6b4c6..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
@@ -10781,6 +10788,38 @@ and @var{type2}, or @code{NULL} if validity should be determined by
the front end.
@end deftypefn
+@deftypefn {Target Hook} {const char *} TARGET_INVALID_PARAMETER_TYPE (tree @var{type})
+If defined, this macro returns the diagnostic message when it is
+invalid for functions to include parameters of type @var{type},
+or @code{NULL} if validity should be determined by
+the front end. This is currently used only by the C and C++ front ends.
+@end deftypefn
+
+@deftypefn {Target Hook} {const char *} TARGET_INVALID_RETURN_TYPE (tree @var{type})
+If defined, this macro returns the diagnostic message when it is
+invalid for functions to have return type @var{type},
+or @code{NULL} if validity should be determined by
+the front end. This is currently used only by the C and C++ front ends.
+@end deftypefn
+
+@deftypefn {Target Hook} {tree} TARGET_PROMOTED_TYPE (tree @var{type})
+If defined, this target hook returns the type to which values of
+@var{type} should be promoted when they appear in expressions,
+analogous to the integer promotions, or @code{NULL_TREE} to use the
+front end's normal promotion rules. This hook is useful when there are
+target-specific types with special promotion rules.
+This is currently used only by the C and C++ front ends.
+@end deftypefn
+
+@deftypefn {Target Hook} {tree} TARGET_CONVERT_TO_TYPE (tree @var{type}, tree @var{expr})
+If defined, this hook returns the result of converting @var{expr} to
+@var{type}. It should return the converted expression,
+or @code{NULL_TREE} to apply the front end's normal conversion rules.
+This hook is useful when there are target-specific types with special
+conversion rules.
+This is currently used only by the C and C++ front ends.
+@end deftypefn
+
@defmac TARGET_USE_JCR_SECTION
This macro determines whether to use the JCR section to register Java
classes. By default, TARGET_USE_JCR_SECTION is defined to 1 if both
@@ -10820,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/doc/tree-ssa.texi b/gcc/doc/tree-ssa.texi
index 659431b0274..ebb85a05769 100644
--- a/gcc/doc/tree-ssa.texi
+++ b/gcc/doc/tree-ssa.texi
@@ -41,6 +41,7 @@ passes for GIMPLE@.
* SSA Operands:: SSA names referenced by GIMPLE statements.
* SSA:: Static Single Assignment representation.
* Alias analysis:: Representing aliased loads and stores.
+* Memory model:: Memory model used by the middle-end.
@end menu
@node Annotations
@@ -108,9 +109,9 @@ full object that they represent. For instance, given
Since @code{a} and @code{b} are non-aliased locals, the statement
@code{a = b} will have one real definition and one real use because
-variable @code{b} is completely modified with the contents of
-variable @code{a}. Real definition are also known as @dfn{killing
-definitions}. Similarly, the use of @code{a} reads all its bits.
+variable @code{a} is completely modified with the contents of
+variable @code{b}. Real definition are also known as @dfn{killing
+definitions}. Similarly, the use of @code{b} reads all its bits.
In contrast, virtual operands are used with variables that can have
a partial or ambiguous reference. This includes structures, arrays,
@@ -892,3 +893,31 @@ providing its aliasing VDEF. The walk stops if asked to.
@end enumerate
+
+@node Memory model
+@section Memory model
+@cindex memory model
+
+The memory model used by the middle-end models that of the C/C++
+languages. The middle-end has the notion of an effective type
+of a memory region which is used for type-based alias analysis.
+
+The following is a refinement of ISO C99 6.5/6, clarifying the block copy case
+to follow common sense and extending the concept of a dynamic effective
+type to objects with a declared type as required for C++.
+
+@smallexample
+The effective type of an object for an access to its stored value is
+the declared type of the object or the effective type determined by
+a previous store to it. If a value is stored into an object through
+an lvalue having a type that is not a character type, then the
+type of the lvalue becomes the effective type of the object for that
+access and for subsequent accesses that do not modify the stored value.
+If a value is copied into an object using @code{memcpy} or @code{memmove},
+or is copied as an array of character type, then the effective type
+of the modified object for that access and for subsequent accesses that
+do not modify the value is undetermined. For all other accesses to an
+object, the effective type of the object is simply the type of the
+lvalue used for the access.
+@end smallexample
+
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index 7156b6e8a9f..8236881474b 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -14638,6 +14638,12 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
/* Prevent broken recursion; we can't hand off to the same type. */
gcc_assert (DECL_ORIGINAL_TYPE (TYPE_NAME (type)) != type);
+ /* Use the DIE of the containing namespace as the parent DIE of
+ the type description DIE we want to generate. */
+ if (DECL_CONTEXT (TYPE_NAME (type))
+ && TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL)
+ context_die = lookup_decl_die (DECL_CONTEXT (TYPE_NAME (type)));
+
TREE_ASM_WRITTEN (type) = 1;
gen_decl_die (TYPE_NAME (type), NULL, context_die);
return;
diff --git a/gcc/except.c b/gcc/except.c
index a698e8f1c5b..ff45a7e6d72 100644
--- a/gcc/except.c
+++ b/gcc/except.c
@@ -1039,6 +1039,43 @@ get_next_region_sharing_label (int region)
return r->next_region_sharing_label->region_number;
}
+/* Return bitmap of all labels that are handlers of must not throw regions. */
+
+bitmap
+must_not_throw_labels (void)
+{
+ struct eh_region_d *i;
+ bitmap labels = BITMAP_ALLOC (NULL);
+
+ i = cfun->eh->region_tree;
+ if (! i)
+ return labels;
+
+ while (1)
+ {
+ if (i->type == ERT_MUST_NOT_THROW && i->tree_label
+ && LABEL_DECL_UID (i->tree_label) >= 0)
+ bitmap_set_bit (labels, LABEL_DECL_UID (i->tree_label));
+
+ /* If there are sub-regions, process them. */
+ if (i->inner)
+ i = i->inner;
+ /* If there are peers, process them. */
+ else if (i->next_peer)
+ i = i->next_peer;
+ /* Otherwise, step back up the tree to the next peer. */
+ else
+ {
+ do {
+ i = i->outer;
+ if (i == NULL)
+ return labels;
+ } while (i->next_peer == NULL);
+ i = i->next_peer;
+ }
+ }
+}
+
/* Set up EH labels for RTL. */
void
diff --git a/gcc/except.h b/gcc/except.h
index 6906601ceb7..58c596a17ba 100644
--- a/gcc/except.h
+++ b/gcc/except.h
@@ -274,6 +274,6 @@ extern void set_eh_throw_stmt_table (struct function *, struct htab *);
extern void remove_unreachable_regions (sbitmap, sbitmap);
extern VEC(int,heap) * label_to_region_map (void);
extern int num_eh_regions (void);
-extern struct eh_region_d *redirect_eh_edge_to_label (struct edge_def *, tree,
- bool, bool, int);
+extern bitmap must_not_throw_labels (void);
+extern struct eh_region_d *redirect_eh_edge_to_label (struct edge_def *, tree, bool, bool, int);
extern int get_next_region_sharing_label (int);
diff --git a/gcc/expr.c b/gcc/expr.c
index 15d26700a4a..37ed067cb5b 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))
@@ -9293,13 +9329,6 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
/* Lowered by gimplify.c. */
gcc_unreachable ();
- case CHANGE_DYNAMIC_TYPE_EXPR:
- /* This is ignored at the RTL level. The tree level set
- DECL_POINTER_ALIAS_SET of any variable to be 0, which is
- overkill for the RTL layer but is all that we can
- represent. */
- return const0_rtx;
-
case EXC_PTR_EXPR:
return get_exception_pointer ();
diff --git a/gcc/final.c b/gcc/final.c
index 30ccc852991..2f68ee8431e 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -553,7 +553,17 @@ static int min_labelno, max_labelno;
int
label_to_alignment (rtx label)
{
- return LABEL_TO_ALIGNMENT (label);
+ if (CODE_LABEL_NUMBER (label) <= max_labelno)
+ return LABEL_TO_ALIGNMENT (label);
+ return 0;
+}
+
+int
+label_to_max_skip (rtx label)
+{
+ if (CODE_LABEL_NUMBER (label) <= max_labelno)
+ return LABEL_TO_MAX_SKIP (label);
+ return 0;
}
#ifdef HAVE_ATTR_length
@@ -891,6 +901,7 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
if (LABEL_P (insn))
{
rtx next;
+ bool next_is_jumptable;
/* Merge in alignments computed by compute_alignments. */
log = LABEL_TO_ALIGNMENT (insn);
@@ -900,31 +911,30 @@ shorten_branches (rtx first ATTRIBUTE_UNUSED)
max_skip = LABEL_TO_MAX_SKIP (insn);
}
- log = LABEL_ALIGN (insn);
- if (max_log < log)
+ next = next_nonnote_insn (insn);
+ next_is_jumptable = next && JUMP_TABLE_DATA_P (next);
+ if (!next_is_jumptable)
{
- max_log = log;
- max_skip = LABEL_ALIGN_MAX_SKIP;
+ log = LABEL_ALIGN (insn);
+ if (max_log < log)
+ {
+ max_log = log;
+ max_skip = LABEL_ALIGN_MAX_SKIP;
+ }
}
- next = next_nonnote_insn (insn);
/* ADDR_VECs only take room if read-only data goes into the text
section. */
- if (JUMP_TABLES_IN_TEXT_SECTION
- || readonly_data_section == text_section)
- if (next && JUMP_P (next))
- {
- rtx nextbody = PATTERN (next);
- if (GET_CODE (nextbody) == ADDR_VEC
- || GET_CODE (nextbody) == ADDR_DIFF_VEC)
- {
- log = ADDR_VEC_ALIGN (next);
- if (max_log < log)
- {
- max_log = log;
- max_skip = LABEL_ALIGN_MAX_SKIP;
- }
- }
- }
+ if ((JUMP_TABLES_IN_TEXT_SECTION
+ || readonly_data_section == text_section)
+ && next_is_jumptable)
+ {
+ log = ADDR_VEC_ALIGN (next);
+ if (max_log < log)
+ {
+ max_log = log;
+ max_skip = LABEL_ALIGN_MAX_SKIP;
+ }
+ }
LABEL_TO_ALIGNMENT (insn) = max_log;
LABEL_TO_MAX_SKIP (insn) = max_skip;
max_log = 0;
@@ -2013,48 +2023,41 @@ final_scan_insn (rtx insn, FILE *file, int optimize ATTRIBUTE_UNUSED,
app_disable ();
next = next_nonnote_insn (insn);
- if (next != 0 && JUMP_P (next))
+ /* If this label is followed by a jump-table, make sure we put
+ the label in the read-only section. Also possibly write the
+ label and jump table together. */
+ if (next != 0 && JUMP_TABLE_DATA_P (next))
{
- rtx nextbody = PATTERN (next);
-
- /* If this label is followed by a jump-table,
- make sure we put the label in the read-only section. Also
- possibly write the label and jump table together. */
-
- if (GET_CODE (nextbody) == ADDR_VEC
- || GET_CODE (nextbody) == ADDR_DIFF_VEC)
- {
#if defined(ASM_OUTPUT_ADDR_VEC) || defined(ASM_OUTPUT_ADDR_DIFF_VEC)
- /* In this case, the case vector is being moved by the
- target, so don't output the label at all. Leave that
- to the back end macros. */
+ /* In this case, the case vector is being moved by the
+ target, so don't output the label at all. Leave that
+ to the back end macros. */
#else
- if (! JUMP_TABLES_IN_TEXT_SECTION)
- {
- int log_align;
+ if (! JUMP_TABLES_IN_TEXT_SECTION)
+ {
+ int log_align;
- switch_to_section (targetm.asm_out.function_rodata_section
- (current_function_decl));
+ switch_to_section (targetm.asm_out.function_rodata_section
+ (current_function_decl));
#ifdef ADDR_VEC_ALIGN
- log_align = ADDR_VEC_ALIGN (next);
+ log_align = ADDR_VEC_ALIGN (next);
#else
- log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
+ log_align = exact_log2 (BIGGEST_ALIGNMENT / BITS_PER_UNIT);
#endif
- ASM_OUTPUT_ALIGN (file, log_align);
- }
- else
- switch_to_section (current_function_section ());
+ ASM_OUTPUT_ALIGN (file, log_align);
+ }
+ else
+ switch_to_section (current_function_section ());
#ifdef ASM_OUTPUT_CASE_LABEL
- ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
- next);
+ ASM_OUTPUT_CASE_LABEL (file, "L", CODE_LABEL_NUMBER (insn),
+ next);
#else
- targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
+ targetm.asm_out.internal_label (file, "L", CODE_LABEL_NUMBER (insn));
#endif
#endif
- break;
- }
+ break;
}
if (LABEL_ALT_ENTRY_P (insn))
output_alternate_entry_point (file, insn);
diff --git a/gcc/fold-const.c b/gcc/fold-const.c
index b3ad7875842..643a4449a17 100644
--- a/gcc/fold-const.c
+++ b/gcc/fold-const.c
@@ -7999,6 +7999,13 @@ build_fold_addr_expr_with_type (tree t, tree ptrtype)
if (TREE_TYPE (t) != ptrtype)
t = build1 (NOP_EXPR, ptrtype, t);
}
+ else if (TREE_CODE (t) == VIEW_CONVERT_EXPR)
+ {
+ t = build_fold_addr_expr (TREE_OPERAND (t, 0));
+
+ if (TREE_TYPE (t) != ptrtype)
+ t = fold_convert (ptrtype, t);
+ }
else
t = build1 (ADDR_EXPR, ptrtype, t);
@@ -10169,8 +10176,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;
@@ -10184,10 +10195,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)
{
@@ -10202,10 +10215,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));
}
}
}
@@ -11376,6 +11391,8 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
if (prec < HOST_BITS_PER_WIDE_INT
|| newmask == ~(unsigned HOST_WIDE_INT) 0)
{
+ tree newmaskt;
+
if (shift_type != TREE_TYPE (arg0))
{
tem = fold_build2 (TREE_CODE (arg0), shift_type,
@@ -11386,9 +11403,9 @@ fold_binary (enum tree_code code, tree type, tree op0, tree op1)
}
else
tem = op0;
- return fold_build2 (BIT_AND_EXPR, type, tem,
- build_int_cst_type (TREE_TYPE (op1),
- newmask));
+ newmaskt = build_int_cst_type (TREE_TYPE (op1), newmask);
+ if (!tree_int_cst_equal (newmaskt, arg1))
+ return fold_build2 (BIT_AND_EXPR, type, tem, newmaskt);
}
}
}
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index bc6dd0b9645..6f9e4241e47 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,3 +1,172 @@
+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
+ * primary.c (gfc_match_varspec): Handle procedure pointer components
+ with array return value.
+ * resolve.c (resolve_expr_ppc): Ditto.
+ (resolve_symbol): Make sure the interface of a procedure pointer has
+ been resolved.
+ * trans-array.c (gfc_walk_function_expr): Handle procedure pointer
+ components with array return value.
+ * trans-expr.c (gfc_conv_component_ref,gfc_conv_procedure_call,
+ gfc_trans_arrayfunc_assign): Ditto.
+ (gfc_trans_pointer_assignment): Handle procedure pointer assignments,
+ where the rhs is a dummy argument.
+ * trans-types.c (gfc_get_ppc_type,gfc_get_derived_type): Handle
+ procedure pointer components with array return value.
+
+2009-05-24 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+ Dominique Dhumieres
+
+ PR fortran/35732
+ PR fortran/39872
+ * trans-array.c (gfc_conv_ss_startstride): Add one to index.
+
+2009-05-22 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/40195
+ * module.c (read_md5_from_module_file): Close file before returning.
+
+2009-05-18 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/40164
+ * primary.c (gfc_match_rvalue): Handle procedure pointer components in
+ arrays.
+ * resolve.c (resolve_ppc_call,resolve_expr_ppc): Resolve component and
+ array references.
+ (resolve_fl_derived): Procedure pointer components are not required to
+ have constant array bounds in their return value.
+
+2009-05-18 Janus Weil <janus@gcc.gnu.org>
+
+ * intrinsic.c (add_sym): Fix my last commit (r147655),
+ which broke bootstrap.
+
+2009-05-18 Richard Guenther <rguenther@suse.de>
+
+ PR fortran/40168
+ * trans-expr.c (gfc_trans_zero_assign): For local array
+ destinations use an assignment from an empty constructor.
+
+2009-05-18 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/36947
+ PR fortran/40039
+ * expr.c (gfc_check_pointer_assign): Check intents when comparing
+ interfaces.
+ * gfortran.h (typedef struct gfc_intrinsic_arg): Add 'intent' member.
+ (gfc_compare_interfaces): Additional argument.
+ * interface.c (operator_correspondence): Add check for equality of
+ intents, and new argument 'intent_check'.
+ (gfc_compare_interfaces): New argument 'intent_check', which is passed
+ on to operator_correspondence.
+ (check_interface1): Don't check intents when comparing interfaces.
+ (compare_parameter): Do check intents when comparing interfaces.
+ * intrinsic.c (add_sym): Add intents for arguments of intrinsic
+ procedures.
+ (add_sym_1,add_sym_1s,add_sym_1m,add_sym_2,add_sym_2s,add_sym_3,
+ add_sym_3ml,add_sym_3red,add_sym_3s,add_sym_4): Use INTENT_IN by
+ default.
+ (add_sym_1_intent,add_sym_1s_intent,add_sym_2s_intent,add_sym_3s_intent)
+ : New functions to add intrinsic symbols, specifying custom intents.
+ (add_sym_4s,add_sym_5s): Add new arguments to specify intents.
+ (add_functions,add_subroutines): Add intents for various intrinsics.
+ * resolve.c (check_generic_tbp_ambiguity): Don't check intents when
+ comparing interfaces.
+ * symbol.c (gfc_copy_formal_args_intr): Copy intent.
+
+2009-05-17 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ * iso-fortran-env.def: Define INT8, INT16, INT32, INT64, REAL32,
+ REAL64 and REAL128.
+ * gfortran.h (gfc_get_int_kind_from_width_isofortranenv,
+ gfc_get_real_kind_from_width_isofortranenv): New prototypes.
+ * iso-c-binding.def: Update definitions for the INT*_T,
+ INT_LEAST*_T and INT_FAST*_T named parameters.
+ * trans-types.c (get_typenode_from_name, get_int_kind_from_name,
+ gfc_get_real_kind_from_width_isofortranenv): New functions.
+
+2009-05-17 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/36260
+ * intrinsic.c (add_functions, add_subroutines): Fix argument
+ names and wrap long lines.
+ * intrinsic.texi: Fix documentation and argument names of
+ LOG_GAMMA, DATAN2, DBESJN, DTIME, ETIME, FSTAT, STAT, LSTAT,
+ GET_COMMAND, IDATE, LTIME, MOVE_ALLOC, NINT, OR, PRODUCT,
+ SUM, RAND, RANDOM_SEED, REAL, SELECTED_INT_KIND,
+ SELECTED_REAL_KIND and XOR.
+
+2009-05-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/33197
+ * intrinsic.c (add_functions): Use ERFC_SCALED simplification.
+ * intrinsic.h (gfc_simplify_erfc_scaled): New prototype.
+ * simplify.c (fullprec_erfc_scaled, asympt_erfc_scaled,
+ gfc_simplify_erfc_scaled): New functions.
+
+2009-05-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/31243
+ * resolve.c (resolve_substring): Don't allow too large substring
+ indexes.
+ (gfc_resolve_substring_charlen): Fix typo.
+ (gfc_resolve_character_operator): Fix typo.
+ (resolve_charlen): Catch unreasonably large string lengths.
+ * simplify.c (gfc_simplify_len): Don't error out on LEN
+ range checks.
+
+2009-05-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/36031
+ * decl.c (set_enum_kind): Use global short-enums flag.
+ * gfortran.h (gfc_option_t): Remove short_enums flag.
+ * lang.opt (-fshort-enums): Refer to C documentation.
+ * options.c (gfc_init_options, gfc_handle_option): Use global
+ short-enums flag.
+
2009-05-15 Tobias Burnus <burnus@net-b.de>
PR fortran/39352
@@ -91,7 +260,7 @@
* gfortran.h (gfc_code): Rename struct member label to label1.
* dump-parse-tree.c (show_code_node): Update symbol.
* trans-stmt.c (gfc_trans_label_assign, gfc_trans_goto,
- gfc_trans_arithmetic_if)": Ditto.
+ gfc_trans_arithmetic_if): Ditto.
* resolve.c (gfc_resolve_blocks, resolve_code): Ditto.
* match.c (match_arithmetic_if, gfc_match_if, gfc_reference_st_label,
gfc_match_assign, gfc_match_goto): Ditto.
@@ -349,13 +518,13 @@
2009-04-24 Daniel Kraft <d@domob.eu>
* gfortran.h (gfc_get_typebound_proc): Removed as macro, now a function.
- (struct gfc_symtree): Moved `typebound' member inside union.
- (struct gfc_namespace): Add `tb_sym_root' as new symtree to sort out
+ (struct gfc_symtree): Moved "typebound" member inside union.
+ (struct gfc_namespace): Add "tb_sym_root" as new symtree to sort out
type-bound procedures there.
(gfc_get_tbp_symtree): New procedure.
* symbol.c (tentative_tbp_list): New global.
- (gfc_get_namespace): NULL new `tb_sym_root' member.
- (gfc_new_symtree): Removed initialization of `typebound' member.
+ (gfc_get_namespace): NULL new "tb_sym_root" member.
+ (gfc_new_symtree): Removed initialization of "typebound" member.
(gfc_undo_symbols): Process list of tentative tbp's.
(gfc_commit_symbols): Ditto.
(free_tb_tree): New method.
@@ -368,8 +537,8 @@
* primary.c (gfc_match_varspec): Ditto. Don't reference tbp-symbol
as it isn't a symbol any longer.
* module.c (mio_typebound_symtree): Adapt to changes.
- (mio_typebound_proc): Ditto, create symtrees using `gfc_get_tbp_symtree'
- rather than `gfc_get_sym_tree'.
+ (mio_typebound_proc): Ditto, create symtrees using "gfc_get_tbp_symtree"
+ rather than "gfc_get_sym_tree".
(mio_f2k_derived): Ditto.
* decl.c (match_procedure_in_type): Ditto.
(gfc_match_generic): Ditto. Don't reference tbp-symbol.
@@ -478,7 +647,7 @@
2009-04-11 Daniel Kraft <d@domob.eu>
PR fortran/37746
- * gfortran.h (struct gfc_charlen): New field `passed_length' to store
+ * gfortran.h (struct gfc_charlen): New field "passed_length" to store
the actual passed string length for dummy arguments.
* trans-decl.c (gfc_create_string_length): Formatting fixes and added
assertion, moved a local variable into the innermost block it is needed.
@@ -586,15 +755,15 @@
2009-04-06 Janus Weil <janus@gcc.gnu.org>
- PR fortran/39414
- * decl.c (match_procedure_decl): Fix double declaration problems with
- PROCEDURE statements.
- * symbol.c (gfc_add_type): Ditto.
+ PR fortran/39414
+ * decl.c (match_procedure_decl): Fix double declaration problems with
+ PROCEDURE statements.
+ * symbol.c (gfc_add_type): Ditto.
2009-04-06 Paul Thomas <pault@gcc.gnu.org>
- PR fortran/36091
- * trans-array.c (gfc_conv_array_ref): If the symbol has the
+ PR fortran/36091
+ * trans-array.c (gfc_conv_array_ref): If the symbol has the
temporary attribute use the array_spec for the bounds.
* gfortran.h : Add the temporary field to the structure
'symbol_attribute'.
@@ -723,7 +892,7 @@
2009-03-29 Daniel Kraft <d@domob.eu>
PR fortran/37423
- * gfortran.h (struct gfc_typebound_proc): Added new flag `deferred' and
+ * gfortran.h (struct gfc_typebound_proc): Added new flag "deferred" and
added a comment explaining DEFERRED binding handling.
* decl.c (match_binding_attributes): Really match DEFERRED attribute.
(match_procedure_in_type): Really match PROCEDURE(interface) syntax
@@ -735,7 +904,7 @@
(resolve_typebound_procedure): Allow abstract interfaces as targets
for DEFERRED bindings.
(ensure_not_abstract_walker), (ensure_not_abstract): New methods.
- (resolve_fl_derived): Use new `ensure_not_abstract' method for
+ (resolve_fl_derived): Use new "ensure_not_abstract" method for
non-ABSTRACT types extending ABSTRACT ones to ensure each DEFERRED
binding is overridden.
(check_typebound_baseobject): New method.
@@ -744,7 +913,7 @@
* gfc-internals.texi (Type-bound procedures): Document a little bit
about internal handling of DEFERRED bindings.
-2009-03-29 Tobias Schlüter <tobi@gcc.gnu.org>
+2009-03-29 Tobias Schlueter <tobi@gcc.gnu.org>
PR fortran/38507
* gfortran.h (gfc_st_label): Fix comment.
diff --git a/gcc/fortran/Make-lang.in b/gcc/fortran/Make-lang.in
index b4a57a5dc29..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)'; \
- $(CXX) -c $(ALL_CXXFLAGS) $(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)
- $(CXX) $(ALL_CXXFLAGS) $(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
- $(CXX) $(ALL_CXXFLAGS) $(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
- $(CXX) -c $(ALL_CXXFLAGS) $(ALL_CPPFLAGS) -DBASEVER=$(BASEVER_s) \
- $< $(OUTPUT_OPTION)
+ $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) \
+ -DBASEVER=$(BASEVER_s) $< $(OUTPUT_OPTION)
diff --git a/gcc/fortran/decl.c b/gcc/fortran/decl.c
index ae80be11a82..8bb94bf2766 100644
--- a/gcc/fortran/decl.c
+++ b/gcc/fortran/decl.c
@@ -24,6 +24,7 @@ along with GCC; see the file COPYING3. If not see
#include "gfortran.h"
#include "match.h"
#include "parse.h"
+#include "flags.h"
/* Macros to access allocate memory for gfc_data_variable,
@@ -5295,7 +5296,7 @@ set_enum_kind(void)
if (max_enum == NULL || enum_history == NULL)
return;
- if (!gfc_option.fshort_enums)
+ if (!flag_short_enums)
return;
i = 0;
diff --git a/gcc/fortran/expr.c b/gcc/fortran/expr.c
index feaa6254840..2c70ba6bb98 100644
--- a/gcc/fortran/expr.c
+++ b/gcc/fortran/expr.c
@@ -3176,7 +3176,7 @@ gfc_check_pointer_assign (gfc_expr *lvalue, gfc_expr *rvalue)
return SUCCESS;
if (rvalue->expr_type == EXPR_VARIABLE
&& !gfc_compare_interfaces (lvalue->symtree->n.sym,
- rvalue->symtree->n.sym, 0))
+ rvalue->symtree->n.sym, 0, 1))
{
gfc_error ("Interfaces don't match "
"in procedure pointer assignment at %L", &rvalue->where);
diff --git a/gcc/fortran/gfortran.h b/gcc/fortran/gfortran.h
index bc066bc8b8e..82f07ef0052 100644
--- a/gcc/fortran/gfortran.h
+++ b/gcc/fortran/gfortran.h
@@ -1445,6 +1445,7 @@ typedef struct gfc_intrinsic_arg
gfc_typespec ts;
int optional;
+ ENUM_BITFIELD (sym_intent) intent:2;
gfc_actual_arglist *actual;
struct gfc_intrinsic_arg *next;
@@ -1555,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
{
@@ -2060,7 +2062,6 @@ typedef struct
int warn_std;
int allow_std;
- int fshort_enums;
int convert;
int record_marker;
int max_subrecord_length;
@@ -2255,6 +2256,8 @@ bool gfc_check_character_range (gfc_char_t, int);
/* trans-types.c */
gfc_try gfc_check_any_c_kind (gfc_typespec *);
int gfc_validate_kind (bt, int, bool);
+int gfc_get_int_kind_from_width_isofortranenv (int size);
+int gfc_get_real_kind_from_width_isofortranenv (int size);
extern int gfc_index_integer_kind;
extern int gfc_default_integer_kind;
extern int gfc_max_integer_kind;
@@ -2565,7 +2568,7 @@ gfc_try gfc_ref_dimen_size (gfc_array_ref *, int dimen, mpz_t *);
void gfc_free_interface (gfc_interface *);
int gfc_compare_derived_types (gfc_symbol *, gfc_symbol *);
int gfc_compare_types (gfc_typespec *, gfc_typespec *);
-int gfc_compare_interfaces (gfc_symbol*, gfc_symbol*, int);
+int gfc_compare_interfaces (gfc_symbol*, gfc_symbol*, int, int);
void gfc_check_interfaces (gfc_namespace *);
void gfc_procedure_use (gfc_symbol *, gfc_actual_arglist **, locus *);
gfc_symbol *gfc_search_interface (gfc_interface *, int,
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/interface.c b/gcc/fortran/interface.c
index f2d14657f06..48c026cb2fe 100644
--- a/gcc/fortran/interface.c
+++ b/gcc/fortran/interface.c
@@ -873,23 +873,32 @@ count_types_test (gfc_formal_arglist *f1, gfc_formal_arglist *f2)
which makes this test much easier than that for generic tests.
This subroutine is also used when comparing a formal and actual
- argument list when an actual parameter is a dummy procedure. At
- that point, two formal interfaces must be compared for equality
- which is what happens here. */
+ argument list when an actual parameter is a dummy procedure, and in
+ procedure pointer assignments. In these cases, two formal interfaces must be
+ compared for equality which is what happens here. 'intent_flag' specifies
+ whether the intents of the arguments are required to match, which is not the
+ case for ambiguity checks. */
static int
-operator_correspondence (gfc_formal_arglist *f1, gfc_formal_arglist *f2)
+operator_correspondence (gfc_formal_arglist *f1, gfc_formal_arglist *f2,
+ int intent_flag)
{
for (;;)
{
+ /* Check existence. */
if (f1 == NULL && f2 == NULL)
break;
if (f1 == NULL || f2 == NULL)
return 1;
+ /* Check type and rank. */
if (!compare_type_rank (f1->sym, f2->sym))
return 1;
+ /* Check intent. */
+ if (intent_flag && (f1->sym->attr.intent != f2->sym->attr.intent))
+ return 1;
+
f1 = f1->next;
f2 = f2->next;
}
@@ -961,7 +970,8 @@ generic_correspondence (gfc_formal_arglist *f1, gfc_formal_arglist *f2)
would be ambiguous between the two interfaces, zero otherwise. */
int
-gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, int generic_flag)
+gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, int generic_flag,
+ int intent_flag)
{
gfc_formal_arglist *f1, *f2;
@@ -1001,7 +1011,7 @@ gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol *s2, int generic_flag)
}
else
{
- if (operator_correspondence (f1, f2))
+ if (operator_correspondence (f1, f2, intent_flag))
return 0;
}
@@ -1080,7 +1090,7 @@ check_interface1 (gfc_interface *p, gfc_interface *q0,
if (p->sym->name == q->sym->name && p->sym->module == q->sym->module)
continue;
- if (gfc_compare_interfaces (p->sym, q->sym, generic_flag))
+ if (gfc_compare_interfaces (p->sym, q->sym, generic_flag, 0))
{
if (referenced)
{
@@ -1362,7 +1372,7 @@ compare_parameter (gfc_symbol *formal, gfc_expr *actual,
|| actual->symtree->n.sym->attr.external)
return 1; /* Assume match. */
- if (!gfc_compare_interfaces (formal, actual->symtree->n.sym, 0))
+ if (!gfc_compare_interfaces (formal, actual->symtree->n.sym, 0, 1))
goto proc_fail;
return 1;
diff --git a/gcc/fortran/intrinsic.c b/gcc/fortran/intrinsic.c
index ca125a36335..0b16a727778 100644
--- a/gcc/fortran/intrinsic.c
+++ b/gcc/fortran/intrinsic.c
@@ -227,11 +227,12 @@ do_check (gfc_intrinsic_sym *specific, gfc_actual_arglist *arg)
simplify pointer to simplification function
resolve pointer to resolution function
- Optional arguments come in multiples of four:
- char * name of argument
- bt type of argument
- int kind of argument
- int arg optional flag (1=optional, 0=required)
+ Optional arguments come in multiples of five:
+ char * name of argument
+ bt type of argument
+ int kind of argument
+ int arg optional flag (1=optional, 0=required)
+ sym_intent intent of argument
The sequence is terminated by a NULL name.
@@ -249,6 +250,7 @@ add_sym (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type
{
char buf[GFC_MAX_SYMBOL_LEN + 11]; /* 10 for '_gfortran_', 1 for '\0' */
int optional, first_flag;
+ sym_intent intent;
va_list argp;
switch (sizing)
@@ -301,6 +303,7 @@ add_sym (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type
type = (bt) va_arg (argp, int);
kind = va_arg (argp, int);
optional = va_arg (argp, int);
+ intent = (sym_intent) va_arg (argp, int);
if (sizing != SZ_NOTHING)
nargs++;
@@ -319,6 +322,7 @@ add_sym (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt type
next_arg->ts.type = type;
next_arg->ts.kind = kind;
next_arg->optional = optional;
+ next_arg->intent = intent;
}
}
@@ -390,7 +394,7 @@ add_sym_1 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt ty
rf.f1 = resolve;
add_sym (name, id, cl, actual_ok, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
+ a1, type1, kind1, optional1, INTENT_IN,
(void *) 0);
}
@@ -414,7 +418,59 @@ add_sym_1s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
rf.s1 = resolve;
add_sym (name, id, cl, ACTUAL_NO, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
+ a1, type1, kind1, optional1, INTENT_IN,
+ (void *) 0);
+}
+
+
+/* Add a symbol to the function list where the function takes
+ 1 arguments, specifying the intent of the argument. */
+
+static void
+add_sym_1_intent (const char *name, gfc_isym_id id, enum klass cl,
+ int actual_ok, bt type, int kind, int standard,
+ gfc_try (*check) (gfc_expr *),
+ gfc_expr *(*simplify) (gfc_expr *),
+ void (*resolve) (gfc_expr *, gfc_expr *),
+ const char *a1, bt type1, int kind1, int optional1,
+ sym_intent intent1)
+{
+ gfc_check_f cf;
+ gfc_simplify_f sf;
+ gfc_resolve_f rf;
+
+ cf.f1 = check;
+ sf.f1 = simplify;
+ rf.f1 = resolve;
+
+ add_sym (name, id, cl, actual_ok, type, kind, standard, cf, sf, rf,
+ a1, type1, kind1, optional1, intent1,
+ (void *) 0);
+}
+
+
+/* Add a symbol to the subroutine list where the subroutine takes
+ 1 arguments, specifying the intent of the argument. */
+
+static void
+add_sym_1s_intent (const char *name, gfc_isym_id id, enum klass cl, bt type,
+ int kind, int standard,
+ gfc_try (*check) (gfc_expr *),
+ gfc_expr *(*simplify) (gfc_expr *),
+ void (*resolve) (gfc_code *),
+ const char *a1, bt type1, int kind1, int optional1,
+ sym_intent intent1)
+{
+ gfc_check_f cf;
+ gfc_simplify_f sf;
+ gfc_resolve_f rf;
+
+ cf.f1 = check;
+ sf.f1 = simplify;
+ rf.s1 = resolve;
+
+ add_sym (name, id, cl, ACTUAL_NO, type, kind, standard, cf, sf, rf,
+ a1, type1, kind1, optional1, intent1,
(void *) 0);
}
@@ -440,8 +496,8 @@ add_sym_1m (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt t
rf.f1m = resolve;
add_sym (name, id, cl, actual_ok, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
- a2, type2, kind2, optional2,
+ a1, type1, kind1, optional1, INTENT_IN,
+ a2, type2, kind2, optional2, INTENT_IN,
(void *) 0);
}
@@ -467,8 +523,8 @@ add_sym_2 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt ty
rf.f2 = resolve;
add_sym (name, id, cl, actual_ok, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
- a2, type2, kind2, optional2,
+ a1, type1, kind1, optional1, INTENT_IN,
+ a2, type2, kind2, optional2, INTENT_IN,
(void *) 0);
}
@@ -493,8 +549,36 @@ add_sym_2s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
rf.s1 = resolve;
add_sym (name, id, cl, ACTUAL_NO, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
- a2, type2, kind2, optional2,
+ a1, type1, kind1, optional1, INTENT_IN,
+ a2, type2, kind2, optional2, INTENT_IN,
+ (void *) 0);
+}
+
+
+/* Add a symbol to the subroutine list where the subroutine takes
+ 2 arguments, specifying the intent of the arguments. */
+
+static void
+add_sym_2s_intent (const char *name, gfc_isym_id id, enum klass cl, bt type,
+ int kind, int standard,
+ gfc_try (*check) (gfc_expr *, gfc_expr *),
+ gfc_expr *(*simplify) (gfc_expr *, gfc_expr *),
+ void (*resolve) (gfc_code *),
+ const char *a1, bt type1, int kind1, int optional1,
+ sym_intent intent1, const char *a2, bt type2, int kind2,
+ int optional2, sym_intent intent2)
+{
+ gfc_check_f cf;
+ gfc_simplify_f sf;
+ gfc_resolve_f rf;
+
+ cf.f2 = check;
+ sf.f2 = simplify;
+ rf.s1 = resolve;
+
+ add_sym (name, id, cl, ACTUAL_NO, type, kind, standard, cf, sf, rf,
+ a1, type1, kind1, optional1, intent1,
+ a2, type2, kind2, optional2, intent2,
(void *) 0);
}
@@ -521,9 +605,9 @@ add_sym_3 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt ty
rf.f3 = resolve;
add_sym (name, id, cl, actual_ok, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
- a2, type2, kind2, optional2,
- a3, type3, kind3, optional3,
+ a1, type1, kind1, optional1, INTENT_IN,
+ a2, type2, kind2, optional2, INTENT_IN,
+ a3, type3, kind3, optional3, INTENT_IN,
(void *) 0);
}
@@ -550,9 +634,9 @@ add_sym_3ml (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt
rf.f3 = resolve;
add_sym (name, id, cl, actual_ok, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
- a2, type2, kind2, optional2,
- a3, type3, kind3, optional3,
+ a1, type1, kind1, optional1, INTENT_IN,
+ a2, type2, kind2, optional2, INTENT_IN,
+ a3, type3, kind3, optional3, INTENT_IN,
(void *) 0);
}
@@ -579,9 +663,9 @@ add_sym_3red (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt
rf.f3 = resolve;
add_sym (name, id, cl, actual_ok, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
- a2, type2, kind2, optional2,
- a3, type3, kind3, optional3,
+ a1, type1, kind1, optional1, INTENT_IN,
+ a2, type2, kind2, optional2, INTENT_IN,
+ a3, type3, kind3, optional3, INTENT_IN,
(void *) 0);
}
@@ -607,9 +691,39 @@ add_sym_3s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
rf.s1 = resolve;
add_sym (name, id, cl, ACTUAL_NO, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
- a2, type2, kind2, optional2,
- a3, type3, kind3, optional3,
+ a1, type1, kind1, optional1, INTENT_IN,
+ a2, type2, kind2, optional2, INTENT_IN,
+ a3, type3, kind3, optional3, INTENT_IN,
+ (void *) 0);
+}
+
+
+/* Add a symbol to the subroutine list where the subroutine takes
+ 3 arguments, specifying the intent of the arguments. */
+
+static void
+add_sym_3s_intent (const char *name, gfc_isym_id id, enum klass cl, bt type,
+ int kind, int standard,
+ gfc_try (*check) (gfc_expr *, gfc_expr *, gfc_expr *),
+ gfc_expr *(*simplify) (gfc_expr *, gfc_expr *, gfc_expr *),
+ void (*resolve) (gfc_code *),
+ const char *a1, bt type1, int kind1, int optional1,
+ sym_intent intent1, const char *a2, bt type2, int kind2,
+ int optional2, sym_intent intent2, const char *a3, bt type3,
+ int kind3, int optional3, sym_intent intent3)
+{
+ gfc_check_f cf;
+ gfc_simplify_f sf;
+ gfc_resolve_f rf;
+
+ cf.f3 = check;
+ sf.f3 = simplify;
+ rf.s1 = resolve;
+
+ add_sym (name, id, cl, ACTUAL_NO, type, kind, standard, cf, sf, rf,
+ a1, type1, kind1, optional1, intent1,
+ a2, type2, kind2, optional2, intent2,
+ a3, type3, kind3, optional3, intent3,
(void *) 0);
}
@@ -639,10 +753,10 @@ add_sym_4 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt ty
rf.f4 = resolve;
add_sym (name, id, cl, actual_ok, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
- a2, type2, kind2, optional2,
- a3, type3, kind3, optional3,
- a4, type4, kind4, optional4,
+ a1, type1, kind1, optional1, INTENT_IN,
+ a2, type2, kind2, optional2, INTENT_IN,
+ a3, type3, kind3, optional3, INTENT_IN,
+ a4, type4, kind4, optional4, INTENT_IN,
(void *) 0);
}
@@ -651,15 +765,17 @@ add_sym_4 (const char *name, gfc_isym_id id, enum klass cl, int actual_ok, bt ty
4 arguments. */
static void
-add_sym_4s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind, int standard,
+add_sym_4s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
+ int standard,
gfc_try (*check) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *),
gfc_expr *(*simplify) (gfc_expr *, gfc_expr *, gfc_expr *,
gfc_expr *),
void (*resolve) (gfc_code *),
const char *a1, bt type1, int kind1, int optional1,
- const char *a2, bt type2, int kind2, int optional2,
- const char *a3, bt type3, int kind3, int optional3,
- const char *a4, bt type4, int kind4, int optional4)
+ sym_intent intent1, const char *a2, bt type2, int kind2,
+ int optional2, sym_intent intent2, const char *a3, bt type3,
+ int kind3, int optional3, sym_intent intent3, const char *a4,
+ bt type4, int kind4, int optional4, sym_intent intent4)
{
gfc_check_f cf;
gfc_simplify_f sf;
@@ -670,10 +786,10 @@ add_sym_4s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
rf.s1 = resolve;
add_sym (name, id, cl, ACTUAL_NO, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
- a2, type2, kind2, optional2,
- a3, type3, kind3, optional3,
- a4, type4, kind4, optional4,
+ a1, type1, kind1, optional1, intent1,
+ a2, type2, kind2, optional2, intent2,
+ a3, type3, kind3, optional3, intent3,
+ a4, type4, kind4, optional4, intent4,
(void *) 0);
}
@@ -682,17 +798,20 @@ add_sym_4s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
5 arguments. */
static void
-add_sym_5s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind, int standard,
+add_sym_5s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
+ int standard,
gfc_try (*check) (gfc_expr *, gfc_expr *, gfc_expr *, gfc_expr *,
gfc_expr *),
gfc_expr *(*simplify) (gfc_expr *, gfc_expr *, gfc_expr *,
gfc_expr *, gfc_expr *),
void (*resolve) (gfc_code *),
const char *a1, bt type1, int kind1, int optional1,
- const char *a2, bt type2, int kind2, int optional2,
- const char *a3, bt type3, int kind3, int optional3,
- const char *a4, bt type4, int kind4, int optional4,
- const char *a5, bt type5, int kind5, int optional5)
+ sym_intent intent1, const char *a2, bt type2, int kind2,
+ int optional2, sym_intent intent2, const char *a3, bt type3,
+ int kind3, int optional3, sym_intent intent3, const char *a4,
+ bt type4, int kind4, int optional4, sym_intent intent4,
+ const char *a5, bt type5, int kind5, int optional5,
+ sym_intent intent5)
{
gfc_check_f cf;
gfc_simplify_f sf;
@@ -703,11 +822,11 @@ add_sym_5s (const char *name, gfc_isym_id id, enum klass cl, bt type, int kind,
rf.s1 = resolve;
add_sym (name, id, cl, ACTUAL_NO, type, kind, standard, cf, sf, rf,
- a1, type1, kind1, optional1,
- a2, type2, kind2, optional2,
- a3, type3, kind3, optional3,
- a4, type4, kind4, optional4,
- a5, type5, kind5, optional5,
+ a1, type1, kind1, optional1, intent1,
+ a2, type2, kind2, optional2, intent2,
+ a3, type3, kind3, optional3, intent3,
+ a4, type4, kind4, optional4, intent4,
+ a5, type5, kind5, optional5, intent5,
(void *) 0);
}
@@ -962,7 +1081,8 @@ add_functions (void)
*x = "x", *sh = "shift", *stg = "string", *ssg = "substring",
*y = "y", *sz = "size", *sta = "string_a", *stb = "string_b",
*z = "z", *ln = "len", *ut = "unit", *han = "handler",
- *num = "number", *tm = "time", *nm = "name", *md = "mode";
+ *num = "number", *tm = "time", *nm = "name", *md = "mode",
+ *vl = "values", *p1 = "path1", *p2 = "path2", *com = "command";
int di, dr, dd, dl, dc, dz, ii;
@@ -1431,8 +1551,9 @@ add_functions (void)
make_generic ("erfc", GFC_ISYM_ERFC, GFC_STD_F2008);
add_sym_1 ("erfc_scaled", GFC_ISYM_ERFC_SCALED, CLASS_ELEMENTAL, ACTUAL_NO,
- BT_REAL, dr, GFC_STD_F2008, gfc_check_fn_r, NULL,
- gfc_resolve_g77_math1, x, BT_REAL, dr, REQUIRED);
+ BT_REAL, dr, GFC_STD_F2008, gfc_check_fn_r,
+ gfc_simplify_erfc_scaled, gfc_resolve_g77_math1, x, BT_REAL,
+ dr, REQUIRED);
make_generic ("erfc_scaled", GFC_ISYM_ERFC_SCALED, GFC_STD_F2008);
@@ -1499,9 +1620,9 @@ add_functions (void)
make_generic ("fraction", GFC_ISYM_FRACTION, GFC_STD_F95);
- add_sym_2 ("fstat", GFC_ISYM_FSTAT, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
- gfc_check_fstat, NULL, gfc_resolve_fstat,
- a, BT_INTEGER, di, REQUIRED, b, BT_INTEGER, di, REQUIRED);
+ add_sym_2 ("fstat", GFC_ISYM_FSTAT, NO_CLASS, ACTUAL_NO, BT_INTEGER, di,
+ GFC_STD_GNU, gfc_check_fstat, NULL, gfc_resolve_fstat,
+ ut, BT_INTEGER, di, REQUIRED, vl, BT_INTEGER, di, REQUIRED);
make_generic ("fstat", GFC_ISYM_FSTAT, GFC_STD_GNU);
@@ -1850,9 +1971,9 @@ add_functions (void)
make_generic ("llt", GFC_ISYM_LLT, GFC_STD_F77);
- add_sym_2 ("link", GFC_ISYM_LINK, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
- gfc_check_link, NULL, gfc_resolve_link,
- a, BT_CHARACTER, dc, REQUIRED, b, BT_CHARACTER, dc, REQUIRED);
+ add_sym_2 ("link", GFC_ISYM_LINK, NO_CLASS, ACTUAL_NO, BT_INTEGER, di,
+ GFC_STD_GNU, gfc_check_link, NULL, gfc_resolve_link,
+ p1, BT_CHARACTER, dc, REQUIRED, p2, BT_CHARACTER, dc, REQUIRED);
make_generic ("link", GFC_ISYM_LINK, GFC_STD_GNU);
@@ -1900,15 +2021,15 @@ add_functions (void)
make_generic ("logical", GFC_ISYM_LOGICAL, GFC_STD_F95);
- add_sym_2 ("lstat", GFC_ISYM_LSTAT, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
- gfc_check_stat, NULL, gfc_resolve_lstat,
- a, BT_CHARACTER, dc, REQUIRED, b, BT_INTEGER, di, REQUIRED);
+ add_sym_2 ("lstat", GFC_ISYM_LSTAT, NO_CLASS, ACTUAL_NO, BT_INTEGER, di,
+ GFC_STD_GNU, gfc_check_stat, NULL, gfc_resolve_lstat,
+ nm, BT_CHARACTER, dc, REQUIRED, vl, BT_INTEGER, di, REQUIRED);
make_generic ("lstat", GFC_ISYM_LSTAT, GFC_STD_GNU);
- add_sym_1 ("malloc", GFC_ISYM_MALLOC, NO_CLASS, ACTUAL_NO, BT_INTEGER, ii, GFC_STD_GNU,
- gfc_check_malloc, NULL, gfc_resolve_malloc, a, BT_INTEGER, di,
- REQUIRED);
+ add_sym_1 ("malloc", GFC_ISYM_MALLOC, NO_CLASS, ACTUAL_NO, BT_INTEGER, ii,
+ GFC_STD_GNU, gfc_check_malloc, NULL, gfc_resolve_malloc,
+ sz, BT_INTEGER, di, REQUIRED);
make_generic ("malloc", GFC_ISYM_MALLOC, GFC_STD_GNU);
@@ -1967,13 +2088,13 @@ add_functions (void)
make_generic ("maxval", GFC_ISYM_MAXVAL, GFC_STD_F95);
- add_sym_0 ("mclock", GFC_ISYM_MCLOCK, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
- NULL, NULL, gfc_resolve_mclock);
+ add_sym_0 ("mclock", GFC_ISYM_MCLOCK, NO_CLASS, ACTUAL_NO, BT_INTEGER, di,
+ GFC_STD_GNU, NULL, NULL, gfc_resolve_mclock);
make_generic ("mclock", GFC_ISYM_MCLOCK, GFC_STD_GNU);
- add_sym_0 ("mclock8", GFC_ISYM_MCLOCK8, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
- NULL, NULL, gfc_resolve_mclock8);
+ add_sym_0 ("mclock8", GFC_ISYM_MCLOCK8, NO_CLASS, ACTUAL_NO, BT_INTEGER, di,
+ GFC_STD_GNU, NULL, NULL, gfc_resolve_mclock8);
make_generic ("mclock8", GFC_ISYM_MCLOCK8, GFC_STD_GNU);
@@ -2100,9 +2221,9 @@ add_functions (void)
make_generic ("precision", GFC_ISYM_PRECISION, GFC_STD_F95);
- add_sym_1 ("present", GFC_ISYM_PRESENT, CLASS_INQUIRY, ACTUAL_NO, BT_LOGICAL, dl, GFC_STD_F95,
- gfc_check_present, NULL, NULL,
- a, BT_REAL, dr, REQUIRED);
+ add_sym_1_intent ("present", GFC_ISYM_PRESENT, CLASS_INQUIRY, ACTUAL_NO,
+ BT_LOGICAL, dl, GFC_STD_F95, gfc_check_present, NULL, NULL,
+ a, BT_REAL, dr, REQUIRED, INTENT_UNKNOWN);
make_generic ("present", GFC_ISYM_PRESENT, GFC_STD_F95);
@@ -2155,9 +2276,9 @@ add_functions (void)
make_generic ("real", GFC_ISYM_REAL, GFC_STD_F77);
- add_sym_2 ("rename", GFC_ISYM_RENAME, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
- gfc_check_rename, NULL, gfc_resolve_rename,
- a, BT_CHARACTER, dc, REQUIRED, b, BT_CHARACTER, dc, REQUIRED);
+ add_sym_2 ("rename", GFC_ISYM_RENAME, NO_CLASS, ACTUAL_NO, BT_INTEGER, di,
+ GFC_STD_GNU, gfc_check_rename, NULL, gfc_resolve_rename,
+ p1, BT_CHARACTER, dc, REQUIRED, p2, BT_CHARACTER, dc, REQUIRED);
make_generic ("rename", GFC_ISYM_RENAME, GFC_STD_GNU);
@@ -2338,9 +2459,9 @@ add_functions (void)
make_generic ("sqrt", GFC_ISYM_SQRT, GFC_STD_F77);
- add_sym_2 ("stat", GFC_ISYM_STAT, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
- gfc_check_stat, NULL, gfc_resolve_stat,
- a, BT_CHARACTER, dc, REQUIRED, b, BT_INTEGER, di, REQUIRED);
+ add_sym_2 ("stat", GFC_ISYM_STAT, NO_CLASS, ACTUAL_NO, BT_INTEGER, di,
+ GFC_STD_GNU, gfc_check_stat, NULL, gfc_resolve_stat,
+ nm, BT_CHARACTER, dc, REQUIRED, vl, BT_INTEGER, di, REQUIRED);
make_generic ("stat", GFC_ISYM_STAT, GFC_STD_GNU);
@@ -2351,15 +2472,15 @@ add_functions (void)
make_generic ("sum", GFC_ISYM_SUM, GFC_STD_F95);
- add_sym_2 ("symlnk", GFC_ISYM_SYMLNK, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
- gfc_check_symlnk, NULL, gfc_resolve_symlnk,
- a, BT_CHARACTER, dc, REQUIRED, b, BT_CHARACTER, dc, REQUIRED);
+ add_sym_2 ("symlnk", GFC_ISYM_SYMLNK, NO_CLASS, ACTUAL_NO, BT_INTEGER, di,
+ GFC_STD_GNU, gfc_check_symlnk, NULL, gfc_resolve_symlnk,
+ p1, BT_CHARACTER, dc, REQUIRED, p2, BT_CHARACTER, dc, REQUIRED);
make_generic ("symlnk", GFC_ISYM_SYMLNK, GFC_STD_GNU);
- add_sym_1 ("system", GFC_ISYM_SYSTEM, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
- NULL, NULL, NULL,
- c, BT_CHARACTER, dc, REQUIRED);
+ add_sym_1 ("system", GFC_ISYM_SYSTEM, NO_CLASS, ACTUAL_NO, BT_INTEGER, di,
+ GFC_STD_GNU, NULL, NULL, NULL,
+ com, BT_CHARACTER, dc, REQUIRED);
make_generic ("system", GFC_ISYM_SYSTEM, GFC_STD_GNU);
@@ -2440,16 +2561,16 @@ add_functions (void)
make_generic ("ubound", GFC_ISYM_UBOUND, GFC_STD_F95);
/* g77 compatibility for UMASK. */
- add_sym_1 ("umask", GFC_ISYM_UMASK, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
- gfc_check_umask, NULL, gfc_resolve_umask,
- a, BT_INTEGER, di, REQUIRED);
+ add_sym_1 ("umask", GFC_ISYM_UMASK, NO_CLASS, ACTUAL_NO, BT_INTEGER, di,
+ GFC_STD_GNU, gfc_check_umask, NULL, gfc_resolve_umask,
+ msk, BT_INTEGER, di, REQUIRED);
make_generic ("umask", GFC_ISYM_UMASK, GFC_STD_GNU);
/* g77 compatibility for UNLINK. */
add_sym_1 ("unlink", GFC_ISYM_UNLINK, NO_CLASS, ACTUAL_NO, BT_INTEGER, di, GFC_STD_GNU,
gfc_check_unlink, NULL, gfc_resolve_unlink,
- a, BT_CHARACTER, dc, REQUIRED);
+ "path", BT_CHARACTER, dc, REQUIRED);
make_generic ("unlink", GFC_ISYM_UNLINK, GFC_STD_GNU);
@@ -2468,9 +2589,9 @@ add_functions (void)
make_generic ("verify", GFC_ISYM_VERIFY, GFC_STD_F95);
- add_sym_1 ("loc", GFC_ISYM_LOC, NO_CLASS, ACTUAL_NO, BT_INTEGER, ii, GFC_STD_GNU,
- gfc_check_loc, NULL, gfc_resolve_loc,
- ar, BT_UNKNOWN, 0, REQUIRED);
+ add_sym_1 ("loc", GFC_ISYM_LOC, NO_CLASS, ACTUAL_NO, BT_INTEGER, ii,
+ GFC_STD_GNU, gfc_check_loc, NULL, gfc_resolve_loc,
+ x, BT_UNKNOWN, 0, REQUIRED);
make_generic ("loc", GFC_ISYM_LOC, GFC_STD_GNU);
}
@@ -2491,7 +2612,8 @@ add_subroutines (void)
*val = "value", *num = "number", *name = "name",
*trim_name = "trim_name", *ut = "unit", *han = "handler",
*sec = "seconds", *res = "result", *of = "offset", *md = "mode",
- *whence = "whence", *pos = "pos";
+ *whence = "whence", *pos = "pos", *ptr = "ptr", *p1 = "path1",
+ *p2 = "path2", *msk = "mask", *old = "old";
int di, dr, dc, dl, ii;
@@ -2505,9 +2627,10 @@ add_subroutines (void)
make_noreturn();
- add_sym_1s ("cpu_time", GFC_ISYM_CPU_TIME, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_F95,
- gfc_check_cpu_time, NULL, gfc_resolve_cpu_time,
- tm, BT_REAL, dr, REQUIRED);
+ add_sym_1s_intent ("cpu_time", GFC_ISYM_CPU_TIME, NO_CLASS, BT_UNKNOWN, 0,
+ GFC_STD_F95, gfc_check_cpu_time, NULL,
+ gfc_resolve_cpu_time,
+ tm, BT_REAL, dr, REQUIRED, INTENT_OUT);
/* More G77 compatibility garbage. */
add_sym_2s ("ctime", GFC_ISYM_CTIME, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
@@ -2543,10 +2666,12 @@ add_subroutines (void)
name, BT_CHARACTER, dc, REQUIRED, md, BT_CHARACTER, dc, REQUIRED,
st, BT_INTEGER, di, OPTIONAL);
- add_sym_4s ("date_and_time", GFC_ISYM_DATE_AND_TIME, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_F95,
- gfc_check_date_and_time, NULL, NULL,
- dt, BT_CHARACTER, dc, OPTIONAL, tm, BT_CHARACTER, dc, OPTIONAL,
- zn, BT_CHARACTER, dc, OPTIONAL, vl, BT_INTEGER, di, OPTIONAL);
+ add_sym_4s ("date_and_time", GFC_ISYM_DATE_AND_TIME, NO_CLASS, BT_UNKNOWN, 0,
+ GFC_STD_F95, gfc_check_date_and_time, NULL, NULL,
+ dt, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT,
+ tm, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT,
+ zn, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT,
+ vl, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
/* More G77 compatibility garbage. */
add_sym_2s ("etime", GFC_ISYM_ETIME, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
@@ -2584,46 +2709,56 @@ add_subroutines (void)
/* F2003 commandline routines. */
- add_sym_3s ("get_command", GFC_ISYM_GET_COMMAND, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_F2003,
- NULL, NULL, gfc_resolve_get_command,
- com, BT_CHARACTER, dc, OPTIONAL,
- length, BT_INTEGER, di, OPTIONAL,
- st, BT_INTEGER, di, OPTIONAL);
+ add_sym_3s_intent ("get_command", GFC_ISYM_GET_COMMAND, NO_CLASS, BT_UNKNOWN,
+ 0, GFC_STD_F2003, NULL, NULL, gfc_resolve_get_command,
+ com, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT,
+ length, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+ st, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
- add_sym_4s ("get_command_argument", GFC_ISYM_GET_COMMAND_ARGUMENT, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_F2003,
- NULL, NULL, gfc_resolve_get_command_argument,
- num, BT_INTEGER, di, REQUIRED, val, BT_CHARACTER, dc, OPTIONAL,
- length, BT_INTEGER, di, OPTIONAL, st, BT_INTEGER, di, OPTIONAL);
+ add_sym_4s ("get_command_argument", GFC_ISYM_GET_COMMAND_ARGUMENT, NO_CLASS,
+ BT_UNKNOWN, 0, GFC_STD_F2003, NULL, NULL,
+ gfc_resolve_get_command_argument,
+ num, BT_INTEGER, di, REQUIRED, INTENT_IN,
+ val, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT,
+ length, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+ st, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
/* F2003 subroutine to get environment variables. */
- add_sym_5s ("get_environment_variable", GFC_ISYM_GET_ENVIRONMENT_VARIABLE, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_F2003,
+ add_sym_5s ("get_environment_variable", GFC_ISYM_GET_ENVIRONMENT_VARIABLE,
+ NO_CLASS, BT_UNKNOWN, 0, GFC_STD_F2003,
NULL, NULL, gfc_resolve_get_environment_variable,
- name, BT_CHARACTER, dc, REQUIRED,
- val, BT_CHARACTER, dc, OPTIONAL,
- length, BT_INTEGER, di, OPTIONAL, st, BT_INTEGER, di, OPTIONAL,
- trim_name, BT_LOGICAL, dl, OPTIONAL);
-
- add_sym_2s ("move_alloc", GFC_ISYM_MOVE_ALLOC, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_F2003,
- gfc_check_move_alloc, NULL, NULL,
- f, BT_UNKNOWN, 0, REQUIRED,
- t, BT_UNKNOWN, 0, REQUIRED);
-
- add_sym_5s ("mvbits", GFC_ISYM_MVBITS, CLASS_ELEMENTAL, BT_UNKNOWN, 0, GFC_STD_F95,
- gfc_check_mvbits, gfc_simplify_mvbits, gfc_resolve_mvbits,
- f, BT_INTEGER, di, REQUIRED, fp, BT_INTEGER, di, REQUIRED,
- ln, BT_INTEGER, di, REQUIRED, t, BT_INTEGER, di, REQUIRED,
- tp, BT_INTEGER, di, REQUIRED);
-
- add_sym_1s ("random_number", GFC_ISYM_RANDOM_NUMBER, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_F95,
- gfc_check_random_number, NULL, gfc_resolve_random_number,
- h, BT_REAL, dr, REQUIRED);
-
- add_sym_3s ("random_seed", GFC_ISYM_RANDOM_SEED, NO_CLASS,
- BT_UNKNOWN, 0, GFC_STD_F95,
- gfc_check_random_seed, NULL, gfc_resolve_random_seed,
- sz, BT_INTEGER, di, OPTIONAL, pt, BT_INTEGER, di, OPTIONAL,
- gt, BT_INTEGER, di, OPTIONAL);
+ name, BT_CHARACTER, dc, REQUIRED, INTENT_IN,
+ val, BT_CHARACTER, dc, OPTIONAL, INTENT_OUT,
+ length, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+ st, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+ trim_name, BT_LOGICAL, dl, OPTIONAL, INTENT_IN);
+
+ add_sym_2s_intent ("move_alloc", GFC_ISYM_MOVE_ALLOC, NO_CLASS, BT_UNKNOWN, 0,
+ GFC_STD_F2003, gfc_check_move_alloc, NULL, NULL,
+ f, BT_UNKNOWN, 0, REQUIRED, INTENT_INOUT,
+ t, BT_UNKNOWN, 0, REQUIRED, INTENT_OUT);
+
+ add_sym_5s ("mvbits", GFC_ISYM_MVBITS, CLASS_ELEMENTAL, BT_UNKNOWN, 0,
+ GFC_STD_F95, gfc_check_mvbits, gfc_simplify_mvbits,
+ gfc_resolve_mvbits,
+ f, BT_INTEGER, di, REQUIRED, INTENT_IN,
+ fp, BT_INTEGER, di, REQUIRED, INTENT_IN,
+ ln, BT_INTEGER, di, REQUIRED, INTENT_IN,
+ t, BT_INTEGER, di, REQUIRED, INTENT_INOUT,
+ tp, BT_INTEGER, di, REQUIRED, INTENT_IN);
+
+ add_sym_1s_intent ("random_number", GFC_ISYM_RANDOM_NUMBER, NO_CLASS,
+ BT_UNKNOWN, 0, GFC_STD_F95, gfc_check_random_number, NULL,
+ gfc_resolve_random_number,
+ h, BT_REAL, dr, REQUIRED, INTENT_OUT);
+
+ add_sym_3s_intent ("random_seed", GFC_ISYM_RANDOM_SEED, NO_CLASS,
+ BT_UNKNOWN, 0, GFC_STD_F95,
+ gfc_check_random_seed, NULL, gfc_resolve_random_seed,
+ sz, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+ pt, BT_INTEGER, di, OPTIONAL, INTENT_IN,
+ gt, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
/* More G77 compatibility garbage. */
add_sym_3s ("alarm", GFC_ISYM_ALARM, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
@@ -2633,7 +2768,7 @@ add_subroutines (void)
add_sym_1s ("srand", GFC_ISYM_SRAND, NO_CLASS, BT_UNKNOWN, di, GFC_STD_GNU,
gfc_check_srand, NULL, gfc_resolve_srand,
- c, BT_INTEGER, 4, REQUIRED);
+ "seed", BT_INTEGER, 4, REQUIRED);
add_sym_1s ("exit", GFC_ISYM_EXIT, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_exit, NULL, gfc_resolve_exit,
@@ -2663,13 +2798,16 @@ add_subroutines (void)
gfc_check_fgetput_sub, NULL, gfc_resolve_fput_sub,
c, BT_CHARACTER, dc, REQUIRED, st, BT_INTEGER, di, OPTIONAL);
- add_sym_1s ("free", GFC_ISYM_FREE, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU, gfc_check_free,
- NULL, gfc_resolve_free, c, BT_INTEGER, ii, REQUIRED);
+ add_sym_1s ("free", GFC_ISYM_FREE, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
+ gfc_check_free, NULL, gfc_resolve_free,
+ ptr, BT_INTEGER, ii, REQUIRED);
add_sym_4s ("fseek", GFC_ISYM_FSEEK, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_fseek_sub, NULL, gfc_resolve_fseek_sub,
- ut, BT_INTEGER, di, REQUIRED, of, BT_INTEGER, di, REQUIRED,
- whence, BT_INTEGER, di, REQUIRED, st, BT_INTEGER, di, OPTIONAL);
+ ut, BT_INTEGER, di, REQUIRED, INTENT_IN,
+ of, BT_INTEGER, di, REQUIRED, INTENT_IN,
+ whence, BT_INTEGER, di, REQUIRED, INTENT_IN,
+ st, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
add_sym_2s ("ftell", GFC_ISYM_FTELL, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_ftell_sub, NULL, gfc_resolve_ftell_sub,
@@ -2685,21 +2823,21 @@ add_subroutines (void)
add_sym_3s ("link", GFC_ISYM_LINK, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_link_sub, NULL, gfc_resolve_link_sub,
- name, BT_CHARACTER, dc, REQUIRED, val, BT_CHARACTER,
+ p1, BT_CHARACTER, dc, REQUIRED, p2, BT_CHARACTER,
dc, REQUIRED, st, BT_INTEGER, di, OPTIONAL);
add_sym_1s ("perror", GFC_ISYM_PERROR, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_perror, NULL, gfc_resolve_perror,
- c, BT_CHARACTER, dc, REQUIRED);
+ "string", BT_CHARACTER, dc, REQUIRED);
add_sym_3s ("rename", GFC_ISYM_RENAME, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_rename_sub, NULL, gfc_resolve_rename_sub,
- name, BT_CHARACTER, dc, REQUIRED, val, BT_CHARACTER,
+ p1, BT_CHARACTER, dc, REQUIRED, p2, BT_CHARACTER,
dc, REQUIRED, st, BT_INTEGER, di, OPTIONAL);
add_sym_1s ("sleep", GFC_ISYM_SLEEP, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_sleep_sub, NULL, gfc_resolve_sleep_sub,
- val, BT_INTEGER, di, REQUIRED);
+ sec, BT_INTEGER, di, REQUIRED);
add_sym_3s ("fstat", GFC_ISYM_FSTAT, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_fstat_sub, NULL, gfc_resolve_fstat_sub,
@@ -2723,17 +2861,19 @@ add_subroutines (void)
add_sym_3s ("symlnk", GFC_ISYM_SYMLINK, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_symlnk_sub, NULL, gfc_resolve_symlnk_sub,
- name, BT_CHARACTER, dc, REQUIRED, val, BT_CHARACTER,
+ p1, BT_CHARACTER, dc, REQUIRED, p2, BT_CHARACTER,
dc, REQUIRED, st, BT_INTEGER, di, OPTIONAL);
add_sym_2s ("system", GFC_ISYM_SYSTEM, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
NULL, NULL, gfc_resolve_system_sub,
com, BT_CHARACTER, dc, REQUIRED, st, BT_INTEGER, di, OPTIONAL);
- add_sym_3s ("system_clock", GFC_ISYM_SYSTEM_CLOCK, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_F95,
- gfc_check_system_clock, NULL, gfc_resolve_system_clock,
- c, BT_INTEGER, di, OPTIONAL, cr, BT_INTEGER, di, OPTIONAL,
- cm, BT_INTEGER, di, OPTIONAL);
+ add_sym_3s_intent ("system_clock", GFC_ISYM_SYSTEM_CLOCK, NO_CLASS,
+ BT_UNKNOWN, 0, GFC_STD_F95,
+ gfc_check_system_clock, NULL, gfc_resolve_system_clock,
+ c, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+ cr, BT_INTEGER, di, OPTIONAL, INTENT_OUT,
+ cm, BT_INTEGER, di, OPTIONAL, INTENT_OUT);
add_sym_2s ("ttynam", GFC_ISYM_TTYNAM, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_ttynam_sub, NULL, gfc_resolve_ttynam_sub,
@@ -2741,11 +2881,11 @@ add_subroutines (void)
add_sym_2s ("umask", GFC_ISYM_UMASK, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_umask_sub, NULL, gfc_resolve_umask_sub,
- val, BT_INTEGER, di, REQUIRED, num, BT_INTEGER, di, OPTIONAL);
+ msk, BT_INTEGER, di, REQUIRED, old, BT_INTEGER, di, OPTIONAL);
add_sym_2s ("unlink", GFC_ISYM_UNLINK, NO_CLASS, BT_UNKNOWN, 0, GFC_STD_GNU,
gfc_check_unlink_sub, NULL, gfc_resolve_unlink_sub,
- c, BT_CHARACTER, dc, REQUIRED, st, BT_INTEGER, di, OPTIONAL);
+ "path", BT_CHARACTER, dc, REQUIRED, st, BT_INTEGER, di, OPTIONAL);
}
diff --git a/gcc/fortran/intrinsic.h b/gcc/fortran/intrinsic.h
index 83c5207785b..7e8bc73ec6f 100644
--- a/gcc/fortran/intrinsic.h
+++ b/gcc/fortran/intrinsic.h
@@ -232,6 +232,7 @@ gfc_expr *gfc_simplify_dprod (gfc_expr *, gfc_expr *);
gfc_expr *gfc_simplify_epsilon (gfc_expr *);
gfc_expr *gfc_simplify_erf (gfc_expr *);
gfc_expr *gfc_simplify_erfc (gfc_expr *);
+gfc_expr *gfc_simplify_erfc_scaled (gfc_expr *);
gfc_expr *gfc_simplify_exp (gfc_expr *);
gfc_expr *gfc_simplify_exponent (gfc_expr *);
gfc_expr *gfc_simplify_float (gfc_expr *);
diff --git a/gcc/fortran/intrinsic.texi b/gcc/fortran/intrinsic.texi
index 06cdff0c828..d560af78b37 100644
--- a/gcc/fortran/intrinsic.texi
+++ b/gcc/fortran/intrinsic.texi
@@ -167,7 +167,6 @@ Some basic guidelines for editing this document:
* @code{LEADZ}: LEADZ, Number of leading zero bits of an integer
* @code{LEN}: LEN, Length of a character entity
* @code{LEN_TRIM}: LEN_TRIM, Length of a character entity without trailing blank characters
-* @code{LOG_GAMMA}: LOG_GAMMA, Logarithm of the Gamma function
* @code{LGE}: LGE, Lexical greater than or equal
* @code{LGT}: LGT, Lexical greater than
* @code{LINK}: LINK, Create a hard link
@@ -177,6 +176,7 @@ Some basic guidelines for editing this document:
* @code{LOC}: LOC, Returns the address of a variable
* @code{LOG}: LOG, Logarithm function
* @code{LOG10}: LOG10, Base 10 logarithm function
+* @code{LOG_GAMMA}: LOG_GAMMA, Logarithm of the Gamma function
* @code{LOGICAL}: LOGICAL, Convert to logical type
* @code{LONG}: LONG, Convert to integer type
* @code{LSHIFT}: LSHIFT, Left shift bits
@@ -1435,7 +1435,7 @@ end program test_atan2
@item @emph{Specific names}:
@multitable @columnfractions .20 .20 .20 .25
@item Name @tab Argument @tab Return type @tab Standard
-@item @code{DATAN2(X)} @tab @code{REAL(8) X} @tab @code{REAL(8)} @tab Fortran 77 and later
+@item @code{DATAN2(X, Y)} @tab @code{REAL(8) X}, @code{REAL(8) Y} @tab @code{REAL(8)} @tab Fortran 77 and later
@end multitable
@end table
@@ -1634,9 +1634,9 @@ end program test_besjn
@item @emph{Specific names}:
@multitable @columnfractions .20 .20 .20 .25
-@item Name @tab Argument @tab Return type @tab Standard
-@item @code{DBESJN(X)} @tab @code{INTEGER N} @tab @code{REAL(8)} @tab GNU extension
-@item @tab @code{REAL(8) X} @tab @tab
+@item Name @tab Argument @tab Return type @tab Standard
+@item @code{DBESJN(N, X)} @tab @code{INTEGER N} @tab @code{REAL(8)} @tab GNU extension
+@item @tab @code{REAL(8) X} @tab @tab
@end multitable
@end table
@@ -2488,7 +2488,7 @@ Inquiry function
@end multitable
@item @emph{Return value}:
-The return value is of type @code{INTEGER(4)}
+The return value is an @code{INTEGER} of default kind.
@item @emph{Example}:
@smallexample
@@ -3397,11 +3397,11 @@ end program test_dreal
@table @asis
@item @emph{Description}:
-@code{DTIME(TARRAY, RESULT)} initially returns the number of seconds of runtime
-since the start of the process's execution in @var{RESULT}. @var{TARRAY}
-returns the user and system components of this time in @code{TARRAY(1)} and
-@code{TARRAY(2)} respectively. @var{RESULT} is equal to @code{TARRAY(1) +
-TARRAY(2)}.
+@code{DTIME(VALUES, TIME)} initially returns the number of seconds of runtime
+since the start of the process's execution in @var{TIME}. @var{VALUES}
+returns the user and system components of this time in @code{VALUES(1)} and
+@code{VALUES(2)} respectively. @var{TIME} is equal to @code{VALUES(1) +
+VALUES(2)}.
Subsequent invocations of @code{DTIME} return values accumulated since the
previous invocation.
@@ -3421,12 +3421,12 @@ results. If possible, use @code{CPU_TIME} instead.
This intrinsic is provided in both subroutine and function forms; however,
only one form can be used in any given program unit.
-@var{TARRAY} and @var{RESULT} are @code{INTENT(OUT)} and provide the following:
+@var{VALUES} and @var{TIME} are @code{INTENT(OUT)} and provide the following:
@multitable @columnfractions .15 .30 .40
-@item @tab @code{TARRAY(1)}: @tab User time in seconds.
-@item @tab @code{TARRAY(2)}: @tab System time in seconds.
-@item @tab @code{RESULT}: @tab Run time since start in seconds.
+@item @tab @code{VALUES(1)}: @tab User time in seconds.
+@item @tab @code{VALUES(2)}: @tab System time in seconds.
+@item @tab @code{TIME}: @tab Run time since start in seconds.
@end multitable
@item @emph{Standard}:
@@ -3437,14 +3437,14 @@ Subroutine, function
@item @emph{Syntax}:
@multitable @columnfractions .80
-@item @code{CALL DTIME(TARRAY, RESULT)}.
-@item @code{RESULT = DTIME(TARRAY)}, (not recommended).
+@item @code{CALL DTIME(VALUES, TIME)}.
+@item @code{TIME = DTIME(VALUES)}, (not recommended).
@end multitable
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{TARRAY}@tab The type shall be @code{REAL, DIMENSION(2)}.
-@item @var{RESULT}@tab The type shall be @code{REAL}.
+@item @var{VALUES}@tab The type shall be @code{REAL, DIMENSION(2)}.
+@item @var{TIME}@tab The type shall be @code{REAL}.
@end multitable
@item @emph{Return value}:
@@ -3716,10 +3716,10 @@ end program test_erfc_scaled
@table @asis
@item @emph{Description}:
-@code{ETIME(TARRAY, RESULT)} returns the number of seconds of runtime
-since the start of the process's execution in @var{RESULT}. @var{TARRAY}
-returns the user and system components of this time in @code{TARRAY(1)} and
-@code{TARRAY(2)} respectively. @var{RESULT} is equal to @code{TARRAY(1) + TARRAY(2)}.
+@code{ETIME(VALUES, TIME)} returns the number of seconds of runtime
+since the start of the process's execution in @var{TIME}. @var{VALUES}
+returns the user and system components of this time in @code{VALUES(1)} and
+@code{VALUES(2)} respectively. @var{TIME} is equal to @code{VALUES(1) + VALUES(2)}.
On some systems, the underlying timings are represented using types with
sufficiently small limits that overflows (wrap around) are possible, such as
@@ -3730,12 +3730,12 @@ run of the compiled program.
This intrinsic is provided in both subroutine and function forms; however,
only one form can be used in any given program unit.
-@var{TARRAY} and @var{RESULT} are @code{INTENT(OUT)} and provide the following:
+@var{VALUES} and @var{TIME} are @code{INTENT(OUT)} and provide the following:
@multitable @columnfractions .15 .30 .60
-@item @tab @code{TARRAY(1)}: @tab User time in seconds.
-@item @tab @code{TARRAY(2)}: @tab System time in seconds.
-@item @tab @code{RESULT}: @tab Run time since start in seconds.
+@item @tab @code{VALUES(1)}: @tab User time in seconds.
+@item @tab @code{VALUES(2)}: @tab System time in seconds.
+@item @tab @code{TIME}: @tab Run time since start in seconds.
@end multitable
@item @emph{Standard}:
@@ -3746,14 +3746,14 @@ Subroutine, function
@item @emph{Syntax}:
@multitable @columnfractions .80
-@item @code{CALL ETIME(TARRAY, RESULT)}.
-@item @code{RESULT = ETIME(TARRAY)}, (not recommended).
+@item @code{CALL ETIME(VALUES, TIME)}.
+@item @code{TIME = ETIME(VALUES)}, (not recommended).
@end multitable
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{TARRAY}@tab The type shall be @code{REAL, DIMENSION(2)}.
-@item @var{RESULT}@tab The type shall be @code{REAL}.
+@item @var{VALUES}@tab The type shall be @code{REAL, DIMENSION(2)}.
+@item @var{TIME}@tab The type shall be @code{REAL}.
@end multitable
@item @emph{Return value}:
@@ -4557,7 +4557,7 @@ END PROGRAM
@code{FSTAT} is identical to @ref{STAT}, except that information about an
already opened file is obtained.
-The elements in @code{BUFF} are the same as described by @ref{STAT}.
+The elements in @code{VALUES} are the same as described by @ref{STAT}.
This intrinsic is provided in both subroutine and function forms; however,
only one form can be used in any given program unit.
@@ -4569,12 +4569,12 @@ GNU extension
Subroutine, function
@item @emph{Syntax}:
-@code{CALL FSTAT(UNIT, BUFF [, STATUS])}
+@code{CALL FSTAT(UNIT, VALUES [, STATUS])}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@item @var{UNIT} @tab An open I/O unit number of type @code{INTEGER}.
-@item @var{BUFF} @tab The type shall be @code{INTEGER(4), DIMENSION(13)}.
+@item @var{VALUES} @tab The type shall be @code{INTEGER(4), DIMENSION(13)}.
@item @var{STATUS} @tab (Optional) status flag of type @code{INTEGER(4)}. Returns 0
on success and a system specific error code otherwise.
@end multitable
@@ -4817,18 +4817,24 @@ Fortran 2003 and later
Subroutine
@item @emph{Syntax}:
-@code{CALL GET_COMMAND(COMMAND)}
+@code{CALL GET_COMMAND([COMMAND, LENGTH, STATUS])}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{COMMAND} @tab Shall be of type @code{CHARACTER} and of default
-kind.
+@item @var{COMMAND} @tab (Optional) shall be of type @code{CHARACTER} and
+of default kind.
+@item @var{LENGTH} @tab (Optional) Shall be of type @code{INTEGER} and of
+default kind.
+@item @var{STATUS} @tab (Optional) Shall be of type @code{INTEGER} and of
+default kind.
@end multitable
@item @emph{Return value}:
-Stores the entire command line that was used to invoke the program in
-@var{COMMAND}. If @var{COMMAND} is not large enough, the command will be
-truncated.
+If @var{COMMAND} is present, stores the entire command line that was used
+to invoke the program in @var{COMMAND}. If @var{LENGTH} is present, it is
+assigned the length of the command line. If @var{STATUS} is present, it
+is assigned 0 upon success of the command, -1 if @var{COMMAND} is too
+short to store the command line, or a positive value in case of an error.
@item @emph{Example}:
@smallexample
@@ -4867,12 +4873,14 @@ Subroutine
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{NUMBER} @tab Shall be a scalar of type @code{INTEGER(4)},
-@math{@var{NUMBER} \geq 0}
+@item @var{NUMBER} @tab Shall be a scalar of type @code{INTEGER} and of
+default kind, @math{@var{NUMBER} \geq 0}
@item @var{VALUE} @tab Shall be a scalar of type @code{CHARACTER}
and of default kind.
-@item @var{LENGTH} @tab (Option) Shall be a scalar of type @code{INTEGER(4)}.
-@item @var{STATUS} @tab (Option) Shall be a scalar of type @code{INTEGER(4)}.
+@item @var{LENGTH} @tab (Option) Shall be a scalar of type @code{INTEGER}
+and of default kind.
+@item @var{STATUS} @tab (Option) Shall be a scalar of type @code{INTEGER}
+and of default kind.
@end multitable
@item @emph{Return value}:
@@ -5022,11 +5030,16 @@ Subroutine
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{NAME} @tab Shall be a scalar of type @code{CHARACTER(1)}.
-@item @var{VALUE} @tab Shall be a scalar of type @code{CHARACTER(1)}.
-@item @var{LENGTH} @tab Shall be a scalar of type @code{INTEGER(4)}.
-@item @var{STATUS} @tab Shall be a scalar of type @code{INTEGER(4)}.
-@item @var{TRIM_NAME} @tab Shall be a scalar of type @code{LOGICAL(4)}.
+@item @var{NAME} @tab Shall be a scalar of type @code{CHARACTER}
+and of default kind.
+@item @var{VALUE} @tab Shall be a scalar of type @code{CHARACTER}
+and of default kind.
+@item @var{LENGTH} @tab Shall be a scalar of type @code{INTEGER}
+and of default kind.
+@item @var{STATUS} @tab Shall be a scalar of type @code{INTEGER}
+and of default kind.
+@item @var{TRIM_NAME} @tab Shall be a scalar of type @code{LOGICAL}
+and of default kind.
@end multitable
@item @emph{Return value}:
@@ -5707,9 +5720,9 @@ end program read_val
@table @asis
@item @emph{Description}:
-@code{IDATE(TARRAY)} Fills @var{TARRAY} with the numerical values at the
+@code{IDATE(VALUES)} Fills @var{VALUES} with the numerical values at the
current local time. The day (in the range 1-31), month (in the range 1-12),
-and year appear in elements 1, 2, and 3 of @var{TARRAY}, respectively.
+and year appear in elements 1, 2, and 3 of @var{VALUES}, respectively.
The year has four significant digits.
@item @emph{Standard}:
@@ -7212,13 +7225,14 @@ The return value is of type @code{INTEGER} and of the same kind as
@table @asis
@item @emph{Description}:
-@code{LSTAT} is identical to @ref{STAT}, except that if path is a symbolic link,
-then the link itself is statted, not the file that it refers to.
+@code{LSTAT} is identical to @ref{STAT}, except that if path is a
+symbolic link, then the link itself is statted, not the file that it
+refers to.
-The elements in @code{BUFF} are the same as described by @ref{STAT}.
+The elements in @code{VALUES} are the same as described by @ref{STAT}.
-This intrinsic is provided in both subroutine and function forms; however,
-only one form can be used in any given program unit.
+This intrinsic is provided in both subroutine and function forms;
+however, only one form can be used in any given program unit.
@item @emph{Standard}:
GNU extension
@@ -7227,13 +7241,13 @@ GNU extension
Subroutine, function
@item @emph{Syntax}:
-@code{CALL LSTAT(FILE, BUFF [, STATUS])}
+@code{CALL LSTAT(NAME, VALUES [, STATUS])}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{FILE} @tab The type shall be @code{CHARACTER} of the default
+@item @var{NAME} @tab The type shall be @code{CHARACTER} of the default
kind, a valid path within the file system.
-@item @var{BUFF} @tab The type shall be @code{INTEGER(4), DIMENSION(13)}.
+@item @var{VALUES} @tab The type shall be @code{INTEGER(4), DIMENSION(13)}.
@item @var{STATUS} @tab (Optional) status flag of type @code{INTEGER(4)}.
Returns 0 on success and a system specific error code otherwise.
@end multitable
@@ -7254,8 +7268,8 @@ To stat an open file: @ref{FSTAT}, to stat a file: @ref{STAT}
@table @asis
@item @emph{Description}:
-Given a system time value @var{STIME} (as provided by the @code{TIME8()}
-intrinsic), fills @var{TARRAY} with values extracted from it appropriate
+Given a system time value @var{TIME} (as provided by the @code{TIME8()}
+intrinsic), fills @var{VALUES} with values extracted from it appropriate
to the local time zone using @code{localtime(3)}.
@item @emph{Standard}:
@@ -7265,18 +7279,18 @@ GNU extension
Subroutine
@item @emph{Syntax}:
-@code{CALL LTIME(STIME, TARRAY)}
+@code{CALL LTIME(TIME, VALUES)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{STIME} @tab An @code{INTEGER} scalar expression
+@item @var{TIME} @tab An @code{INTEGER} scalar expression
corresponding to a system time, with @code{INTENT(IN)}.
-@item @var{TARRAY} @tab A default @code{INTEGER} array with 9 elements,
+@item @var{VALUES} @tab A default @code{INTEGER} array with 9 elements,
with @code{INTENT(OUT)}.
@end multitable
@item @emph{Return value}:
-The elements of @var{TARRAY} are assigned as follows:
+The elements of @var{VALUES} are assigned as follows:
@enumerate
@item Seconds after the minute, range 0--59 or 0--61 to allow for leap
seconds
@@ -8046,8 +8060,8 @@ end program
@table @asis
@item @emph{Description}:
-@code{MOVE_ALLOC(SRC, DEST)} moves the allocation from @var{SRC} to
-@var{DEST}. @var{SRC} will become deallocated in the process.
+@code{MOVE_ALLOC(FROM, TO)} moves the allocation from @var{FROM} to
+@var{TO}. @var{FROM} will become deallocated in the process.
@item @emph{Standard}:
Fortran 2003 and later
@@ -8056,14 +8070,14 @@ Fortran 2003 and later
Subroutine
@item @emph{Syntax}:
-@code{CALL MOVE_ALLOC(SRC, DEST)}
+@code{CALL MOVE_ALLOC(FROM, TO)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{SRC} @tab @code{ALLOCATABLE}, @code{INTENT(INOUT)}, may be
+@item @var{FROM} @tab @code{ALLOCATABLE}, @code{INTENT(INOUT)}, may be
of any type and kind.
-@item @var{DEST} @tab @code{ALLOCATABLE}, @code{INTENT(OUT)}, shall be
-of the same type, kind and rank as @var{SRC}.
+@item @var{TO} @tab @code{ALLOCATABLE}, @code{INTENT(OUT)}, shall be
+of the same type, kind and rank as @var{FROM}.
@end multitable
@item @emph{Return value}:
@@ -8219,7 +8233,7 @@ end program newline
@table @asis
@item @emph{Description}:
-@code{NINT(X)} rounds its argument to the nearest whole number.
+@code{NINT(A)} rounds its argument to the nearest whole number.
@item @emph{Standard}:
Fortran 77 and later, with @var{KIND} argument Fortran 90 and later
@@ -8228,11 +8242,11 @@ Fortran 77 and later, with @var{KIND} argument Fortran 90 and later
Elemental function
@item @emph{Syntax}:
-@code{RESULT = NINT(X [, KIND])}
+@code{RESULT = NINT(A [, KIND])}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{X} @tab The type of the argument shall be @code{REAL}.
+@item @var{A} @tab The type of the argument shall be @code{REAL}.
@item @var{KIND} @tab (Optional) An @code{INTEGER} initialization
expression indicating the kind parameter of the result.
@end multitable
@@ -8368,13 +8382,13 @@ GNU extension
Function
@item @emph{Syntax}:
-@code{RESULT = OR(X, Y)}
+@code{RESULT = OR(I, J)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{X} @tab The type shall be either a scalar @code{INTEGER}
+@item @var{I} @tab The type shall be either a scalar @code{INTEGER}
type or a scalar @code{LOGICAL} type.
-@item @var{Y} @tab The type shall be the same as the type of @var{X}.
+@item @var{J} @tab The type shall be the same as the type of @var{J}.
@end multitable
@item @emph{Return value}:
@@ -8606,8 +8620,10 @@ Fortran 95 and later
Transformational function
@item @emph{Syntax}:
-@code{RESULT = PRODUCT(ARRAY[, MASK])}
-@code{RESULT = PRODUCT(ARRAY, DIM[, MASK])}
+@multitable @columnfractions .80
+@item @code{RESULT = PRODUCT(ARRAY[, MASK])}
+@item @code{RESULT = PRODUCT(ARRAY, DIM[, MASK])}
+@end multitable
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@@ -8732,11 +8748,11 @@ GNU extension
Function
@item @emph{Syntax}:
-@code{RESULT = RAND(FLAG)}
+@code{RESULT = RAND(I)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{FLAG} @tab Shall be a scalar @code{INTEGER} of kind 4.
+@item @var{I} @tab Shall be a scalar @code{INTEGER} of kind 4.
@end multitable
@item @emph{Return value}:
@@ -8839,7 +8855,7 @@ Fortran 95 and later
Subroutine
@item @emph{Syntax}:
-@code{CALL RANDOM_SEED(SIZE, PUT, GET)}
+@code{CALL RANDOM_SEED([SIZE, PUT, GET])}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@@ -8924,8 +8940,8 @@ See @code{PRECISION} for an example.
@table @asis
@item @emph{Description}:
-@code{REAL(X [, KIND])} converts its argument @var{X} to a real type. The
-@code{REALPART(X)} function is provided for compatibility with @command{g77},
+@code{REAL(A [, KIND])} converts its argument @var{A} to a real type. The
+@code{REALPART} function is provided for compatibility with @command{g77},
and its use is strongly discouraged.
@item @emph{Standard}:
@@ -8936,13 +8952,13 @@ Elemental function
@item @emph{Syntax}:
@multitable @columnfractions .80
-@item @code{RESULT = REAL(X [, KIND])}
+@item @code{RESULT = REAL(A [, KIND])}
@item @code{RESULT = REALPART(Z)}
@end multitable
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{X} @tab Shall be @code{INTEGER}, @code{REAL}, or
+@item @var{A} @tab Shall be @code{INTEGER}, @code{REAL}, or
@code{COMPLEX}.
@item @var{KIND} @tab (Optional) An @code{INTEGER} initialization
expression indicating the kind parameter of the result.
@@ -8954,14 +8970,14 @@ the following rules:
@table @asis
@item (A)
-@code{REAL(X)} is converted to a default real type if @var{X} is an
+@code{REAL(A)} is converted to a default real type if @var{A} is an
integer or real variable.
@item (B)
-@code{REAL(X)} is converted to a real type with the kind type parameter
-of @var{X} if @var{X} is a complex variable.
+@code{REAL(A)} is converted to a real type with the kind type parameter
+of @var{A} if @var{A} is a complex variable.
@item (C)
-@code{REAL(X, KIND)} is converted to a real type with kind type
-parameter @var{KIND} if @var{X} is a complex, integer, or real
+@code{REAL(A, KIND)} is converted to a real type with kind type
+parameter @var{KIND} if @var{A} is a complex, integer, or real
variable.
@end table
@@ -9432,9 +9448,9 @@ end program ascii_kind
@table @asis
@item @emph{Description}:
-@code{SELECTED_INT_KIND(I)} return the kind value of the smallest integer
-type that can represent all values ranging from @math{-10^I} (exclusive)
-to @math{10^I} (exclusive). If there is no integer kind that accommodates
+@code{SELECTED_INT_KIND(R)} return the kind value of the smallest integer
+type that can represent all values ranging from @math{-10^R} (exclusive)
+to @math{10^R} (exclusive). If there is no integer kind that accommodates
this range, @code{SELECTED_INT_KIND} returns @math{-1}.
@item @emph{Standard}:
@@ -9444,11 +9460,11 @@ Fortran 95 and later
Transformational function
@item @emph{Syntax}:
-@code{RESULT = SELECTED_INT_KIND(I)}
+@code{RESULT = SELECTED_INT_KIND(R)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{I} @tab Shall be a scalar and of type @code{INTEGER}.
+@item @var{R} @tab Shall be a scalar and of type @code{INTEGER}.
@end multitable
@item @emph{Example}:
@@ -9489,7 +9505,7 @@ Fortran 95 and later
Transformational function
@item @emph{Syntax}:
-@code{RESULT = SELECTED_REAL_KIND(P, R)}
+@code{RESULT = SELECTED_REAL_KIND([P, R])}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@@ -10212,21 +10228,21 @@ This function returns information about a file. No permissions are required on
the file itself, but execute (search) permission is required on all of the
directories in path that lead to the file.
-The elements that are obtained and stored in the array @code{BUFF}:
+The elements that are obtained and stored in the array @code{VALUES}:
@multitable @columnfractions .15 .70
-@item @code{buff(1)} @tab Device ID
-@item @code{buff(2)} @tab Inode number
-@item @code{buff(3)} @tab File mode
-@item @code{buff(4)} @tab Number of links
-@item @code{buff(5)} @tab Owner's uid
-@item @code{buff(6)} @tab Owner's gid
-@item @code{buff(7)} @tab ID of device containing directory entry for file (0 if not available)
-@item @code{buff(8)} @tab File size (bytes)
-@item @code{buff(9)} @tab Last access time
-@item @code{buff(10)} @tab Last modification time
-@item @code{buff(11)} @tab Last file status change time
-@item @code{buff(12)} @tab Preferred I/O block size (-1 if not available)
-@item @code{buff(13)} @tab Number of blocks allocated (-1 if not available)
+@item @code{VALUES(1)} @tab Device ID
+@item @code{VALUES(2)} @tab Inode number
+@item @code{VALUES(3)} @tab File mode
+@item @code{VALUES(4)} @tab Number of links
+@item @code{VALUES(5)} @tab Owner's uid
+@item @code{VALUES(6)} @tab Owner's gid
+@item @code{VALUES(7)} @tab ID of device containing directory entry for file (0 if not available)
+@item @code{VALUES(8)} @tab File size (bytes)
+@item @code{VALUES(9)} @tab Last access time
+@item @code{VALUES(10)} @tab Last modification time
+@item @code{VALUES(11)} @tab Last file status change time
+@item @code{VALUES(12)} @tab Preferred I/O block size (-1 if not available)
+@item @code{VALUES(13)} @tab Number of blocks allocated (-1 if not available)
@end multitable
Not all these elements are relevant on all systems.
@@ -10242,13 +10258,13 @@ GNU extension
Subroutine, function
@item @emph{Syntax}:
-@code{CALL STAT(FILE,BUFF[,STATUS])}
+@code{CALL STAT(NAME, VALUES [, STATUS])}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{FILE} @tab The type shall be @code{CHARACTER}, of the
+@item @var{NAME} @tab The type shall be @code{CHARACTER}, of the
default kind and a valid path within the file system.
-@item @var{BUFF} @tab The type shall be @code{INTEGER(4), DIMENSION(13)}.
+@item @var{VALUES} @tab The type shall be @code{INTEGER(4), DIMENSION(13)}.
@item @var{STATUS} @tab (Optional) status flag of type @code{INTEGER(4)}. Returns 0
on success and a system specific error code otherwise.
@end multitable
@@ -10305,8 +10321,10 @@ Fortran 95 and later
Transformational function
@item @emph{Syntax}:
-@code{RESULT = SUM(ARRAY[, MASK])}
-@code{RESULT = SUM(ARRAY, DIM[, MASK])}
+@multitable @columnfractions .80
+@item @code{RESULT = SUM(ARRAY[, MASK])}
+@item @code{RESULT = SUM(ARRAY, DIM[, MASK])}
+@end multitable
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@@ -10965,22 +10983,24 @@ the relevant dimension.
@table @asis
@item @emph{Description}:
-Sets the file creation mask to @var{MASK} and returns the old value in
-argument @var{OLD} if it is supplied. See @code{umask(2)}.
+Sets the file creation mask to @var{MASK}. If called as a function, it
+returns the old value. If called as a subroutine and argument @var{OLD}
+if it is supplied, it is set to the old value. See @code{umask(2)}.
@item @emph{Standard}:
GNU extension
@item @emph{Class}:
-Subroutine
+Subroutine, function
@item @emph{Syntax}:
@code{CALL UMASK(MASK [, OLD])}
+@code{OLD = UMASK(MASK)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
@item @var{MASK} @tab Shall be a scalar of type @code{INTEGER}.
-@item @var{MASK} @tab (Optional) Shall be a scalar of type
+@item @var{OLD} @tab (Optional) Shall be a scalar of type
@code{INTEGER}.
@end multitable
@@ -11154,13 +11174,13 @@ GNU extension
Function
@item @emph{Syntax}:
-@code{RESULT = XOR(X, Y)}
+@code{RESULT = XOR(I, J)}
@item @emph{Arguments}:
@multitable @columnfractions .15 .70
-@item @var{X} @tab The type shall be either a scalar @code{INTEGER}
+@item @var{I} @tab The type shall be either a scalar @code{INTEGER}
type or a scalar @code{LOGICAL} type.
-@item @var{Y} @tab The type shall be the same as the type of @var{I}.
+@item @var{J} @tab The type shall be the same as the type of @var{I}.
@end multitable
@item @emph{Return value}:
diff --git a/gcc/fortran/iso-c-binding.def b/gcc/fortran/iso-c-binding.def
index 98c3c982267..94c12fd09af 100644
--- a/gcc/fortran/iso-c-binding.def
+++ b/gcc/fortran/iso-c-binding.def
@@ -56,41 +56,44 @@ NAMED_INTCST (ISOCBINDING_LONG_LONG, "c_long_long", \
NAMED_INTCST (ISOCBINDING_INTMAX_T, "c_intmax_t", \
get_int_kind_from_node (intmax_type_node), GFC_STD_F2003)
NAMED_INTCST (ISOCBINDING_INTPTR_T, "c_intptr_t", \
- get_int_kind_from_node (ptr_type_node), GFC_STD_F2003)
+ get_int_kind_from_name (INTPTR_TYPE), GFC_STD_F2003)
NAMED_INTCST (ISOCBINDING_SIZE_T, "c_size_t", \
gfc_index_integer_kind, GFC_STD_F2003)
NAMED_INTCST (ISOCBINDING_SIGNED_CHAR, "c_signed_char", \
get_int_kind_from_node (signed_char_type_node), GFC_STD_F2003)
-NAMED_INTCST (ISOCBINDING_INT8_T, "c_int8_t", get_int_kind_from_width (8), \
- GFC_STD_F2003)
-NAMED_INTCST (ISOCBINDING_INT16_T, "c_int16_t", get_int_kind_from_width (16), \
- GFC_STD_F2003)
-NAMED_INTCST (ISOCBINDING_INT32_T, "c_int32_t", get_int_kind_from_width (32), \
- GFC_STD_F2003)
-NAMED_INTCST (ISOCBINDING_INT64_T, "c_int64_t", get_int_kind_from_width (64), \
- GFC_STD_F2003)
+NAMED_INTCST (ISOCBINDING_INT8_T, "c_int8_t", \
+ get_int_kind_from_name (INT8_TYPE), GFC_STD_F2003)
+NAMED_INTCST (ISOCBINDING_INT16_T, "c_int16_t", \
+ get_int_kind_from_name (INT16_TYPE), GFC_STD_F2003)
+NAMED_INTCST (ISOCBINDING_INT32_T, "c_int32_t", \
+ get_int_kind_from_name (INT32_TYPE), GFC_STD_F2003)
+NAMED_INTCST (ISOCBINDING_INT64_T, "c_int64_t", \
+ get_int_kind_from_name (INT64_TYPE), GFC_STD_F2003)
/* GNU Extension. */
-NAMED_INTCST (ISOCBINDING_INT128_T, "c_int128_t", get_int_kind_from_width (128), \
- GFC_STD_GNU)
+NAMED_INTCST (ISOCBINDING_INT128_T, "c_int128_t", \
+ get_int_kind_from_width (128), GFC_STD_GNU)
NAMED_INTCST (ISOCBINDING_INT_LEAST8_T, "c_int_least8_t", \
- get_int_kind_from_minimal_width (8), GFC_STD_F2003)
+ get_int_kind_from_name (INT_LEAST8_TYPE), GFC_STD_F2003)
NAMED_INTCST (ISOCBINDING_INT_LEAST16_T, "c_int_least16_t", \
- get_int_kind_from_minimal_width (16), GFC_STD_F2003)
+ get_int_kind_from_name (INT_LEAST16_TYPE), GFC_STD_F2003)
NAMED_INTCST (ISOCBINDING_INT_LEAST32_T, "c_int_least32_t", \
- get_int_kind_from_minimal_width (32), GFC_STD_F2003)
+ get_int_kind_from_name (INT_LEAST32_TYPE), GFC_STD_F2003)
NAMED_INTCST (ISOCBINDING_INT_LEAST64_T, "c_int_least64_t", \
- get_int_kind_from_minimal_width (64), GFC_STD_F2003)
+ get_int_kind_from_name (INT_LEAST64_TYPE), GFC_STD_F2003)
/* GNU Extension. */
NAMED_INTCST (ISOCBINDING_INT_LEAST128_T, "c_int_least128_t", \
get_int_kind_from_minimal_width (128), GFC_STD_GNU)
-/* TODO: Implement c_int_fast*_t. Depends on PR 448. */
-NAMED_INTCST (ISOCBINDING_INT_FAST8_T, "c_int_fast8_t", -2, GFC_STD_F2003)
-NAMED_INTCST (ISOCBINDING_INT_FAST16_T, "c_int_fast16_t", -2, GFC_STD_F2003)
-NAMED_INTCST (ISOCBINDING_INT_FAST32_T, "c_int_fast32_t", -2, GFC_STD_F2003)
-NAMED_INTCST (ISOCBINDING_INT_FAST64_T, "c_int_fast64_t", -2, GFC_STD_F2003)
+NAMED_INTCST (ISOCBINDING_INT_FAST8_T, "c_int_fast8_t", \
+ get_int_kind_from_name (INT_FAST8_TYPE), GFC_STD_F2003)
+NAMED_INTCST (ISOCBINDING_INT_FAST16_T, "c_int_fast16_t", \
+ get_int_kind_from_name (INT_FAST16_TYPE), GFC_STD_F2003)
+NAMED_INTCST (ISOCBINDING_INT_FAST32_T, "c_int_fast32_t", \
+ get_int_kind_from_name (INT_FAST32_TYPE), GFC_STD_F2003)
+NAMED_INTCST (ISOCBINDING_INT_FAST64_T, "c_int_fast64_t", \
+ get_int_kind_from_name (INT_FAST64_TYPE), GFC_STD_F2003)
/* GNU Extension. */
NAMED_INTCST (ISOCBINDING_INT_FAST128_T, "c_int_fast128_t", -2, GFC_STD_GNU)
diff --git a/gcc/fortran/iso-fortran-env.def b/gcc/fortran/iso-fortran-env.def
index 5f2c04231c5..fa6071f45b2 100644
--- a/gcc/fortran/iso-fortran-env.def
+++ b/gcc/fortran/iso-fortran-env.def
@@ -33,6 +33,14 @@ NAMED_INTCST (ISOFORTRANENV_FILE_STORAGE_SIZE, "file_storage_size", 8, \
GFC_STD_F2003)
NAMED_INTCST (ISOFORTRANENV_INPUT_UNIT, "input_unit", GFC_STDIN_UNIT_NUMBER, \
GFC_STD_F2003)
+NAMED_INTCST (ISOFORTRANENV_INT8, "int8", \
+ gfc_get_int_kind_from_width_isofortranenv (8), GFC_STD_F2008)
+NAMED_INTCST (ISOFORTRANENV_INT16, "int16", \
+ gfc_get_int_kind_from_width_isofortranenv (16), GFC_STD_F2008)
+NAMED_INTCST (ISOFORTRANENV_INT32, "int32", \
+ gfc_get_int_kind_from_width_isofortranenv (32), GFC_STD_F2008)
+NAMED_INTCST (ISOFORTRANENV_INT64, "int64", \
+ gfc_get_int_kind_from_width_isofortranenv (64), GFC_STD_F2008)
NAMED_INTCST (ISOFORTRANENV_IOSTAT_END, "iostat_end", LIBERROR_END, \
GFC_STD_F2003)
NAMED_INTCST (ISOFORTRANENV_IOSTAT_EOR, "iostat_eor", LIBERROR_EOR, \
@@ -41,3 +49,9 @@ NAMED_INTCST (ISOFORTRANENV_NUMERIC_STORAGE_SIZE, "numeric_storage_size", \
gfc_numeric_storage_size, GFC_STD_F2003)
NAMED_INTCST (ISOFORTRANENV_OUTPUT_UNIT, "output_unit", GFC_STDOUT_UNIT_NUMBER, \
GFC_STD_F2003)
+NAMED_INTCST (ISOFORTRANENV_REAL32, "real32", \
+ gfc_get_real_kind_from_width_isofortranenv (32), GFC_STD_F2008)
+NAMED_INTCST (ISOFORTRANENV_REAL64, "real64", \
+ gfc_get_real_kind_from_width_isofortranenv (64), GFC_STD_F2008)
+NAMED_INTCST (ISOFORTRANENV_REAL128, "real128", \
+ gfc_get_real_kind_from_width_isofortranenv (128), GFC_STD_F2008)
diff --git a/gcc/fortran/lang.opt b/gcc/fortran/lang.opt
index 9da290c81fa..d29dddee8e1 100644
--- a/gcc/fortran/lang.opt
+++ b/gcc/fortran/lang.opt
@@ -350,7 +350,7 @@ Append a second underscore if the name already contains an underscore
fshort-enums
Fortran
-Use the narrowest integer type possible for enumeration types
+; Documented in C
fsign-zero
Fortran
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/module.c b/gcc/fortran/module.c
index 2a48f88dbda..82a41996ca4 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -4759,7 +4759,7 @@ read_md5_from_module_file (const char * filename, unsigned char md5[16])
if ((file = fopen (filename, "r")) == NULL)
return -1;
- /* Read two lines. */
+ /* Read the first line. */
if (fgets (buf, sizeof (buf) - 1, file) == NULL)
{
fclose (file);
@@ -4769,8 +4769,12 @@ read_md5_from_module_file (const char * filename, unsigned char md5[16])
/* The file also needs to be overwritten if the version number changed. */
n = strlen ("GFORTRAN module version '" MOD_VERSION "' created");
if (strncmp (buf, "GFORTRAN module version '" MOD_VERSION "' created", n) != 0)
- return -1;
+ {
+ fclose (file);
+ return -1;
+ }
+ /* Read a second line. */
if (fgets (buf, sizeof (buf) - 1, file) == NULL)
{
fclose (file);
diff --git a/gcc/fortran/options.c b/gcc/fortran/options.c
index 65841f6a629..2d899f546ab 100644
--- a/gcc/fortran/options.c
+++ b/gcc/fortran/options.c
@@ -137,7 +137,7 @@ gfc_init_options (unsigned int argc, const char **argv)
set_default_std_flags ();
/* -fshort-enums can be default on some targets. */
- gfc_option.fshort_enums = targetm.default_short_enums ();
+ flag_short_enums = targetm.default_short_enums ();
/* Initialize cpp-related options. */
gfc_cpp_init_options(argc, argv);
@@ -858,7 +858,7 @@ gfc_handle_option (size_t scode, const char *arg, int value)
break;
case OPT_fshort_enums:
- gfc_option.fshort_enums = 1;
+ flag_short_enums = 1;
break;
case OPT_fconvert_little_endian:
diff --git a/gcc/fortran/primary.c b/gcc/fortran/primary.c
index 96fbddce92a..1a03165fcbe 100644
--- a/gcc/fortran/primary.c
+++ b/gcc/fortran/primary.c
@@ -1726,7 +1726,8 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
tail = NULL;
gfc_gobble_whitespace ();
- if ((equiv_flag && gfc_peek_ascii_char () == '(') || sym->attr.dimension)
+ if ((equiv_flag && gfc_peek_ascii_char () == '(')
+ || (sym->attr.dimension && !sym->attr.proc_pointer))
{
/* In EQUIVALENCE, we don't know yet whether we are seeing
an array, character variable or array of character
@@ -1843,7 +1844,7 @@ gfc_match_varspec (gfc_expr *primary, int equiv_flag, bool sub_flag,
break;
}
- if (component->as != NULL)
+ if (component->as != NULL && !component->attr.proc_pointer)
{
tail = extend_ref (primary, tail);
tail->type = REF_ARRAY;
@@ -2558,7 +2559,7 @@ gfc_match_rvalue (gfc_expr **result)
if (gfc_matching_procptr_assignment)
{
gfc_gobble_whitespace ();
- if (gfc_peek_ascii_char () == '(')
+ if (!sym->attr.dimension && gfc_peek_ascii_char () == '(')
/* Parse functions returning a procptr. */
goto function0;
diff --git a/gcc/fortran/resolve.c b/gcc/fortran/resolve.c
index dbca1752b55..8158b71ee4f 100644
--- a/gcc/fortran/resolve.c
+++ b/gcc/fortran/resolve.c
@@ -3897,6 +3897,8 @@ resolve_array_ref (gfc_array_ref *ar)
static gfc_try
resolve_substring (gfc_ref *ref)
{
+ int k = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
+
if (ref->u.ss.start != NULL)
{
if (gfc_resolve_expr (ref->u.ss.start) == FAILURE)
@@ -3954,6 +3956,16 @@ resolve_substring (gfc_ref *ref)
&ref->u.ss.start->where);
return FAILURE;
}
+
+ if (compare_bound_mpz_t (ref->u.ss.end,
+ gfc_integer_kinds[k].huge) == CMP_GT
+ && (compare_bound (ref->u.ss.end, ref->u.ss.start) == CMP_EQ
+ || compare_bound (ref->u.ss.end, ref->u.ss.start) == CMP_GT))
+ {
+ gfc_error ("Substring end index at %L is too large",
+ &ref->u.ss.end->where);
+ return FAILURE;
+ }
}
return SUCCESS;
@@ -4016,7 +4028,7 @@ gfc_resolve_substring_charlen (gfc_expr *e)
e->ts.cl->length = gfc_add (e->ts.cl->length, gfc_int_expr (1));
e->ts.cl->length->ts.type = BT_INTEGER;
- e->ts.cl->length->ts.kind = gfc_charlen_int_kind;;
+ e->ts.cl->length->ts.kind = gfc_charlen_int_kind;
/* Make sure that the length is simplified. */
gfc_simplify_expr (e->ts.cl->length, 1);
@@ -4475,7 +4487,7 @@ gfc_resolve_character_operator (gfc_expr *e)
e->ts.cl->length = gfc_add (e1, e2);
e->ts.cl->length->ts.type = BT_INTEGER;
- e->ts.cl->length->ts.kind = gfc_charlen_int_kind;;
+ e->ts.cl->length->ts.kind = gfc_charlen_int_kind;
gfc_simplify_expr (e->ts.cl->length, 0);
gfc_resolve_expr (e->ts.cl->length);
@@ -4828,6 +4840,9 @@ resolve_ppc_call (gfc_code* c)
if (!comp->attr.subroutine)
gfc_add_subroutine (&comp->attr, comp->name, &c->expr1->where);
+ if (resolve_ref (c->expr1) == FAILURE)
+ return FAILURE;
+
if (resolve_actual_arglist (c->ext.actual, comp->attr.proc,
comp->formal == NULL) == FAILURE)
return FAILURE;
@@ -4853,10 +4868,15 @@ resolve_expr_ppc (gfc_expr* e)
e->value.function.isym = NULL;
e->value.function.actual = e->value.compcall.actual;
e->ts = comp->ts;
+ if (comp->as != NULL)
+ e->rank = comp->as->rank;
if (!comp->attr.function)
gfc_add_function (&comp->attr, comp->name, &e->where);
+ if (resolve_ref (e) == FAILURE)
+ return FAILURE;
+
if (resolve_actual_arglist (e->value.function.actual, comp->attr.proc,
comp->formal == NULL) == FAILURE)
return FAILURE;
@@ -7383,7 +7403,7 @@ resolve_index_expr (gfc_expr *e)
static gfc_try
resolve_charlen (gfc_charlen *cl)
{
- int i;
+ int i, k;
if (cl->resolved)
return SUCCESS;
@@ -7407,6 +7427,16 @@ resolve_charlen (gfc_charlen *cl)
gfc_replace_expr (cl->length, gfc_int_expr (0));
}
+ /* Check that the character length is not too large. */
+ k = gfc_validate_kind (BT_INTEGER, gfc_charlen_int_kind, false);
+ if (cl->length && cl->length->expr_type == EXPR_CONSTANT
+ && cl->length->ts.type == BT_INTEGER
+ && mpz_cmp (cl->length->value.integer, gfc_integer_kinds[k].huge) > 0)
+ {
+ gfc_error ("String length at %L is too large", &cl->length->where);
+ return FAILURE;
+ }
+
return SUCCESS;
}
@@ -8563,7 +8593,7 @@ check_generic_tbp_ambiguity (gfc_tbp_generic* t1, gfc_tbp_generic* t2,
}
/* Compare the interfaces. */
- if (gfc_compare_interfaces (sym1, sym2, 1))
+ if (gfc_compare_interfaces (sym1, sym2, 1, 0))
{
gfc_error ("'%s' and '%s' for GENERIC '%s' at %L are ambiguous",
sym1->name, sym2->name, generic_name, &where);
@@ -9125,7 +9155,8 @@ resolve_fl_derived (gfc_symbol *sym)
&& sym != c->ts.derived)
add_dt_to_dt_list (c->ts.derived);
- if (c->attr.pointer || c->attr.allocatable || c->as == NULL)
+ if (c->attr.pointer || c->attr.proc_pointer || c->attr.allocatable
+ || c->as == NULL)
continue;
for (i = 0; i < c->as->rank; i++)
@@ -9385,6 +9416,7 @@ resolve_symbol (gfc_symbol *sym)
|| sym->ts.interface->attr.intrinsic)
{
gfc_symbol *ifc = sym->ts.interface;
+ resolve_symbol (ifc);
if (ifc->attr.intrinsic)
resolve_intrinsic (ifc, &ifc->declared_at);
diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c
index 7be4671acfb..4dd114b532f 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");
@@ -1213,6 +1238,143 @@ gfc_simplify_erfc (gfc_expr *x)
}
+/* Helper functions to simplify ERFC_SCALED(x) = ERFC(x) * EXP(X**2). */
+
+#define MAX_ITER 200
+#define ARG_LIMIT 12
+
+/* Calculate ERFC_SCALED directly by its definition:
+
+ ERFC_SCALED(x) = ERFC(x) * EXP(X**2)
+
+ using a large precision for intermediate results. This is used for all
+ but large values of the argument. */
+static void
+fullprec_erfc_scaled (mpfr_t res, mpfr_t arg)
+{
+ mp_prec_t prec;
+ mpfr_t a, b;
+
+ prec = mpfr_get_default_prec ();
+ mpfr_set_default_prec (10 * prec);
+
+ mpfr_init (a);
+ mpfr_init (b);
+
+ mpfr_set (a, arg, GFC_RND_MODE);
+ mpfr_sqr (b, a, GFC_RND_MODE);
+ mpfr_exp (b, b, GFC_RND_MODE);
+ mpfr_erfc (a, a, GFC_RND_MODE);
+ mpfr_mul (a, a, b, GFC_RND_MODE);
+
+ mpfr_set (res, a, GFC_RND_MODE);
+ mpfr_set_default_prec (prec);
+
+ mpfr_clear (a);
+ mpfr_clear (b);
+}
+
+/* Calculate ERFC_SCALED using a power series expansion in 1/arg:
+
+ ERFC_SCALED(x) = 1 / (x * sqrt(pi))
+ * (1 + Sum_n (-1)**n * (1 * 3 * 5 * ... * (2n-1))
+ / (2 * x**2)**n)
+
+ This is used for large values of the argument. Intermediate calculations
+ are performed with twice the precision. We don't do a fixed number of
+ iterations of the sum, but stop when it has converged to the required
+ precision. */
+static void
+asympt_erfc_scaled (mpfr_t res, mpfr_t arg)
+{
+ mpfr_t sum, x, u, v, w, oldsum, sumtrunc;
+ mpz_t num;
+ mp_prec_t prec;
+ unsigned i;
+
+ prec = mpfr_get_default_prec ();
+ mpfr_set_default_prec (2 * prec);
+
+ mpfr_init (sum);
+ mpfr_init (x);
+ mpfr_init (u);
+ mpfr_init (v);
+ mpfr_init (w);
+ mpz_init (num);
+
+ mpfr_init (oldsum);
+ mpfr_init (sumtrunc);
+ mpfr_set_prec (oldsum, prec);
+ mpfr_set_prec (sumtrunc, prec);
+
+ mpfr_set (x, arg, GFC_RND_MODE);
+ mpfr_set_ui (sum, 1, GFC_RND_MODE);
+ mpz_set_ui (num, 1);
+
+ mpfr_set (u, x, GFC_RND_MODE);
+ mpfr_sqr (u, u, GFC_RND_MODE);
+ mpfr_mul_ui (u, u, 2, GFC_RND_MODE);
+ mpfr_pow_si (u, u, -1, GFC_RND_MODE);
+
+ for (i = 1; i < MAX_ITER; i++)
+ {
+ mpfr_set (oldsum, sum, GFC_RND_MODE);
+
+ mpz_mul_ui (num, num, 2 * i - 1);
+ mpz_neg (num, num);
+
+ mpfr_set (w, u, GFC_RND_MODE);
+ mpfr_pow_ui (w, w, i, GFC_RND_MODE);
+
+ mpfr_set_z (v, num, GFC_RND_MODE);
+ mpfr_mul (v, v, w, GFC_RND_MODE);
+
+ mpfr_add (sum, sum, v, GFC_RND_MODE);
+
+ mpfr_set (sumtrunc, sum, GFC_RND_MODE);
+ if (mpfr_cmp (sumtrunc, oldsum) == 0)
+ break;
+ }
+
+ /* We should have converged by now; otherwise, ARG_LIMIT is probably
+ set too low. */
+ gcc_assert (i < MAX_ITER);
+
+ /* Divide by x * sqrt(Pi). */
+ mpfr_const_pi (u, GFC_RND_MODE);
+ mpfr_sqrt (u, u, GFC_RND_MODE);
+ mpfr_mul (u, u, x, GFC_RND_MODE);
+ mpfr_div (sum, sum, u, GFC_RND_MODE);
+
+ mpfr_set (res, sum, GFC_RND_MODE);
+ mpfr_set_default_prec (prec);
+
+ mpfr_clears (sum, x, u, v, w, oldsum, sumtrunc, NULL);
+ mpz_clear (num);
+}
+
+
+gfc_expr *
+gfc_simplify_erfc_scaled (gfc_expr *x)
+{
+ gfc_expr *result;
+
+ if (x->expr_type != EXPR_CONSTANT)
+ return NULL;
+
+ result = gfc_constant_result (x->ts.type, x->ts.kind, &x->where);
+ if (mpfr_cmp_d (x->value.real, ARG_LIMIT) >= 0)
+ asympt_erfc_scaled (result->value.real, x->value.real);
+ else
+ fullprec_erfc_scaled (result->value.real, x->value.real);
+
+ return range_check (result, "ERFC_SCALED");
+}
+
+#undef MAX_ITER
+#undef ARG_LIMIT
+
+
gfc_expr *
gfc_simplify_epsilon (gfc_expr *e)
{
@@ -1233,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;
@@ -1248,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);
@@ -1256,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:
@@ -2433,7 +2602,13 @@ gfc_simplify_len (gfc_expr *e, gfc_expr *kind)
{
result = gfc_constant_result (BT_INTEGER, k, &e->where);
mpz_set_si (result->value.integer, e->value.character.length);
- return range_check (result, "LEN");
+ if (gfc_range_check (result) == ARITH_OK)
+ return result;
+ else
+ {
+ gfc_free_expr (result);
+ return NULL;
+ }
}
if (e->ts.cl != NULL && e->ts.cl->length != NULL
@@ -2442,7 +2617,13 @@ gfc_simplify_len (gfc_expr *e, gfc_expr *kind)
{
result = gfc_constant_result (BT_INTEGER, k, &e->where);
mpz_set (result->value.integer, e->ts.cl->length->value.integer);
- return range_check (result, "LEN");
+ if (gfc_range_check (result) == ARITH_OK)
+ return result;
+ else
+ {
+ gfc_free_expr (result);
+ return NULL;
+ }
}
return NULL;
@@ -2539,7 +2720,6 @@ gfc_expr *
gfc_simplify_log (gfc_expr *x)
{
gfc_expr *result;
- mpfr_t xr, xi;
if (x->expr_type != EXPR_CONSTANT)
return NULL;
@@ -2572,6 +2752,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);
@@ -2585,7 +2771,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:
@@ -4165,7 +4352,6 @@ gfc_expr *
gfc_simplify_sin (gfc_expr *x)
{
gfc_expr *result;
- mpfr_t xp, xq;
if (x->expr_type != EXPR_CONSTANT)
return NULL;
@@ -4180,6 +4366,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);
@@ -4192,6 +4384,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:
@@ -4276,7 +4470,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;
@@ -4293,10 +4486,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);
@@ -4368,7 +4567,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/symbol.c b/gcc/fortran/symbol.c
index 81473a420bf..326d73e3ebf 100644
--- a/gcc/fortran/symbol.c
+++ b/gcc/fortran/symbol.c
@@ -3914,6 +3914,7 @@ gfc_copy_formal_args_intr (gfc_symbol *dest, gfc_intrinsic_sym *src)
/* May need to copy more info for the symbol. */
formal_arg->sym->ts = curr_arg->ts;
formal_arg->sym->attr.optional = curr_arg->optional;
+ formal_arg->sym->attr.intent = curr_arg->intent;
formal_arg->sym->attr.flavor = FL_VARIABLE;
formal_arg->sym->attr.dummy = 1;
diff --git a/gcc/fortran/trans-array.c b/gcc/fortran/trans-array.c
index f4276ca133c..7dea22253f4 100644
--- a/gcc/fortran/trans-array.c
+++ b/gcc/fortran/trans-array.c
@@ -3256,6 +3256,8 @@ gfc_conv_ss_startstride (gfc_loopinfo * loop)
info->start[n]);
tmp = fold_build2 (FLOOR_DIV_EXPR, gfc_array_index_type, tmp,
info->stride[n]);
+ tmp = fold_build2 (PLUS_EXPR, gfc_array_index_type,
+ gfc_index_one_node, tmp);
tmp = fold_build2 (MAX_EXPR, gfc_array_index_type, tmp,
build_int_cst (gfc_array_index_type, 0));
/* We remember the size of the first section, and check all the
@@ -6293,6 +6295,7 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
gfc_ss *newss;
gfc_intrinsic_sym *isym;
gfc_symbol *sym;
+ gfc_component *comp = NULL;
isym = expr->value.function.isym;
@@ -6305,7 +6308,9 @@ gfc_walk_function_expr (gfc_ss * ss, gfc_expr * expr)
sym = expr->symtree->n.sym;
/* A function that returns arrays. */
- if (gfc_return_by_reference (sym) && sym->result->attr.dimension)
+ is_proc_ptr_comp (expr, &comp);
+ if ((!comp && gfc_return_by_reference (sym) && sym->result->attr.dimension)
+ || (comp && comp->attr.dimension))
{
newss = gfc_get_ss ();
newss->type = GFC_SS_FUNCTION;
diff --git a/gcc/fortran/trans-decl.c b/gcc/fortran/trans-decl.c
index 8f355f6a373..ba85eddeb8a 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;
@@ -1525,7 +1526,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 +1545,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);
@@ -2635,6 +2630,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 +2643,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 +3835,218 @@ 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);
+ 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 +4131,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 +4314,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-expr.c b/gcc/fortran/trans-expr.c
index cf17598c9f6..f1f009122ef 100644
--- a/gcc/fortran/trans-expr.c
+++ b/gcc/fortran/trans-expr.c
@@ -476,8 +476,8 @@ gfc_conv_component_ref (gfc_se * se, gfc_ref * ref)
se->string_length = tmp;
}
- if ((c->attr.pointer || c->attr.proc_pointer) && c->attr.dimension == 0
- && c->ts.type != BT_CHARACTER)
+ if ((c->attr.pointer && c->attr.dimension == 0 && c->ts.type != BT_CHARACTER)
+ || c->attr.proc_pointer)
se->expr = build_fold_indirect_ref (se->expr);
}
@@ -2396,6 +2396,7 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_symbol *fsym;
stmtblock_t post;
enum {MISSING = 0, ELEMENTAL, SCALAR, SCALAR_POINTER, ARRAY};
+ gfc_component *comp = NULL;
arglist = NULL_TREE;
retargs = NULL_TREE;
@@ -2550,11 +2551,13 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
gfc_init_block (&post);
gfc_init_interface_mapping (&mapping);
+ is_proc_ptr_comp (expr, &comp);
need_interface_mapping = ((sym->ts.type == BT_CHARACTER
&& sym->ts.cl->length
&& sym->ts.cl->length->expr_type
!= EXPR_CONSTANT)
- || sym->attr.dimension);
+ || (comp && comp->attr.dimension)
+ || (!comp && sym->attr.dimension));
formal = sym->formal;
/* Evaluate the arguments. */
for (; arg != NULL; arg = arg->next, formal = formal ? formal->next : NULL)
@@ -2825,7 +2828,8 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
len = cl.backend_decl;
}
- byref = gfc_return_by_reference (sym);
+ byref = (comp && comp->attr.dimension)
+ || (!comp && gfc_return_by_reference (sym));
if (byref)
{
if (se->direct_byref)
@@ -4053,6 +4057,10 @@ gfc_trans_pointer_assignment (gfc_expr * expr1, gfc_expr * expr2)
&& expr1->symtree->n.sym->attr.dummy)
lse.expr = build_fold_indirect_ref (lse.expr);
+ if (expr2->symtree && expr2->symtree->n.sym->attr.proc_pointer
+ && expr2->symtree->n.sym->attr.dummy)
+ rse.expr = build_fold_indirect_ref (rse.expr);
+
gfc_add_block_to_block (&block, &lse.pre);
gfc_add_block_to_block (&block, &rse.pre);
@@ -4284,6 +4292,7 @@ gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
gfc_ss *ss;
gfc_ref * ref;
bool seen_array_ref;
+ gfc_component *comp = NULL;
/* The caller has already checked rank>0 and expr_type == EXPR_FUNCTION. */
if (expr2->value.function.isym && !gfc_is_intrinsic_libcall (expr2))
@@ -4343,8 +4352,10 @@ gfc_trans_arrayfunc_assign (gfc_expr * expr1, gfc_expr * expr2)
/* The frontend doesn't seem to bother filling in expr->symtree for intrinsic
functions. */
+ is_proc_ptr_comp(expr2, &comp);
gcc_assert (expr2->value.function.isym
- || (gfc_return_by_reference (expr2->value.function.esym)
+ || (comp && comp->attr.dimension)
+ || (!comp && gfc_return_by_reference (expr2->value.function.esym)
&& expr2->value.function.esym->result->attr.dimension));
ss = gfc_walk_expr (expr1);
@@ -4428,11 +4439,14 @@ gfc_trans_zero_assign (gfc_expr * expr)
len = fold_build2 (MULT_EXPR, gfc_array_index_type, len,
fold_convert (gfc_array_index_type, tmp));
- /* Convert arguments to the correct types. */
+ /* If we are zeroing a local array avoid taking its address by emitting
+ a = {} instead. */
if (!POINTER_TYPE_P (TREE_TYPE (dest)))
- dest = gfc_build_addr_expr (pvoid_type_node, dest);
- else
- dest = fold_convert (pvoid_type_node, dest);
+ return build2 (MODIFY_EXPR, void_type_node,
+ dest, build_constructor (TREE_TYPE (dest), NULL));
+
+ /* Convert arguments to the correct types. */
+ dest = fold_convert (pvoid_type_node, dest);
len = fold_convert (size_type_node, len);
/* Construct call to __builtin_memset. */
diff --git a/gcc/fortran/trans-types.c b/gcc/fortran/trans-types.c
index 34144f8ae7d..8aa858a24b1 100644
--- a/gcc/fortran/trans-types.c
+++ b/gcc/fortran/trans-types.c
@@ -163,6 +163,96 @@ get_int_kind_from_node (tree type)
return -1;
}
+/* Return a typenode for the "standard" C type with a given name. */
+static tree
+get_typenode_from_name (const char *name)
+{
+ if (name == NULL || *name == '\0')
+ return NULL_TREE;
+
+ if (strcmp (name, "char") == 0)
+ return char_type_node;
+ if (strcmp (name, "unsigned char") == 0)
+ return unsigned_char_type_node;
+ if (strcmp (name, "signed char") == 0)
+ return signed_char_type_node;
+
+ if (strcmp (name, "short int") == 0)
+ return short_integer_type_node;
+ if (strcmp (name, "short unsigned int") == 0)
+ return short_unsigned_type_node;
+
+ if (strcmp (name, "int") == 0)
+ return integer_type_node;
+ if (strcmp (name, "unsigned int") == 0)
+ return unsigned_type_node;
+
+ if (strcmp (name, "long int") == 0)
+ return long_integer_type_node;
+ if (strcmp (name, "long unsigned int") == 0)
+ return long_unsigned_type_node;
+
+ if (strcmp (name, "long long int") == 0)
+ return long_long_integer_type_node;
+ if (strcmp (name, "long long unsigned int") == 0)
+ return long_long_unsigned_type_node;
+
+ gcc_unreachable ();
+}
+
+static int
+get_int_kind_from_name (const char *name)
+{
+ return get_int_kind_from_node (get_typenode_from_name (name));
+}
+
+
+/* Get the kind number corresponding to an integer of given size,
+ following the required return values for ISO_FORTRAN_ENV INT* constants:
+ -2 is returned if we support a kind of larger size, -1 otherwise. */
+int
+gfc_get_int_kind_from_width_isofortranenv (int size)
+{
+ int i;
+
+ /* Look for a kind with matching storage size. */
+ for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
+ if (gfc_integer_kinds[i].bit_size == size)
+ return gfc_integer_kinds[i].kind;
+
+ /* Look for a kind with larger storage size. */
+ for (i = 0; gfc_integer_kinds[i].kind != 0; i++)
+ if (gfc_integer_kinds[i].bit_size > size)
+ return -2;
+
+ return -1;
+}
+
+/* Get the kind number corresponding to a real of given storage size,
+ following the required return values for ISO_FORTRAN_ENV REAL* constants:
+ -2 is returned if we support a kind of larger size, -1 otherwise. */
+int
+gfc_get_real_kind_from_width_isofortranenv (int size)
+{
+ int i;
+
+ size /= 8;
+
+ /* Look for a kind with matching storage size. */
+ for (i = 0; gfc_real_kinds[i].kind != 0; i++)
+ if (int_size_in_bytes (gfc_get_real_type (gfc_real_kinds[i].kind)) == size)
+ return gfc_real_kinds[i].kind;
+
+ /* Look for a kind with larger storage size. */
+ for (i = 0; gfc_real_kinds[i].kind != 0; i++)
+ if (int_size_in_bytes (gfc_get_real_type (gfc_real_kinds[i].kind)) > size)
+ return -2;
+
+ return -1;
+}
+
+
+
static int
get_int_kind_from_width (int size)
{
@@ -680,6 +770,7 @@ gfc_build_logical_type (gfc_logical_info *info)
return new_type;
}
+
#if 0
/* Return the bit size of the C "size_t". */
@@ -1784,7 +1875,7 @@ tree
gfc_get_ppc_type (gfc_component* c)
{
tree t;
- if (c->attr.function)
+ if (c->attr.function && !c->attr.dimension)
t = gfc_typenode_for_spec (&c->ts);
else
t = void_type_node;
@@ -1906,7 +1997,7 @@ gfc_get_derived_type (gfc_symbol * derived)
/* This returns an array descriptor type. Initialization may be
required. */
- if (c->attr.dimension)
+ if (c->attr.dimension && !c->attr.proc_pointer)
{
if (c->attr.pointer || c->attr.allocatable)
{
diff --git a/gcc/gcc-plugin.h b/gcc/gcc-plugin.h
index ba20b42475c..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. */
@@ -79,6 +90,20 @@ struct plugin_gcc_version
const char *configuration_arguments;
};
+/* Object that keeps track of the plugin name and its arguments. */
+struct plugin_name_args
+{
+ char *base_name; /* Short name of the plugin (filename without
+ .so suffix). */
+ const char *full_name; /* Path to the plugin as specified with
+ -fplugin=. */
+ int argc; /* Number of arguments specified with
+ -fplugin-arg-... */
+ struct plugin_argument *argv; /* Array of ARGC key-value pairs. */
+ const char *version; /* Version string provided by plugin. */
+ const char *help; /* Help string provided by plugin. */
+};
+
/* The default version check. Compares every field in VERSION. */
extern bool plugin_default_version_check (struct plugin_gcc_version *,
@@ -88,21 +113,18 @@ extern bool plugin_default_version_check (struct plugin_gcc_version *,
should define this as an externally-visible function with name
"plugin_init."
- PLUGIN_NAME - name of the plugin (useful for error reporting)
- VERSION - the plugin_gcc_version symbol of the plugin itself.
- ARGC - the size of the ARGV array
- ARGV - an array of key-value argument pair
+ PLUGIN_INFO - plugin invocation information.
+ VERSION - the plugin_gcc_version symbol of GCC.
Returns 0 if initialization finishes successfully. */
-typedef int (*plugin_init_func) (const char *plugin_name,
- struct plugin_gcc_version *version,
- int argc, struct plugin_argument *argv);
+typedef int (*plugin_init_func) (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version);
/* Declaration for "plugin_init" function so that it doesn't need to be
duplicated in every plugin. */
-extern int plugin_init (const char *, struct plugin_gcc_version *version,
- int, struct plugin_argument *);
+extern int plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version);
/* Function type for a plugin callback routine.
@@ -117,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/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/ggc-common.c b/gcc/ggc-common.c
index b6b9e1e3400..2499ff51cd7 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
@@ -104,7 +134,21 @@ ggc_mark_roots (void)
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 ();
@@ -123,6 +167,9 @@ ggc_mark_roots (void)
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 f4842bc4dcf..744355e3de3 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. */
@@ -1937,6 +1938,8 @@ ggc_collect (void)
/* 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 ();
#ifdef GATHER_STATISTICS
@@ -1948,6 +1951,8 @@ ggc_collect (void)
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 5031a01b404..442c80e6713 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. */
@@ -2029,6 +2030,8 @@ ggc_collect (void)
}
}
+ 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);
@@ -2093,6 +2096,8 @@ ggc_collect (void)
}
}
+ invoke_plugin_callbacks (PLUGIN_GGC_END, NULL);
+
timevar_pop (TV_GC);
}
diff --git a/gcc/ggc.h b/gcc/ggc.h
index 5b2743b3386..e3471e45353 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.
@@ -270,6 +271,10 @@ extern const char *ggc_alloc_string (const char *contents, int length);
function is called, not during allocations. */
extern void ggc_collect (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-low.c b/gcc/gimple-low.c
index 02a1ce63549..42bf9b11ea9 100644
--- a/gcc/gimple-low.c
+++ b/gcc/gimple-low.c
@@ -368,7 +368,6 @@ lower_stmt (gimple_stmt_iterator *gsi, struct lower_data *data)
case GIMPLE_PREDICT:
case GIMPLE_LABEL:
case GIMPLE_SWITCH:
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
case GIMPLE_OMP_FOR:
case GIMPLE_OMP_SECTIONS:
case GIMPLE_OMP_SECTIONS_SWITCH:
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 163acf9c065..ec366f86f42 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -1324,27 +1324,6 @@ dump_gimple_omp_atomic_store (pretty_printer *buffer, gimple gs, int spc,
}
}
-/* Dump a GIMPLE_CHANGE_DYNAMIC_TYPE statement GS. BUFFER, SPC and
- FLAGS are as in dump_gimple_stmt. */
-
-static void
-dump_gimple_cdt (pretty_printer *buffer, gimple gs, int spc, int flags)
-{
- if (flags & TDF_RAW)
- dump_gimple_fmt (buffer, spc, flags, "%G <%T, %T>", gs,
- gimple_cdt_new_type (gs), gimple_cdt_location (gs));
- else
- {
- pp_string (buffer, "<<<change_dynamic_type (");
- dump_generic_node (buffer, gimple_cdt_new_type (gs), spc + 2, flags,
- false);
- pp_string (buffer, ") ");
- dump_generic_node (buffer, gimple_cdt_location (gs), spc + 2, flags,
- false);
- pp_string (buffer, ")>>>");
- }
-}
-
/* Dump all the memory operands for statement GS. BUFFER, SPC and
FLAGS are as in dump_gimple_stmt. */
@@ -1508,10 +1487,6 @@ dump_gimple_stmt (pretty_printer *buffer, gimple gs, int spc, int flags)
dump_gimple_omp_critical (buffer, gs, spc, flags);
break;
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- dump_gimple_cdt (buffer, gs, spc, flags);
- break;
-
case GIMPLE_CATCH:
dump_gimple_catch (buffer, gs, spc, flags);
break;
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 0b296370f41..b533ef260b0 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -105,7 +105,6 @@ gss_for_code (enum gimple_code code)
case GIMPLE_COND:
case GIMPLE_GOTO:
case GIMPLE_LABEL:
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
case GIMPLE_SWITCH: return GSS_WITH_OPS;
case GIMPLE_ASM: return GSS_ASM;
case GIMPLE_BIND: return GSS_BIND;
@@ -193,8 +192,6 @@ gimple_size (enum gimple_code code)
return sizeof (struct gimple_statement_omp_atomic_store);
case GIMPLE_WITH_CLEANUP_EXPR:
return sizeof (struct gimple_statement_wce);
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- return sizeof (struct gimple_statement_with_ops);
case GIMPLE_PREDICT:
return sizeof (struct gimple_statement_base);
default:
@@ -1045,20 +1042,6 @@ gimple_build_omp_single (gimple_seq body, tree clauses)
}
-/* Build a GIMPLE_CHANGE_DYNAMIC_TYPE statement. TYPE is the new type
- for the location PTR. */
-
-gimple
-gimple_build_cdt (tree type, tree ptr)
-{
- gimple p = gimple_build_with_ops (GIMPLE_CHANGE_DYNAMIC_TYPE, ERROR_MARK, 2);
- gimple_cdt_set_new_type (p, type);
- gimple_cdt_set_location (p, ptr);
-
- return p;
-}
-
-
/* Build a GIMPLE_OMP_ATOMIC_LOAD statement. */
gimple
@@ -1463,16 +1446,6 @@ walk_gimple_op (gimple stmt, walk_tree_fn callback_op,
return ret;
break;
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- ret = walk_tree (gimple_cdt_location_ptr (stmt), callback_op, wi, pset);
- if (ret)
- return ret;
-
- ret = walk_tree (gimple_cdt_new_type_ptr (stmt), callback_op, wi, pset);
- if (ret)
- return ret;
- break;
-
case GIMPLE_ASM:
ret = walk_gimple_asm (stmt, callback_op, wi);
if (ret)
@@ -2752,7 +2725,6 @@ is_gimple_stmt (tree t)
case TRY_FINALLY_EXPR:
case EH_FILTER_EXPR:
case CATCH_EXPR:
- case CHANGE_DYNAMIC_TYPE_EXPR:
case ASM_EXPR:
case RESX_EXPR:
case STATEMENT_LIST:
@@ -3257,8 +3229,7 @@ walk_stmt_load_store_addr_ops (gimple stmt, void *data,
}
else if (visit_addr
&& (is_gimple_assign (stmt)
- || gimple_code (stmt) == GIMPLE_COND
- || gimple_code (stmt) == GIMPLE_CHANGE_DYNAMIC_TYPE))
+ || gimple_code (stmt) == GIMPLE_COND))
{
for (i = 0; i < gimple_num_ops (stmt); ++i)
if (gimple_op (stmt, i)
diff --git a/gcc/gimple.def b/gcc/gimple.def
index 26aa719f660..cee6753d200 100644
--- a/gcc/gimple.def
+++ b/gcc/gimple.def
@@ -78,17 +78,6 @@ DEFGSCODE(GIMPLE_LABEL, "gimple_label", struct gimple_statement_with_ops)
They must be CASE_LABEL_EXPR nodes. */
DEFGSCODE(GIMPLE_SWITCH, "gimple_switch", struct gimple_statement_with_ops)
-/* GIMPLE_CHANGE_DYNAMIC_TYPE indicates a change in the dynamic type
- of a memory location. This has no value and generates no
- executable code. It is only used for type based alias analysis.
- This is generated by C++ placement new and it's a direct
- translation from CHANGE_DYNAMIC_TYPE_EXPR. The first operand
- (gimple_cdt_new_type) is the new type. The second operand
- (gimple_cdt_location) is the location (pointer) whose type is being
- changed. */
-DEFGSCODE(GIMPLE_CHANGE_DYNAMIC_TYPE, "gimple_change_dynamic_type",
- struct gimple_statement_with_ops)
-
/* IMPORTANT.
Do not rearrange the codes between GIMPLE_ASSIGN and GIMPLE_RETURN.
diff --git a/gcc/gimple.h b/gcc/gimple.h
index ffcf9aa95ae..b16fb545028 100644
--- a/gcc/gimple.h
+++ b/gcc/gimple.h
@@ -4106,69 +4106,6 @@ gimple_nop_p (const_gimple g)
}
-/* Return the new type set by GIMPLE_CHANGE_DYNAMIC_TYPE statement GS. */
-
-static inline tree
-gimple_cdt_new_type (gimple gs)
-{
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- return gimple_op (gs, 1);
-}
-
-/* Return a pointer to the new type set by GIMPLE_CHANGE_DYNAMIC_TYPE
- statement GS. */
-
-static inline tree *
-gimple_cdt_new_type_ptr (gimple gs)
-{
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- return gimple_op_ptr (gs, 1);
-}
-
-/* Set NEW_TYPE to be the type returned by GIMPLE_CHANGE_DYNAMIC_TYPE
- statement GS. */
-
-static inline void
-gimple_cdt_set_new_type (gimple gs, tree new_type)
-{
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- gcc_assert (TREE_CODE_CLASS (TREE_CODE (new_type)) == tcc_type);
- gimple_set_op (gs, 1, new_type);
-}
-
-
-/* Return the location affected by GIMPLE_CHANGE_DYNAMIC_TYPE statement GS. */
-
-static inline tree
-gimple_cdt_location (gimple gs)
-{
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- return gimple_op (gs, 0);
-}
-
-
-/* Return a pointer to the location affected by GIMPLE_CHANGE_DYNAMIC_TYPE
- statement GS. */
-
-static inline tree *
-gimple_cdt_location_ptr (gimple gs)
-{
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- return gimple_op_ptr (gs, 0);
-}
-
-
-/* Set PTR to be the location affected by GIMPLE_CHANGE_DYNAMIC_TYPE
- statement GS. */
-
-static inline void
-gimple_cdt_set_location (gimple gs, tree ptr)
-{
- GIMPLE_CHECK (gs, GIMPLE_CHANGE_DYNAMIC_TYPE);
- gimple_set_op (gs, 0, ptr);
-}
-
-
/* Return the predictor of GIMPLE_PREDICT statement GS. */
static inline enum br_predictor
diff --git a/gcc/gimplify.c b/gcc/gimplify.c
index bff7cdd4b6f..073fda0005b 100644
--- a/gcc/gimplify.c
+++ b/gcc/gimplify.c
@@ -6769,6 +6769,24 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
}
break;
+ case TARGET_MEM_REF:
+ {
+ enum gimplify_status r0 = GS_ALL_DONE, r1 = GS_ALL_DONE;
+
+ if (TMR_SYMBOL (*expr_p))
+ r0 = gimplify_expr (&TMR_SYMBOL (*expr_p), pre_p,
+ post_p, is_gimple_lvalue, fb_either);
+ else if (TMR_BASE (*expr_p))
+ r0 = gimplify_expr (&TMR_BASE (*expr_p), pre_p,
+ post_p, is_gimple_val, fb_either);
+ if (TMR_INDEX (*expr_p))
+ r1 = gimplify_expr (&TMR_INDEX (*expr_p), pre_p,
+ post_p, is_gimple_val, fb_rvalue);
+ /* TMR_STEP and TMR_OFFSET are always integer constants. */
+ ret = MIN (r0, r1);
+ }
+ break;
+
case NON_LVALUE_EXPR:
/* This should have been stripped above. */
gcc_unreachable ();
@@ -6838,19 +6856,6 @@ gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p,
break;
}
- case CHANGE_DYNAMIC_TYPE_EXPR:
- {
- gimple cdt;
-
- ret = gimplify_expr (&CHANGE_DYNAMIC_TYPE_LOCATION (*expr_p),
- pre_p, post_p, is_gimple_reg, fb_lvalue);
- cdt = gimple_build_cdt (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*expr_p),
- CHANGE_DYNAMIC_TYPE_LOCATION (*expr_p));
- gimplify_seq_add_stmt (pre_p, cdt);
- ret = GS_ALL_DONE;
- }
- break;
-
case OBJ_TYPE_REF:
{
enum gimplify_status r0, r1;
diff --git a/gcc/gstab.h b/gcc/gstab.h
index 7f82b55ec10..fccb296cd9a 100644
--- a/gcc/gstab.h
+++ b/gcc/gstab.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 1997, 1998, 2001 Free Software Foundation, Inc.
+/* Copyright (C) 1997, 1998, 2001, 2009 Free Software Foundation, Inc.
This file is part of GCC.
@@ -21,12 +21,15 @@ along with GCC; see the file COPYING3. If not see
#define __define_stab(NAME, CODE, STRING) NAME=CODE,
-enum __stab_debug_code
+enum
{
#include "stab.def"
LAST_UNUSED_STAB_CODE
};
+/* stabs debug codes really are integers with expressive names. */
+typedef int stab_code_type;
+
#undef __define_stab
#endif /* ! GCC_GSTAB_H */
diff --git a/gcc/hooks.c b/gcc/hooks.c
index 796d915e1c6..5af3cd1c411 100644
--- a/gcc/hooks.c
+++ b/gcc/hooks.c
@@ -328,3 +328,10 @@ hook_constcharptr_int_const_tree_const_tree_null (int i ATTRIBUTE_UNUSED,
{
return NULL;
}
+
+/* Generic hook that takes a const_tree and returns NULL_TREE. */
+tree
+hook_tree_const_tree_null (const_tree t ATTRIBUTE_UNUSED)
+{
+ return NULL;
+}
diff --git a/gcc/hooks.h b/gcc/hooks.h
index 89e7f6dbf43..b057d5d6118 100644
--- a/gcc/hooks.h
+++ b/gcc/hooks.h
@@ -63,6 +63,8 @@ extern int hook_int_rtx_0 (rtx);
extern int hook_int_rtx_bool_0 (rtx, bool);
extern int hook_int_size_t_constcharptr_int_0 (size_t, const char *, int);
+extern tree hook_tree_const_tree_null (const_tree);
+
extern tree hook_tree_tree_tree_null (tree, tree);
extern tree hook_tree_tree_tree_tree_null (tree, tree, tree);
extern tree hook_tree_tree_tree_tree_3rd_identity (tree, tree, tree);
diff --git a/gcc/hwint.h b/gcc/hwint.h
index 4e0679c77b6..18085156ac2 100644
--- a/gcc/hwint.h
+++ b/gcc/hwint.h
@@ -99,6 +99,7 @@ extern char sizeof_long_long_must_be_8[sizeof(long long) == 8 ? 1 : -1];
|| (HOST_BITS_PER_LONGLONG < 64 && HOST_BITS_PER___INT64 < 64)
# define HOST_WIDEST_INT HOST_WIDE_INT
# define HOST_BITS_PER_WIDEST_INT HOST_BITS_PER_WIDE_INT
+# define HOST_WIDEST_INT_PRINT HOST_WIDE_INT_PRINT
# define HOST_WIDEST_INT_PRINT_DEC HOST_WIDE_INT_PRINT_DEC
# define HOST_WIDEST_INT_PRINT_DEC_C HOST_WIDE_INT_PRINT_DEC_C
# define HOST_WIDEST_INT_PRINT_UNSIGNED HOST_WIDE_INT_PRINT_UNSIGNED
@@ -116,6 +117,7 @@ extern char sizeof_long_long_must_be_8[sizeof(long long) == 8 ? 1 : -1];
#error "This line should be impossible to reach"
# endif
# endif
+# define HOST_WIDEST_INT_PRINT HOST_LONG_LONG_FORMAT
# define HOST_WIDEST_INT_PRINT_DEC "%" HOST_LONG_LONG_FORMAT "d"
# define HOST_WIDEST_INT_PRINT_DEC_C "%" HOST_LONG_LONG_FORMAT "dLL"
# define HOST_WIDEST_INT_PRINT_UNSIGNED "%" HOST_LONG_LONG_FORMAT "u"
diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c
index 2b63806172b..581a88a1b6c 100644
--- a/gcc/ipa-cp.c
+++ b/gcc/ipa-cp.c
@@ -396,7 +396,7 @@ ipcp_cloning_candidate_p (struct cgraph_node *node)
cgraph_node_name (node));
return false;
}
- if (node->local.inline_summary.self_insns < n_calls)
+ if (node->local.inline_summary.self_size < n_calls)
{
if (dump_file)
fprintf (dump_file, "Considering %s for cloning; code would shrink.\n",
@@ -837,10 +837,7 @@ ipcp_update_callgraph (void)
{
next = cs->next_caller;
if (!ipcp_node_is_clone (cs->caller) && ipcp_need_redirect_p (cs))
- {
- cgraph_redirect_edge_callee (cs, orig_node);
- gimple_call_set_fndecl (cs->call_stmt, orig_node->decl);
- }
+ cgraph_redirect_edge_callee (cs, orig_node);
}
}
}
@@ -916,7 +913,7 @@ ipcp_estimate_growth (struct cgraph_node *node)
call site. Precise cost is dificult to get, as our size metric counts
constants and moves as free. Generally we are looking for cases that
small function is called very many times. */
- growth = node->local.inline_summary.self_insns
+ growth = node->local.inline_summary.self_size
- removable_args * redirectable_node_callers;
if (growth < 0)
return 0;
@@ -956,7 +953,7 @@ ipcp_estimate_cloning_cost (struct cgraph_node *node)
cost /= freq_sum * 1000 / REG_BR_PROB_BASE + 1;
if (dump_file)
fprintf (dump_file, "Cost of versioning %s is %i, (size: %i, freq: %i)\n",
- cgraph_node_name (node), cost, node->local.inline_summary.self_insns,
+ cgraph_node_name (node), cost, node->local.inline_summary.self_size,
freq_sum);
return cost + 1;
}
@@ -1012,7 +1009,7 @@ ipcp_insert_stage (void)
{
if (node->count > max_count)
max_count = node->count;
- overall_size += node->local.inline_summary.self_insns;
+ overall_size += node->local.inline_summary.self_size;
}
max_new_size = overall_size;
diff --git a/gcc/ipa-inline.c b/gcc/ipa-inline.c
index 18eed571aae..28f0ec9862d 100644
--- a/gcc/ipa-inline.c
+++ b/gcc/ipa-inline.c
@@ -138,6 +138,9 @@ along with GCC; see the file COPYING3. If not see
#include "tree-flow.h"
#include "rtl.h"
#include "ipa-prop.h"
+#include "except.h"
+
+#define MAX_TIME 1000000000
/* Mode incremental inliner operate on:
@@ -164,8 +167,8 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *, enum inlining_mode,
/* Statistics we collect about inlining algorithm. */
static int ncalls_inlined;
static int nfunctions_inlined;
-static int overall_insns;
-static gcov_type max_count;
+static int overall_size;
+static gcov_type max_count, max_benefit;
/* Holders of ipa cgraph hooks: */
static struct cgraph_node_hook_list *function_insertion_hook_holder;
@@ -176,19 +179,30 @@ inline_summary (struct cgraph_node *node)
return &node->local.inline_summary;
}
-/* Estimate size of the function after inlining WHAT into TO. */
+/* Estimate self time of the function after inlining WHAT into TO. */
static int
-cgraph_estimate_size_after_inlining (int times, struct cgraph_node *to,
+cgraph_estimate_time_after_inlining (int frequency, struct cgraph_node *to,
struct cgraph_node *what)
{
- int size;
- tree fndecl = what->decl, arg;
- int call_insns = PARAM_VALUE (PARAM_INLINE_CALL_COST);
+ gcov_type time = (((gcov_type)what->global.time
+ - inline_summary (what)->time_inlining_benefit)
+ * frequency + CGRAPH_FREQ_BASE / 2) / CGRAPH_FREQ_BASE
+ + to->global.time;
+ if (time < 0)
+ time = 0;
+ if (time > MAX_TIME)
+ time = MAX_TIME;
+ return time;
+}
- for (arg = DECL_ARGUMENTS (fndecl); arg; arg = TREE_CHAIN (arg))
- call_insns += estimate_move_cost (TREE_TYPE (arg));
- size = (what->global.insns - call_insns) * times + to->global.insns;
+/* Estimate self time of the function after inlining WHAT into TO. */
+
+static int
+cgraph_estimate_size_after_inlining (int times, struct cgraph_node *to,
+ struct cgraph_node *what)
+{
+ int size = (what->global.size - inline_summary (what)->size_inlining_benefit) * times + to->global.size;
gcc_assert (size >= 0);
return size;
}
@@ -214,7 +228,10 @@ cgraph_clone_inlined_nodes (struct cgraph_edge *e, bool duplicate,
{
gcc_assert (!e->callee->global.inlined_to);
if (e->callee->analyzed)
- overall_insns -= e->callee->global.insns, nfunctions_inlined++;
+ {
+ overall_size -= e->callee->global.size;
+ nfunctions_inlined++;
+ }
duplicate = false;
}
else
@@ -254,12 +271,12 @@ static bool
cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original,
VEC (cgraph_edge_p, heap) **new_edges)
{
- int old_insns = 0, new_insns = 0;
+ int old_size = 0, new_size = 0;
struct cgraph_node *to = NULL, *what;
struct cgraph_edge *curr = e;
-
- if (e->callee->inline_decl)
- cgraph_redirect_edge_callee (e, cgraph_node (e->callee->inline_decl));
+ int freq;
+ bool duplicate = false;
+ int orig_size = e->callee->global.size;
gcc_assert (e->inline_failed);
e->inline_failed = CIF_OK;
@@ -268,23 +285,28 @@ cgraph_mark_inline_edge (struct cgraph_edge *e, bool update_original,
DECL_POSSIBLY_INLINED (e->callee->decl) = true;
e->callee->global.inlined = true;
+ if (e->callee->callers->next_caller
+ || e->callee->needed)
+ duplicate = true;
cgraph_clone_inlined_nodes (e, true, update_original);
what = e->callee;
+ freq = e->frequency;
/* Now update size of caller and all functions caller is inlined into. */
for (;e && !e->inline_failed; e = e->caller->callers)
{
- old_insns = e->caller->global.insns;
- new_insns = cgraph_estimate_size_after_inlining (1, e->caller,
- what);
- gcc_assert (new_insns >= 0);
to = e->caller;
- to->global.insns = new_insns;
+ old_size = e->caller->global.size;
+ new_size = cgraph_estimate_size_after_inlining (1, to, what);
+ to->global.size = new_size;
+ to->global.time = cgraph_estimate_time_after_inlining (freq, to, what);
}
gcc_assert (what->global.inlined_to == to);
- if (new_insns > old_insns)
- overall_insns += new_insns - old_insns;
+ if (new_size > old_size)
+ overall_size += new_size - old_size;
+ if (!duplicate)
+ overall_size -= orig_size;
ncalls_inlined++;
if (flag_indirect_inlining)
@@ -339,7 +361,7 @@ cgraph_estimate_growth (struct cgraph_node *node)
self_recursive = true;
if (e->inline_failed)
growth += (cgraph_estimate_size_after_inlining (1, e->caller, node)
- - e->caller->global.insns);
+ - e->caller->global.size);
}
/* ??? Wrong for non-trivially self recursive functions or cases where
@@ -347,7 +369,7 @@ cgraph_estimate_growth (struct cgraph_node *node)
as in that case we will keep the body around, but we will also avoid
some inlining. */
if (!node->needed && !DECL_EXTERNAL (node->decl) && !self_recursive)
- growth -= node->global.insns;
+ growth -= node->global.size;
node->global.estimated_growth = growth;
return growth;
@@ -382,17 +404,17 @@ cgraph_check_inline_limits (struct cgraph_node *to, struct cgraph_node *what,
/* When inlining large function body called once into small function,
take the inlined function as base for limiting the growth. */
- if (inline_summary (to)->self_insns > inline_summary(what)->self_insns)
- limit = inline_summary (to)->self_insns;
+ if (inline_summary (to)->self_size > inline_summary(what)->self_size)
+ limit = inline_summary (to)->self_size;
else
- limit = inline_summary (what)->self_insns;
+ limit = inline_summary (what)->self_size;
limit += limit * PARAM_VALUE (PARAM_LARGE_FUNCTION_GROWTH) / 100;
/* Check the size after inlining against the function limits. But allow
the function to shrink if it went over the limits by forced inlining. */
newsize = cgraph_estimate_size_after_inlining (times, to, what);
- if (newsize >= to->global.insns
+ if (newsize >= to->global.size
&& newsize > PARAM_VALUE (PARAM_LARGE_FUNCTION_INSNS)
&& newsize > limit)
{
@@ -425,8 +447,6 @@ cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason)
{
tree decl = n->decl;
- if (n->inline_decl)
- decl = n->inline_decl;
if (!flag_inline_small_functions && !DECL_DECLARED_INLINE_P (decl))
{
if (reason)
@@ -443,7 +463,7 @@ cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason)
if (DECL_DECLARED_INLINE_P (decl))
{
- if (n->global.insns >= MAX_INLINE_INSNS_SINGLE)
+ if (n->global.size >= MAX_INLINE_INSNS_SINGLE)
{
if (reason)
*reason = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
@@ -452,7 +472,7 @@ cgraph_default_inline_p (struct cgraph_node *n, cgraph_inline_failed_t *reason)
}
else
{
- if (n->global.insns >= MAX_INLINE_INSNS_AUTO)
+ if (n->global.size >= MAX_INLINE_INSNS_AUTO)
{
if (reason)
*reason = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
@@ -494,11 +514,11 @@ cgraph_recursive_inlining_p (struct cgraph_node *to,
static int
cgraph_edge_badness (struct cgraph_edge *edge)
{
- int badness;
+ gcov_type badness;
int growth =
cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee);
- growth -= edge->caller->global.insns;
+ growth -= edge->caller->global.size;
/* Always prefer inlining saving code size. */
if (growth <= 0)
@@ -507,7 +527,8 @@ cgraph_edge_badness (struct cgraph_edge *edge)
/* When profiling is available, base priorities -(#calls / growth).
So we optimize for overall number of "executed" inlined calls. */
else if (max_count)
- badness = ((int)((double)edge->count * INT_MIN / max_count)) / growth;
+ badness = ((int)((double)edge->count * INT_MIN / max_count / (max_benefit + 1))
+ * (inline_summary (edge->callee)->time_inlining_benefit + 1)) / growth;
/* When function local profile is available, base priorities on
growth / frequency, so we optimize for overall frequency of inlined
@@ -520,21 +541,23 @@ cgraph_edge_badness (struct cgraph_edge *edge)
of the same size gets priority). */
else if (flag_guess_branch_prob)
{
- int div = edge->frequency * 100 / CGRAPH_FREQ_BASE;
- int growth =
- cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee);
- growth -= edge->caller->global.insns;
- badness = growth * 256;
+ int div = edge->frequency * 100 / CGRAPH_FREQ_BASE + 1;
+ badness = growth * 10000;
+ div *= MIN (100 * inline_summary (edge->callee)->time_inlining_benefit
+ / (edge->callee->global.time + 1) + 1, 100);
+
/* Decrease badness if call is nested. */
/* Compress the range so we don't overflow. */
- if (div > 256)
- div = 256 + ceil_log2 (div) - 8;
+ if (div > 10000)
+ div = 10000 + ceil_log2 (div) - 8;
if (div < 1)
div = 1;
if (badness > 0)
badness /= div;
badness += cgraph_estimate_growth (edge->callee);
+ if (badness > INT_MAX)
+ badness = INT_MAX;
}
/* When function local profile is not available or it does not give
useful information (ie frequency is zero), base the cost on
@@ -767,8 +790,9 @@ cgraph_decide_recursive_inlining (struct cgraph_node *node,
fibheap_delete (heap);
if (dump_file)
fprintf (dump_file,
- "\n Inlined %i times, body grown from %i to %i insns\n", n,
- master_clone->global.insns, node->global.insns);
+ "\n Inlined %i times, body grown from size %i to %i, time %i to %i\n", n,
+ master_clone->global.size, node->global.size,
+ master_clone->global.time, node->global.time);
/* Remove master clone we used for inlining. We rely that clones inlined
into master clone gets queued just before master clone so we don't
@@ -846,7 +870,7 @@ cgraph_decide_inlining_of_small_functions (void)
cgraph_inline_failed_t failed_reason;
fibheap_t heap = fibheap_new ();
bitmap updated_nodes = BITMAP_ALLOC (NULL);
- int min_insns, max_insns;
+ int min_size, max_size;
VEC (cgraph_edge_p, heap) *new_indirect_edges = NULL;
if (flag_indirect_inlining)
@@ -880,26 +904,26 @@ cgraph_decide_inlining_of_small_functions (void)
}
}
- max_insns = compute_max_insns (overall_insns);
- min_insns = overall_insns;
+ max_size = compute_max_insns (overall_size);
+ min_size = overall_size;
- while (overall_insns <= max_insns
+ while (overall_size <= max_size
&& (edge = (struct cgraph_edge *) fibheap_extract_min (heap)))
{
- int old_insns = overall_insns;
+ int old_size = overall_size;
struct cgraph_node *where;
int growth =
cgraph_estimate_size_after_inlining (1, edge->caller, edge->callee);
cgraph_inline_failed_t not_good = CIF_OK;
- growth -= edge->caller->global.insns;
+ growth -= edge->caller->global.size;
if (dump_file)
{
fprintf (dump_file,
- "\nConsidering %s with %i insns\n",
+ "\nConsidering %s with %i size\n",
cgraph_node_name (edge->callee),
- edge->callee->global.insns);
+ edge->callee->global.size);
fprintf (dump_file,
" to be inlined into %s in %s:%i\n"
" Estimated growth after inlined into all callees is %+i insns.\n"
@@ -1041,19 +1065,20 @@ cgraph_decide_inlining_of_small_functions (void)
if (dump_file)
{
fprintf (dump_file,
- " Inlined into %s which now has %i insns,"
- "net change of %+i insns.\n",
+ " Inlined into %s which now has size %i and self time %i,"
+ "net change of %+i.\n",
cgraph_node_name (edge->caller),
- edge->caller->global.insns,
- overall_insns - old_insns);
+ edge->caller->global.time,
+ edge->caller->global.size,
+ overall_size - old_size);
}
- if (min_insns > overall_insns)
+ if (min_size > overall_size)
{
- min_insns = overall_insns;
- max_insns = compute_max_insns (min_insns);
+ min_size = overall_size;
+ max_size = compute_max_insns (min_size);
if (dump_file)
- fprintf (dump_file, "New minimal insns reached: %i\n", min_insns);
+ fprintf (dump_file, "New minimal size reached: %i\n", min_size);
}
}
while ((edge = (struct cgraph_edge *) fibheap_extract_min (heap)) != NULL)
@@ -1082,34 +1107,38 @@ cgraph_decide_inlining (void)
int nnodes;
struct cgraph_node **order =
XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
- int old_insns = 0;
+ int old_size = 0;
int i;
- int initial_insns = 0;
bool redo_always_inline = true;
+ int initial_size = 0;
cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
max_count = 0;
+ max_benefit = 0;
for (node = cgraph_nodes; node; node = node->next)
- if (node->analyzed && (node->needed || node->reachable))
+ if (node->analyzed)
{
struct cgraph_edge *e;
- initial_insns += inline_summary (node)->self_insns;
- gcc_assert (inline_summary (node)->self_insns == node->global.insns);
+ gcc_assert (inline_summary (node)->self_size == node->global.size);
+ gcc_assert (node->needed || node->reachable);
+ initial_size += node->global.size;
for (e = node->callees; e; e = e->next_callee)
if (max_count < e->count)
max_count = e->count;
+ if (max_benefit < inline_summary (node)->time_inlining_benefit)
+ max_benefit = inline_summary (node)->time_inlining_benefit;
}
- overall_insns = initial_insns;
gcc_assert (!max_count || (profile_info && flag_branch_probabilities));
+ overall_size = initial_size;
nnodes = cgraph_postorder (order);
if (dump_file)
fprintf (dump_file,
- "\nDeciding on inlining. Starting with %i insns.\n",
- initial_insns);
+ "\nDeciding on inlining. Starting with size %i.\n",
+ initial_size);
for (node = cgraph_nodes; node; node = node->next)
node->aux = 0;
@@ -1143,9 +1172,9 @@ cgraph_decide_inlining (void)
continue;
if (dump_file)
fprintf (dump_file,
- "\nConsidering %s %i insns (always inline)\n",
- cgraph_node_name (node), node->global.insns);
- old_insns = overall_insns;
+ "\nConsidering %s size:%i (always inline)\n",
+ cgraph_node_name (node), node->global.size);
+ old_size = overall_size;
for (e = node->callers; e; e = next)
{
next = e->next_caller;
@@ -1164,9 +1193,9 @@ cgraph_decide_inlining (void)
redo_always_inline = true;
if (dump_file)
fprintf (dump_file,
- " Inlined into %s which now has %i insns.\n",
+ " Inlined into %s which now has size %i.\n",
cgraph_node_name (e->caller),
- e->caller->global.insns);
+ e->caller->global.size);
}
/* Inlining self recursive function might introduce new calls to
themselves we didn't see in the loop above. Fill in the proper
@@ -1176,8 +1205,8 @@ cgraph_decide_inlining (void)
e->inline_failed = CIF_RECURSIVE_INLINING;
if (dump_file)
fprintf (dump_file,
- " Inlined for a net change of %+i insns.\n",
- overall_insns - old_insns);
+ " Inlined for a net change of %+i size.\n",
+ overall_size - old_size);
}
}
@@ -1202,30 +1231,29 @@ cgraph_decide_inlining (void)
&& !DECL_EXTERNAL (node->decl)
&& !DECL_COMDAT (node->decl))
{
+ old_size = overall_size;
if (dump_file)
{
fprintf (dump_file,
- "\nConsidering %s %i insns.\n",
- cgraph_node_name (node), node->global.insns);
+ "\nConsidering %s size %i.\n",
+ cgraph_node_name (node), node->global.size);
fprintf (dump_file,
" Called once from %s %i insns.\n",
cgraph_node_name (node->callers->caller),
- node->callers->caller->global.insns);
+ node->callers->caller->global.size);
}
- old_insns = overall_insns;
-
if (cgraph_check_inline_limits (node->callers->caller, node,
NULL, false))
{
cgraph_mark_inline (node->callers);
if (dump_file)
fprintf (dump_file,
- " Inlined into %s which now has %i insns"
- " for a net change of %+i insns.\n",
+ " Inlined into %s which now has %i size"
+ " for a net change of %+i size.\n",
cgraph_node_name (node->callers->caller),
- node->callers->caller->global.insns,
- overall_insns - old_insns);
+ node->callers->caller->global.size,
+ overall_size - old_size);
}
else
{
@@ -1244,9 +1272,9 @@ cgraph_decide_inlining (void)
if (dump_file)
fprintf (dump_file,
"\nInlined %i calls, eliminated %i functions, "
- "%i insns turned to %i insns.\n\n",
- ncalls_inlined, nfunctions_inlined, initial_insns,
- overall_insns);
+ "size %i turned to %i size.\n\n",
+ ncalls_inlined, nfunctions_inlined, initial_size,
+ overall_size);
free (order);
return 0;
}
@@ -1331,6 +1359,20 @@ try_inline (struct cgraph_edge *e, enum inlining_mode mode, int depth)
return inlined;
}
+/* Return true when N is leaf function. Accept cheap (pure&const) builtins
+ in leaf functions. */
+static bool
+leaf_node_p (struct cgraph_node *n)
+{
+ struct cgraph_edge *e;
+ for (e = n->callees; e; e = e->next_callee)
+ if (!DECL_BUILT_IN (e->callee->decl)
+ || (!TREE_READONLY (e->callee->decl)
+ || DECL_PURE_P (e->callee->decl)))
+ return false;
+ return true;
+}
+
/* Decide on the inlining. We do so in the topological order to avoid
expenses on updating data structures.
DEPTH is depth of recursion, used only for debug output. */
@@ -1417,7 +1459,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
}
continue;
}
- if (!e->callee->analyzed && !e->callee->inline_decl)
+ if (!e->callee->analyzed)
{
if (dump_file)
{
@@ -1434,6 +1476,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
if (mode != INLINE_ALL && mode != INLINE_ALWAYS_INLINE)
for (e = node->callees; e; e = e->next_callee)
{
+ int allowed_growth = 0;
if (!e->callee->local.inlinable
|| !e->inline_failed
|| e->callee->local.disregard_inline_limits)
@@ -1460,6 +1503,10 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
}
continue;
}
+
+ if (cgraph_maybe_hot_edge_p (e) && leaf_node_p (e->callee))
+ allowed_growth = PARAM_VALUE (PARAM_EARLY_INLINING_INSNS);
+
/* When the function body would grow and inlining the function won't
eliminate the need for offline copy of the function, don't inline.
*/
@@ -1467,22 +1514,22 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
|| (!flag_inline_functions
&& !DECL_DECLARED_INLINE_P (e->callee->decl)))
&& (cgraph_estimate_size_after_inlining (1, e->caller, e->callee)
- > e->caller->global.insns)
- && cgraph_estimate_growth (e->callee) > 0)
+ > e->caller->global.size + allowed_growth)
+ && cgraph_estimate_growth (e->callee) > allowed_growth)
{
if (dump_file)
{
indent_to (dump_file, depth);
fprintf (dump_file,
- "Not inlining: code size would grow by %i insns.\n",
+ "Not inlining: code size would grow by %i.\n",
cgraph_estimate_size_after_inlining (1, e->caller,
e->callee)
- - e->caller->global.insns);
+ - e->caller->global.size);
}
continue;
}
if (!cgraph_check_inline_limits (node, e->callee, &e->inline_failed,
- false)
+ false)
|| gimple_call_cannot_inline_p (e->call_stmt))
{
if (dump_file)
@@ -1493,7 +1540,7 @@ cgraph_decide_inlining_incrementally (struct cgraph_node *node,
}
continue;
}
- if (!e->callee->analyzed && !e->callee->inline_decl)
+ if (!e->callee->analyzed)
{
if (dump_file)
{
@@ -1611,6 +1658,178 @@ struct simple_ipa_opt_pass pass_ipa_early_inline =
}
};
+/* See if statement might disappear after inlining. We are not terribly
+ sophisficated, basically looking for simple abstraction penalty wrappers. */
+
+static bool
+likely_eliminated_by_inlining_p (gimple stmt)
+{
+ enum gimple_code code = gimple_code (stmt);
+ switch (code)
+ {
+ case GIMPLE_RETURN:
+ return true;
+ case GIMPLE_ASSIGN:
+ if (gimple_num_ops (stmt) != 2)
+ return false;
+
+ /* Casts of parameters, loads from parameters passed by reference
+ and stores to return value or parameters are probably free after
+ inlining. */
+ if (gimple_assign_rhs_code (stmt) == CONVERT_EXPR
+ || gimple_assign_rhs_code (stmt) == NOP_EXPR
+ || gimple_assign_rhs_code (stmt) == VIEW_CONVERT_EXPR
+ || gimple_assign_rhs_class (stmt) == GIMPLE_SINGLE_RHS)
+ {
+ tree rhs = gimple_assign_rhs1 (stmt);
+ tree lhs = gimple_assign_lhs (stmt);
+ tree inner_rhs = rhs;
+ tree inner_lhs = lhs;
+ bool rhs_free = false;
+ bool lhs_free = false;
+
+ while (handled_component_p (inner_lhs) || TREE_CODE (inner_lhs) == INDIRECT_REF)
+ inner_lhs = TREE_OPERAND (inner_lhs, 0);
+ while (handled_component_p (inner_rhs)
+ || TREE_CODE (inner_rhs) == ADDR_EXPR || TREE_CODE (inner_rhs) == INDIRECT_REF)
+ inner_rhs = TREE_OPERAND (inner_rhs, 0);
+
+
+ if (TREE_CODE (inner_rhs) == PARM_DECL
+ || (TREE_CODE (inner_rhs) == SSA_NAME
+ && SSA_NAME_IS_DEFAULT_DEF (inner_rhs)
+ && TREE_CODE (SSA_NAME_VAR (inner_rhs)) == PARM_DECL))
+ rhs_free = true;
+ if (rhs_free && is_gimple_reg (lhs))
+ lhs_free = true;
+ if (((TREE_CODE (inner_lhs) == PARM_DECL
+ || (TREE_CODE (inner_lhs) == SSA_NAME
+ && SSA_NAME_IS_DEFAULT_DEF (inner_lhs)
+ && TREE_CODE (SSA_NAME_VAR (inner_lhs)) == PARM_DECL))
+ && inner_lhs != lhs)
+ || TREE_CODE (inner_lhs) == RESULT_DECL
+ || (TREE_CODE (inner_lhs) == SSA_NAME
+ && TREE_CODE (SSA_NAME_VAR (inner_lhs)) == RESULT_DECL))
+ lhs_free = true;
+ if (lhs_free && (is_gimple_reg (rhs) || is_gimple_min_invariant (rhs)))
+ rhs_free = true;
+ if (lhs_free && rhs_free)
+ return true;
+ }
+ return false;
+ default:
+ return false;
+ }
+}
+
+/* Compute function body size parameters for NODE. */
+
+static void
+estimate_function_body_sizes (struct cgraph_node *node)
+{
+ gcov_type time = 0;
+ gcov_type time_inlining_benefit = 0;
+ int size = 0;
+ int size_inlining_benefit = 0;
+ basic_block bb;
+ gimple_stmt_iterator bsi;
+ struct function *my_function = DECL_STRUCT_FUNCTION (node->decl);
+ tree arg;
+ int freq;
+ tree funtype = TREE_TYPE (node->decl);
+ bitmap must_not_throw = must_not_throw_labels ();
+
+ if (dump_file)
+ {
+ fprintf (dump_file, "Analyzing function body size: %s\n", cgraph_node_name (node));
+ }
+
+ gcc_assert (my_function && my_function->cfg);
+ FOR_EACH_BB_FN (bb, my_function)
+ {
+ freq = compute_call_stmt_bb_frequency (node->decl, bb);
+ for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+ {
+ int this_size = estimate_num_insns (gsi_stmt (bsi), &eni_size_weights);
+ int this_time = estimate_num_insns (gsi_stmt (bsi), &eni_time_weights);
+
+ /* MUST_NOT_THROW is usually handled by runtime calling terminate and stopping
+ stacking unwinding. However when there is local cleanup that can resume
+ to MUST_NOT_THROW then we generate explicit handler containing
+ std::terminate () call.
+
+ Because inlining of function can introduce new cleanup region, prior
+ inlining we keep std::terinate () calls for every MUST_NOT_THROW containing
+ function call. Wast majority of these will be eliminated after inlining
+ and crossjumping will inify possible duplicated calls. So ignore
+ the handlers for function body estimates. */
+ if (gimple_code (gsi_stmt (bsi)) == GIMPLE_LABEL
+ && bitmap_bit_p (must_not_throw,
+ LABEL_DECL_UID (gimple_label_label (gsi_stmt (bsi)))))
+ {
+ if (dump_file)
+ fprintf (dump_file, " MUST_NOT_THROW landing pad. Ignoring whole BB.\n");
+ }
+ if (dump_file)
+ {
+ fprintf (dump_file, " freq:%6i size:%3i time:%3i ", freq, this_size, this_time);
+ print_gimple_stmt (dump_file, gsi_stmt (bsi), 0, 0);
+ }
+ this_time *= freq;
+ time += this_time;
+ size += this_size;
+ if (likely_eliminated_by_inlining_p (gsi_stmt (bsi)))
+ {
+ size_inlining_benefit += this_size;
+ time_inlining_benefit += this_time;
+ if (dump_file)
+ fprintf (dump_file, " Likely eliminated\n");
+ }
+ gcc_assert (time >= 0);
+ gcc_assert (size >= 0);
+ }
+ }
+ time = (time + CGRAPH_FREQ_BASE / 2) / CGRAPH_FREQ_BASE;
+ time_inlining_benefit = ((time_inlining_benefit + CGRAPH_FREQ_BASE / 2)
+ / CGRAPH_FREQ_BASE);
+ if (dump_file)
+ {
+ fprintf (dump_file, "Overall function body time: %i-%i size: %i-%i\n",
+ (int)time, (int)time_inlining_benefit,
+ size, size_inlining_benefit);
+ }
+ time_inlining_benefit += eni_time_weights.call_cost;
+ size_inlining_benefit += eni_size_weights.call_cost;
+ if (!VOID_TYPE_P (TREE_TYPE (funtype)))
+ {
+ int cost = estimate_move_cost (TREE_TYPE (funtype));
+ time_inlining_benefit += cost;
+ size_inlining_benefit += cost;
+ }
+ for (arg = DECL_ARGUMENTS (node->decl); arg; arg = TREE_CHAIN (arg))
+ if (!VOID_TYPE_P (TREE_TYPE (arg)))
+ {
+ int cost = estimate_move_cost (TREE_TYPE (arg));
+ time_inlining_benefit += cost;
+ size_inlining_benefit += cost;
+ }
+ if (time_inlining_benefit > MAX_TIME)
+ time_inlining_benefit = MAX_TIME;
+ if (time > MAX_TIME)
+ time = MAX_TIME;
+ inline_summary (node)->self_time = time;
+ inline_summary (node)->self_size = size;
+ if (dump_file)
+ {
+ fprintf (dump_file, "With function call overhead time: %i-%i size: %i-%i\n",
+ (int)time, (int)time_inlining_benefit,
+ size, size_inlining_benefit);
+ }
+ inline_summary (node)->time_inlining_benefit = time_inlining_benefit;
+ inline_summary (node)->size_inlining_benefit = size_inlining_benefit;
+ BITMAP_FREE (must_not_throw);
+}
+
/* Compute parameters of functions used by inliner. */
unsigned int
compute_inline_parameters (struct cgraph_node *node)
@@ -1628,19 +1847,13 @@ compute_inline_parameters (struct cgraph_node *node)
/* Can this function be inlined at all? */
node->local.inlinable = tree_inlinable_function_p (current_function_decl);
-
- /* Estimate the number of instructions for this function.
- ??? At -O0 we don't use this information except for the dumps, and
- even then only for always_inline functions. But disabling this
- causes ICEs in the inline heuristics... */
- inline_summary (node)->self_insns
- = estimate_num_insns_fn (current_function_decl, &eni_inlining_weights);
if (node->local.inlinable && !node->local.disregard_inline_limits)
node->local.disregard_inline_limits
= DECL_DISREGARD_INLINE_LIMITS (current_function_decl);
-
+ estimate_function_body_sizes (node);
/* Inlining characteristics are maintained by the cgraph_mark_inline. */
- node->global.insns = inline_summary (node)->self_insns;
+ node->global.time = inline_summary (node)->self_time;
+ node->global.size = inline_summary (node)->self_size;
return 0;
}
@@ -1658,7 +1871,7 @@ struct gimple_opt_pass pass_inline_parameters =
{
{
GIMPLE_PASS,
- NULL, /* name */
+ "inline_param", /* name */
NULL, /* gate */
compute_inline_parameters_for_current,/* execute */
NULL, /* sub */
diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c
index f4fa37d5a05..6f5e26b2042 100644
--- a/gcc/ipa-prop.c
+++ b/gcc/ipa-prop.c
@@ -172,48 +172,30 @@ ipa_initialize_node_params (struct cgraph_node *node)
}
}
-/* Check STMT to detect whether a formal parameter is directly modified within
- STMT, the appropriate entry is updated in the modified flags of INFO.
- Directly means that this function does not check for modifications through
- pointers or escaping addresses because all TREE_ADDRESSABLE parameters are
- considered modified anyway. */
+/* Callback of walk_stmt_load_store_addr_ops for the visit_store and visit_addr
+ parameters. If OP is a parameter declaration, mark it as modified in the
+ info structure passed in DATA. */
-static void
-ipa_check_stmt_modifications (struct ipa_node_params *info, gimple stmt)
+static bool
+visit_store_addr_for_mod_analysis (gimple stmt ATTRIBUTE_UNUSED,
+ tree op, void *data)
{
- int j;
- int index;
- tree lhs;
+ struct ipa_node_params *info = (struct ipa_node_params *) data;
- switch (gimple_code (stmt))
+ if (TREE_CODE (op) == PARM_DECL)
{
- case GIMPLE_ASSIGN:
- lhs = gimple_assign_lhs (stmt);
-
- while (handled_component_p (lhs))
- lhs = TREE_OPERAND (lhs, 0);
- if (TREE_CODE (lhs) == SSA_NAME)
- lhs = SSA_NAME_VAR (lhs);
- index = ipa_get_param_decl_index (info, lhs);
- if (index >= 0)
- info->params[index].modified = true;
- break;
-
- case GIMPLE_ASM:
- /* Asm code could modify any of the parameters. */
- for (j = 0; j < ipa_get_param_count (info); j++)
- info->params[j].modified = true;
- break;
-
- default:
- break;
+ int index = ipa_get_param_decl_index (info, op);
+ gcc_assert (index >= 0);
+ info->params[index].modified = true;
}
+
+ return false;
}
/* Compute which formal parameters of function associated with NODE are locally
- modified. Parameters may be modified in NODE if they are TREE_ADDRESSABLE,
- if they appear on the left hand side of an assignment or if there is an
- ASM_EXPR in the function. */
+ modified or their address is taken. Note that this does not apply on
+ parameters with SSA names but those can and should be analyzed
+ differently. */
void
ipa_detect_param_modifications (struct cgraph_node *node)
@@ -222,27 +204,17 @@ ipa_detect_param_modifications (struct cgraph_node *node)
basic_block bb;
struct function *func;
gimple_stmt_iterator gsi;
- gimple stmt;
struct ipa_node_params *info = IPA_NODE_REF (node);
- int i, count;
if (ipa_get_param_count (info) == 0 || info->modification_analysis_done)
return;
func = DECL_STRUCT_FUNCTION (decl);
FOR_EACH_BB_FN (bb, func)
- {
- for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
- {
- stmt = gsi_stmt (gsi);
- ipa_check_stmt_modifications (info, stmt);
- }
- }
-
- count = ipa_get_param_count (info);
- for (i = 0; i < count; i++)
- if (TREE_ADDRESSABLE (ipa_get_param (info, i)))
- info->params[i].modified = true;
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ walk_stmt_load_store_addr_ops (gsi_stmt (gsi), info, NULL,
+ visit_store_addr_for_mod_analysis,
+ visit_store_addr_for_mod_analysis);
info->modification_analysis_done = 1;
}
@@ -456,6 +428,22 @@ fill_member_ptr_cst_jump_function (struct ipa_jump_func *jfunc,
jfunc->value.member_cst.delta = delta;
}
+/* If RHS is an SSA_NAMe and it is defined by a simple copy assign statement,
+ return the rhs of its defining statement. */
+
+static inline tree
+get_ssa_def_if_simple_copy (tree rhs)
+{
+ while (TREE_CODE (rhs) == SSA_NAME && !SSA_NAME_IS_DEFAULT_DEF (rhs))
+ {
+ gimple def_stmt = SSA_NAME_DEF_STMT (rhs);
+
+ if (gimple_assign_single_p (def_stmt))
+ rhs = gimple_assign_rhs1 (def_stmt);
+ }
+ return rhs;
+}
+
/* Traverse statements from CALL backwards, scanning whether the argument ARG
which is a member pointer is filled in with constant values. If it is, fill
the jump function JFUNC in appropriately. METHOD_FIELD and DELTA_FIELD are
@@ -482,7 +470,7 @@ determine_cst_member_ptr (gimple call, tree arg, tree method_field,
gimple stmt = gsi_stmt (gsi);
tree lhs, rhs, fld;
- if (!is_gimple_assign (stmt) || gimple_num_ops (stmt) != 2)
+ if (!gimple_assign_single_p (stmt))
return;
lhs = gimple_assign_lhs (stmt);
@@ -495,6 +483,7 @@ determine_cst_member_ptr (gimple call, tree arg, tree method_field,
fld = TREE_OPERAND (lhs, 1);
if (!method && fld == method_field)
{
+ rhs = get_ssa_def_if_simple_copy (rhs);
if (TREE_CODE (rhs) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (rhs, 0)) == FUNCTION_DECL
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (rhs, 0))) == METHOD_TYPE)
@@ -512,6 +501,7 @@ determine_cst_member_ptr (gimple call, tree arg, tree method_field,
if (!delta && fld == delta_field)
{
+ rhs = get_ssa_def_if_simple_copy (rhs);
if (TREE_CODE (rhs) == INTEGER_CST)
{
delta = rhs;
@@ -617,7 +607,7 @@ ipa_get_stmt_member_ptr_load_param (gimple stmt)
{
tree rhs;
- if (!is_gimple_assign (stmt) || gimple_num_ops (stmt) != 2)
+ if (!gimple_assign_single_p (stmt))
return NULL_TREE;
rhs = gimple_assign_rhs1 (stmt);
@@ -797,7 +787,7 @@ ipa_analyze_call_uses (struct ipa_node_params *info, gimple call)
return;
def = SSA_NAME_DEF_STMT (cond);
- if (!is_gimple_assign (def) || gimple_num_ops (def) != 3
+ if (!is_gimple_assign (def)
|| gimple_assign_rhs_code (def) != BIT_AND_EXPR
|| !integer_onep (gimple_assign_rhs2 (def)))
return;
@@ -808,8 +798,8 @@ ipa_analyze_call_uses (struct ipa_node_params *info, gimple call)
def = SSA_NAME_DEF_STMT (cond);
- if (is_gimple_assign (def) && gimple_num_ops (def) == 2
- && gimple_assign_rhs_code (def) == NOP_EXPR)
+ if (is_gimple_assign (def)
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)))
{
cond = gimple_assign_rhs1 (def);
if (!ipa_is_ssa_with_stmt_def (cond))
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index 960e1144f91..16fbfea4acb 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,15 @@
+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 9f78c73eef2..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)'; \
- $(CXX) -x c++ -c $(ALL_CXXFLAGS) $(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)
- $(CXX) $(ALL_CXXFLAGS) $(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 $@
- $(CXX) $(ALL_CXXFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(JAVA_OBJS) $(BACKEND) $(ZLIB) $(LIBICONV) $(LIBS) attribs.o $(BACKENDLIBS)
jcf-dump$(exeext): $(JCFDUMP_OBJS) $(LIBDEPS)
rm -f $@
- $(CXX) $(ALL_CXXFLAGS) $(LDFLAGS) -o $@ $(JCFDUMP_OBJS) \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ $(JCFDUMP_OBJS) \
$(CPPLIBS) $(ZLIB) $(LDEXP_LIB) $(LIBS)
jvgenmain$(exeext): $(JVGENMAIN_OBJS) $(LIBDEPS)
rm -f $@
- $(CXX) $(ALL_CXXFLAGS) $(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
- $(CXX) -x c++ -c $(ALL_CXXFLAGS) $(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
- $(CXX) -xc++ -c $(ALL_CXXFLAGS) $(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/mips-tfile.c b/gcc/mips-tfile.c
index 4bd716eb4b9..07d229e672c 100644
--- a/gcc/mips-tfile.c
+++ b/gcc/mips-tfile.c
@@ -675,8 +675,6 @@ main (void)
#include "gstab.h"
-#define STAB_CODE_TYPE enum __stab_debug_code
-
#ifndef MALLOC_CHECK
#ifdef __SABER__
#define MALLOC_CHECK
diff --git a/gcc/objc/ChangeLog b/gcc/objc/ChangeLog
index a1f0f242b4c..a7db6bc0ab9 100644
--- a/gcc/objc/ChangeLog
+++ b/gcc/objc/ChangeLog
@@ -1,3 +1,19 @@
+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
+ than NULL_TREE to build_special_member_call.
+
2009-05-10 Ian Lance Taylor <iant@google.com>
* objc-act.c (objc_building_struct): New static variable.
diff --git a/gcc/objc/Make-lang.in b/gcc/objc/Make-lang.in
index 4af67c2231e..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)
- $(CXX) $(ALL_CXXFLAGS) $(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)
- $(CXX) $(ALL_CXXFLAGS) $(LDFLAGS) -o $@ \
+ $(LINKER) $(ALL_LINKERFLAGS) $(LDFLAGS) -o $@ \
$(OBJC_OBJS) $(C_AND_OBJC_OBJS) cc1obj-checksum.o \
$(BACKEND) $(LIBS) $(BACKENDLIBS)
diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c
index 54f18244c1d..9f121f1c313 100644
--- a/gcc/objc/objc-act.c
+++ b/gcc/objc/objc-act.c
@@ -4538,7 +4538,7 @@ objc_generate_cxx_ctor_or_dtor (bool dtor)
(build_special_member_call
(build_ivar_reference (DECL_NAME (ivar)),
dtor ? complete_dtor_identifier : complete_ctor_identifier,
- NULL_TREE, type, LOOKUP_NORMAL, tf_warning_or_error));
+ NULL, type, LOOKUP_NORMAL, tf_warning_or_error));
}
}
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 5a25e95c33a..1a4aea9b37b 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -812,7 +812,6 @@ copy_var_decl (tree var, tree name, tree type)
TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (var);
TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (var);
DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (var);
- DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (var);
DECL_ARTIFICIAL (copy) = DECL_ARTIFICIAL (var);
DECL_IGNORED_P (copy) = DECL_IGNORED_P (var);
DECL_CONTEXT (copy) = DECL_CONTEXT (var);
@@ -5010,7 +5009,6 @@ expand_omp_atomic_pipeline (basic_block load_bb, basic_block store_bb,
false, NULL_TREE, true, GSI_SAME_STMT);
stmt = gimple_build_assign (iaddr, iaddr_val);
gsi_insert_before (&si, stmt, GSI_SAME_STMT);
- DECL_NO_TBAA_P (iaddr) = 1;
DECL_POINTER_ALIAS_SET (iaddr) = 0;
loadedi = create_tmp_var (itype, NULL);
if (gimple_in_ssa_p (cfun))
diff --git a/gcc/output.h b/gcc/output.h
index e7871f980e2..543164a4c69 100644
--- a/gcc/output.h
+++ b/gcc/output.h
@@ -1,7 +1,7 @@
/* Declarations for insn-output.c. These functions are defined in recog.c,
final.c, and varasm.c.
Copyright (C) 1987, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
+ 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
This file is part of GCC.
@@ -94,6 +94,10 @@ extern int insn_current_reference_address (rtx);
Defined in final.c. */
extern int label_to_alignment (rtx);
+/* Find the alignment maximum skip associated with a CODE_LABEL.
+ Defined in final.c. */
+extern int label_to_max_skip (rtx);
+
/* Output a LABEL_REF, or a bare CODE_LABEL, as an assembler symbol. */
extern void output_asm_label (rtx);
diff --git a/gcc/params.def b/gcc/params.def
index 9b5db87d7eb..ccbc305a627 100644
--- a/gcc/params.def
+++ b/gcc/params.def
@@ -100,7 +100,7 @@ DEFPARAM (PARAM_PREDICTABLE_BRANCH_OUTCOME,
DEFPARAM (PARAM_MAX_INLINE_INSNS_SINGLE,
"max-inline-insns-single",
"The maximum number of instructions in a single function eligible for inlining",
- 450, 0, 0)
+ 400, 0, 0)
/* The single function inlining limit for functions that are
inlined by virtue of -finline-functions (-O3).
@@ -112,7 +112,7 @@ DEFPARAM (PARAM_MAX_INLINE_INSNS_SINGLE,
DEFPARAM (PARAM_MAX_INLINE_INSNS_AUTO,
"max-inline-insns-auto",
"The maximum number of instructions when automatically inlining",
- 90, 0, 0)
+ 60, 0, 0)
DEFPARAM (PARAM_MAX_INLINE_INSNS_RECURSIVE,
"max-inline-insns-recursive",
@@ -212,9 +212,9 @@ DEFPARAM(PARAM_IPCP_UNIT_GROWTH,
"ipcp-unit-growth",
"how much can given compilation unit grow because of the interprocedural constant propagation (in percent)",
10, 0, 0)
-DEFPARAM(PARAM_INLINE_CALL_COST,
- "inline-call-cost",
- "expense of call operation relative to ordinary arithmetic operations",
+DEFPARAM(PARAM_EARLY_INLINING_INSNS,
+ "early-inlining-insns",
+ "maximal estimated growth of function body caused by early inlining of single call",
12, 0, 0)
DEFPARAM(PARAM_LARGE_STACK_FRAME,
"large-stack-frame",
@@ -765,6 +765,12 @@ DEFPARAM (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP,
"max basic blocks number in loop for loop invariant motion",
10000, 0, 0)
+/* Avoid SLP vectorization of large basic blocks. */
+DEFPARAM (PARAM_SLP_MAX_INSNS_IN_BB,
+ "slp-max-insns-in-bb",
+ "Maximum number of instructions in basic block to be considered for SLP vectorization",
+ 1000, 0, 0)
+
/*
Local variables:
mode:c
diff --git a/gcc/params.h b/gcc/params.h
index e9e6834ed2e..16ed29234ca 100644
--- a/gcc/params.h
+++ b/gcc/params.h
@@ -170,4 +170,6 @@ typedef enum compiler_param
PARAM_VALUE (PARAM_SWITCH_CONVERSION_BRANCH_RATIO)
#define LOOP_INVARIANT_MAX_BBS_IN_LOOP \
PARAM_VALUE (PARAM_LOOP_INVARIANT_MAX_BBS_IN_LOOP)
+#define SLP_MAX_INSNS_IN_BB \
+ PARAM_VALUE (PARAM_SLP_MAX_INSNS_IN_BB)
#endif /* ! GCC_PARAMS_H */
diff --git a/gcc/passes.c b/gcc/passes.c
index a050df3516e..2408668c083 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -554,7 +554,11 @@ init_optimization_passes (void)
NEXT_PASS (pass_rename_ssa_copies);
NEXT_PASS (pass_ccp);
NEXT_PASS (pass_forwprop);
- NEXT_PASS (pass_update_address_taken);
+ /* pass_build_ealias is a dummy pass that ensures that we
+ execute TODO_rebuild_alias at this point. Re-building
+ alias information also rewrites no longer addressed
+ locals into SSA form if possible. */
+ NEXT_PASS (pass_build_ealias);
NEXT_PASS (pass_sra_early);
NEXT_PASS (pass_copy_prop);
NEXT_PASS (pass_merge_phi);
@@ -662,6 +666,7 @@ init_optimization_passes (void)
NEXT_PASS (pass_dce_loop);
}
NEXT_PASS (pass_complete_unroll);
+ NEXT_PASS (pass_slp_vectorize);
NEXT_PASS (pass_parallelize_loops);
NEXT_PASS (pass_loop_prefetch);
NEXT_PASS (pass_iv_optimize);
diff --git a/gcc/plugin.c b/gcc/plugin.c
index 9362e6a23e5..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,22 +53,13 @@ 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"
};
-/* Object that keeps track of the plugin name and its arguments
- when parsing the command-line options -fplugin=/path/to/NAME.so and
- -fplugin-arg-NAME-<key>[=<value>]. */
-struct plugin_name_args
-{
- char *base_name;
- const char *full_name;
- int argc;
- struct plugin_argument *argv;
- const char *version;
- const char *help;
-};
-
/* Hash table for the plugin_name_args objects created during command-line
parsing. */
static htab_t plugin_name_args_tab = NULL;
@@ -485,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:
{
@@ -537,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. */
@@ -548,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);
}
@@ -596,8 +602,7 @@ try_init_one_plugin (struct plugin_name_args *plugin)
}
/* Call the plugin-provided initialization routine with the arguments. */
- if ((*plugin_init) (plugin->base_name, &gcc_version, plugin->argc,
- plugin->argv))
+ if ((*plugin_init) (plugin, &gcc_version))
{
error ("Fail to initialize plugin %s", plugin->full_name);
return false;
diff --git a/gcc/predict.c b/gcc/predict.c
index 732283d4c22..e3b4b83b863 100644
--- a/gcc/predict.c
+++ b/gcc/predict.c
@@ -168,8 +168,8 @@ cgraph_maybe_hot_edge_p (struct cgraph_edge *edge)
if (lookup_attribute ("hot", DECL_ATTRIBUTES (edge->caller->decl)))
return true;
if (flag_guess_branch_prob
- && edge->frequency < (CGRAPH_FREQ_MAX
- / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)))
+ && edge->frequency <= (CGRAPH_FREQ_BASE
+ / PARAM_VALUE (HOT_BB_FREQUENCY_FRACTION)))
return false;
return true;
}
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index 0d352642157..969c6ea4ba7 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -425,8 +425,6 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
fputs (" virtual", file);
if (DECL_PRESERVE_P (node))
fputs (" preserve", file);
- if (DECL_NO_TBAA_P (node))
- fputs (" no-tbaa", file);
if (DECL_LANG_FLAG_0 (node))
fputs (" decl_0", file);
if (DECL_LANG_FLAG_1 (node))
diff --git a/gcc/reg-stack.c b/gcc/reg-stack.c
index c1fc8207ec2..2f94958a2e2 100644
--- a/gcc/reg-stack.c
+++ b/gcc/reg-stack.c
@@ -1371,21 +1371,23 @@ subst_stack_regs_pat (rtx insn, stack regstack, rtx pat)
if (pat != PATTERN (insn))
{
- /* The fix_truncdi_1 pattern wants to be able to allocate
- its own scratch register. It does this by clobbering
- an fp reg so that it is assured of an empty reg-stack
- register. If the register is live, kill it now.
- Remove the DEAD/UNUSED note so we don't try to kill it
- later too. */
+ /* The fix_truncdi_1 pattern wants to be able to
+ allocate its own scratch register. It does this by
+ clobbering an fp reg so that it is assured of an
+ empty reg-stack register. If the register is live,
+ kill it now. Remove the DEAD/UNUSED note so we
+ don't try to kill it later too.
+
+ In reality the UNUSED note can be absent in some
+ complicated cases when the register is reused for
+ partially set variable. */
if (note)
emit_pop_insn (insn, regstack, *dest, EMIT_BEFORE);
else
- {
- note = find_reg_note (insn, REG_UNUSED, *dest);
- gcc_assert (note);
- }
- remove_note (insn, note);
+ note = find_reg_note (insn, REG_UNUSED, *dest);
+ if (note)
+ remove_note (insn, note);
replace_reg (dest, FIRST_STACK_REG + 1);
}
else
diff --git a/gcc/target-def.h b/gcc/target-def.h
index 99c74e406f8..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
@@ -536,6 +537,10 @@
#define TARGET_INVALID_CONVERSION hook_constcharptr_const_tree_const_tree_null
#define TARGET_INVALID_UNARY_OP hook_constcharptr_int_const_tree_null
#define TARGET_INVALID_BINARY_OP hook_constcharptr_int_const_tree_const_tree_null
+#define TARGET_INVALID_PARAMETER_TYPE hook_constcharptr_const_tree_null
+#define TARGET_INVALID_RETURN_TYPE hook_constcharptr_const_tree_null
+#define TARGET_PROMOTED_TYPE hook_tree_const_tree_null
+#define TARGET_CONVERT_TO_TYPE hook_tree_tree_tree_null
#define TARGET_FIXED_CONDITION_CODE_REGS hook_bool_uintp_uintp_false
@@ -918,10 +923,15 @@
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, \
TARGET_INVALID_BINARY_OP, \
+ TARGET_INVALID_PARAMETER_TYPE, \
+ TARGET_INVALID_RETURN_TYPE, \
+ TARGET_PROMOTED_TYPE, \
+ TARGET_CONVERT_TO_TYPE, \
TARGET_IRA_COVER_CLASSES, \
TARGET_SECONDARY_RELOAD, \
TARGET_EXPAND_TO_RTL_HOOK, \
diff --git a/gcc/target.h b/gcc/target.h
index 43bdfc41ada..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);
@@ -913,6 +917,24 @@ struct gcc_target
is not permitted on TYPE1 and TYPE2, NULL otherwise. */
const char *(*invalid_binary_op) (int op, const_tree type1, const_tree type2);
+ /* Return the diagnostic message string if TYPE is not valid as a
+ function parameter type, NULL otherwise. */
+ const char *(*invalid_parameter_type) (const_tree type);
+
+ /* Return the diagnostic message string if TYPE is not valid as a
+ function return type, NULL otherwise. */
+ const char *(*invalid_return_type) (const_tree type);
+
+ /* If values of TYPE are promoted to some other type when used in
+ expressions (analogous to the integer promotions), return that type,
+ or NULL_TREE otherwise. */
+ tree (*promoted_type) (const_tree type);
+
+ /* Convert EXPR to TYPE, if target-specific types with special conversion
+ rules are involved. Return the converted expression, or NULL to apply
+ the standard conversion rules. */
+ tree (*convert_to_type) (tree type, tree expr);
+
/* Return the array of IRA cover classes for the current target. */
const enum reg_class *(*ira_cover_classes) (void);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b82f4721256..b0706c50a87 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,427 @@
+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 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
+ * g++.dg/cpp0x/enum3.C: New test.
+
+2009-05-25 Richard Guenther <rguenther@suse.de>
+
+ PR tree-optimization/36327
+ * gcc.dg/tree-ssa/ssa-fre-24.c: New testcase.
+ * gcc.dg/tree-ssa/ssa-fre-25.c: Likewise.
+ * gcc.dg/tree-ssa/sra-2.c: Disable FRE.
+ * gcc.dg/vect/no-vfa-vect-43.c: Adjust.
+ * gcc.dg/vect/vect-40.c: Likewise.
+ * gcc.dg/vect/vect-42.c: Likewise.
+ * gcc.dg/vect/vect-46.c: Likewise.
+ * gcc.dg/vect/vect-76.c: Likewise.
+
+2009-05-25 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/40176
+ * gfortran.dg/proc_ptr_18.f90: New.
+ * gfortran.dg/proc_ptr_19.f90: New.
+ * gfortran.dg/proc_ptr_comp_9.f90: New.
+ * gfortran.dg/proc_ptr_comp_10.f90: New.
+
+2009-05-25 Richard Guenther <rguenther@suse.de>
+
+ * gcc.dg/tree-ssa/ssa-fre-14.c: Adjust.
+ * gcc.dg/tree-ssa/ssa-fre-15.c: Likewise.
+
+2009-05-25 Ira Rosen <irar@il.ibm.com>
+
+ PR tree-optimization/40238
+ * gcc.dg/vect/pr40238.c: New test.
+
+2009-05-24 Jerry DeLisle <jvdelisle@gcc.gnu.org>
+ Dominique Dhumieres
+
+ PR fortran/35732
+ PR fortran/39872
+ * gfortran.dg/bounds_check_fail_3.f90: New test.
+ * gfortran.dg/bounds_check_fail_4.f90: New test.
+ * gfortran.dg/bounds_check_14.f90: Update test.
+ * gfortran.dg/bound_4.f90: Update test.
+
+2009-05-24 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/40233
+ * gcc.c-torture/compile/pr40233.c: New testcase.
+
+2009-05-24 Uros Bizjak <ubizjak@gmail.com>
+
+ * gfortran.dg/erf_2.F90 (dg-options): Add -mieee
+ for alpha*-*-* targets.
+
+2009-05-24 Ira Rosen <irar@il.ibm.com>
+
+ * gcc.dg/vect/bb-slp-1.c: New test.
+ * gcc.dg/vect/bb-slp-2.c, gcc.dg/vect/bb-slp-3.c,
+ gcc.dg/vect/bb-slp-4.c, gcc.dg/vect/bb-slp-5.c,
+ gcc.dg/vect/bb-slp-6.c, gcc.dg/vect/bb-slp-7.c,
+ gcc.dg/vect/bb-slp-8.c, gcc.dg/vect/bb-slp-9.c,
+ gcc.dg/vect/bb-slp-10.c, gcc.dg/vect/bb-slp-11.c,
+ gcc.dg/vect/no-tree-reassoc-bb-slp-12.c, gcc.dg/vect/bb-slp-13.c,
+ gcc.dg/vect/bb-slp-14.c, gcc.dg/vect/bb-slp-15.c,
+ gcc.dg/vect/bb-slp-16.c, gcc.dg/vect/bb-slp-17.c,
+ gcc.dg/vect/bb-slp-18.c, gcc.dg/vect/bb-slp-19.c,
+ gcc.dg/vect/bb-slp-20.c, gcc.dg/vect/bb-slp-21.c,
+ gcc.dg/vect/bb-slp-22.c: Likewise.
+ * gcc.dg/vect/vect.exp: Run basic block SLP tests.
+
+2009-05-23 Mark Mitchell <mark@codesourcery.com>
+ Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ * gcc.dg/falign-labels-1.c: New test.
+
+2009-05-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/specs/rep_clause3.ads: New test.
+
+2009-05-23 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/addr6.adb: New test.
+
+2009-05-22 Mark Mitchell <mark@codesourcery.com>
+
+ * lib/target-supports.exp (check_effective_target_arm_thumb2_ok):
+ New function.
+ * gcc.target/arm/thumb2-mul-space.c: New file.
+ * gcc.target/arm/thumb2-mul-space-2.c: New file.
+ * gcc.target/arm/thumb2-mul-space-3.c: New file.
+ * gcc.target/arm/thumb2-mul-speed.c: New file.
+
+2009-05-22 Richard Guenther <rguenther@suse.de>
+
+ PR middle-end/38964
+ * g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C: XFAIL.
+ * gcc.dg/Wstrict-aliasing-converted-assigned.c: Likewise.
+ * gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c: Likewise.
+
+2009-05-22 Mark Mitchell <mark@codesourcery.com>
+
+ * gcc.dg/dll-6.c: New test.
+ * gcc.dg/dll-6a.c: Likewise.
+ * gcc.dg/dll-7.c: Likewise.
+ * gcc.dg/dll-7a.c: Likewise.
+ * g++.dg/ext/dllexport2.C: Likewise.
+ * g++.dg/ext/dllexport2a.cc: Likewise.
+
+2009-05-21 Steve Ellcey <sje@cup.hp.com>
+
+ PR target/37846
+ * gcc.target/ia64/mfused-madd-vect.c: New test.
+ * gcc.target/ia64/mfused-madd.c: New test.
+ * gcc.target/ia64/mno-fused-madd-vect.c: New test.
+ * gcc.target/ia64/mno-fused-madd.c: New test.
+
+2009-05-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ * gcc.target/i386/movbe-1.c: New.
+ * gcc.target/i386/movbe-2.c: Likewise.
+
+2009-05-21 Taras Glek <tglek@mozilla.com>
+
+ * gcc.dg/plugin/selfassign.c (plugin_init): Updated to new
+ plugin_init signature.
+ * g++.dg/plugin/selfassign.c (plugin_init): Likewise.
+ * g++.dg/plugin/dumb_plugin.c (plugin_init): Likewise.
+ * g++.dg/plugin/attribute_plugin.c (plugin_init): Likewise.
+
+2009-05-21 Mark Mitchell <mark@codesourcery.com>
+
+ * gcc.dg/target/arm/neon-vmla-1.c: New.
+ * gcc.dg/target/arm/neon-vmls-1.c: Likewise.
+
+2009-05-20 Adam Nemet <anemet@caviumnetworks.com>
+
+ * gcc.target/mips/octeon-exts-6.c: New test.
+ * gcc.target/mips/extend-1.c: New test.
+ * gcc.target/mips/octeon-exts-2.c: Adjust to not match sign-extension
+ EXTS.
+ * gcc.target/mips/octeon-exts-5.c: Likewise.
+
+2009-05-20 Jakub Jelinek <jakub@redhat.com>
+
+ PR middle-end/40204
+ * gcc.c-torture/compile/pr40204.c: New test.
+
+2009-05-20 Richard Guenther <rguenther@suse.de>
+
+ * gcc.c-torture/compile/20090518-1.c: New testcase.
+
+2009-05-19 Zdenek Dvorak <ook@ucw.cz>
+
+ PR tree-optimization/40087
+ * gcc.dg/tree-ssa/pr40087.c: New test.
+
+2009-05-19 Andrew Pinski <andrew_pinski@playstation.sony.com>
+
+ * gcc.dg/vector-4.c: New testcase.
+ * gcc.dg/simd-1b.c: % is now allowed for integer vectors.
+ * g++.dg/ext/vector16.C: New testcase.
+
+2009-05-19 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR c/40172
+ * gcc.dg/pr40172.c: Renamed to ...
+ * gcc.dg/pr40172-1.c: This.
+
+ * gcc.dg/pr40172-2.c: New.
+ * gcc.dg/pr40172-3.c: Likewise.
+
+2009-05-19 Manuel López-Ibáñez <manu@gcc.gnu.org>
+
+ PR c/40172
+ * gcc.dg/pr40172.c: Add -Wlogical-op to dg-options.
+
+2009-05-19 Eric Botcazou <ebotcazou@adacore.com>
+
+ * gnat.dg/loop_optimization6.ad[sb]: New test.
+
+2009-05-19 Richard Guenther <rguenther@suse.de>
+
+ * gcc.c-torture/compile/20090519-1.c: New testcase.
+
+2009-05-18 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/explicit1.C: New.
+ * g++.dg/cpp0x/explicit2.C: New.
+
+2009-05-18 Dodji Seketeli <dodji@redhat.com>
+
+ PR debug/40109
+ * g++.dg/debug/dwarf2/nested-1.C: New test.
+
+2009-05-18 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR testsuite/39907
+ * gcc.target/x86_64/abi/asm-support.S (snapshot_ret): Preserve
+ stack alignment.
+
+2009-05-18 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/40164
+ * gfortran.dg/proc_ptr_comp_8.f90: New.
+
+2009-05-18 Richard Guenther <rguenther@suse.de>
+
+ PR fortran/40168
+ * gfortran.dg/array_memset_2.f90: Adjust.
+
+2009-05-18 Janus Weil <janus@gcc.gnu.org>
+
+ PR fortran/36947
+ PR fortran/40039
+ * gfortran.dg/interface_27.f90: New.
+ * gfortran.dg/interface_28.f90: New.
+ * gfortran.dg/proc_ptr_11.f90: Fixing invalid test case.
+ * gfortran.dg/proc_ptr_result_1.f90: Ditto.
+
+2009-05-18 Maxim Kuvyrkov <maxim@codesourcery.com>
+
+ * gcc.target/m68k/tls-ie.c: New test.
+ * gcc.target/m68k/tls-le.c: New test.
+ * gcc.target/m68k/tls-gd.c: New test.
+ * gcc.target/m68k/tls-ld.c: New test.
+ * gcc.target/m68k/tls-ie-xgot.c: New test.
+ * gcc.target/m68k/tls-le-xtls.c: New test.
+ * gcc.target/m68k/tls-gd-xgot.c: New test.
+ * gcc.target/m68k/tls-ld-xgot.c: New test.
+ * gcc.target/m68k/tls-ld-xtls.c: New test.
+ * gcc.target/m68k/tls-ld-xgot-xtls.c: New test.
+
+2009-05-18 Martin Jambor <mjambor@suse.cz>
+
+ * gcc.dg/ipa/modif-1.c: Do not check for unmodified int parameter.
+
+2009-05-17 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR c/40172
+ * gcc.dg/pr40172.c: New.
+
+2009-05-17 Jason Merrill <jason@redhat.com>
+
+ PR c++/40139
+ * g++.dg/template/dtor6.C: New.
+
+2009-05-17 Joseph Myers <joseph@codesourcery.com>
+
+ * g++.dg/warn/translate-ice-1.C: New test.
+
+2009-05-17 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ * gfortran.dg/c_kind_int128_test1.f03: Also test C_INT_FAST128_T.
+ * gfortran.dg/c_kind_int128_test2.f03: Update comment.
+ * gfortran.dg/c_kind_params.f90: Also test int_fast*_t.
+ * gfortran.dg/c_kinds.c: Add int_fast*_t arguments.
+
+2009-05-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/33197
+ * gfortran.dg/erf_2.F90: New test.
+ * gfortran.dg/erfc_scaled_2.f90: New test.
+
+2009-05-16 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR fortran/31243
+ * gcc/testsuite/gfortran.dg/string_1.f90: New test.
+ * gcc/testsuite/gfortran.dg/string_2.f90: New test.
+ * gcc/testsuite/gfortran.dg/string_3.f90: New test.
+
+2009-05-16 David Billinghurst <billingd@gcc.gnu.org>
+
+ * gfortran.dg/default_format_denormal_1.f90: XFAIL on cygwin.
+ * gfortran.dg/default_format_1.f90: Revert change of 2009-05-12
+
2009-05-15 Ian Lance Taylor <iant@google.com>
* gcc.dg/Wcxx-compat-10.c: New testcase.
@@ -68,15 +492,17 @@
2009-05-14 Laurent GUERBY <laurent@guerby.net>
- * ada/acats/tests/c3/c38202a.ada: Use Impdef.
- * ada/acats/tests/c5/c59002c.ada: Likewise.
+ * ada/acats/tests/c3/c38202a.ada: Use Impdef.
+ * ada/acats/tests/c5/c59002c.ada: Likewise.
2009-05-13 Taras Glek <tglek@mozilla.com>
- * g++.dg/plugin/attribute_plugin-test-1.C Testcase input for custom attributes and decl smashing
- * g++.dg/plugin/attribute_plugin.c Testcase plugin to test user attributes
- * g++.dg/plugin/dumb_plugin.c Fixed typo
- * g++.dg/plugin/plugin.exp Added attribute_plugin test
+ * g++.dg/plugin/attribute_plugin-test-1.C: Testcase input for custom
+ attributes and decl smashing.
+ * g++.dg/plugin/attribute_plugin.c: Testcase plugin to test user
+ attributes.
+ * g++.dg/plugin/dumb_plugin.c: Fixed typo.
+ * g++.dg/plugin/plugin.exp: Added attribute_plugin test .
2009-05-14 Jakub Jelinek <jakub@redhat.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/enum3.C b/gcc/testsuite/g++.dg/cpp0x/enum3.C
new file mode 100644
index 00000000000..5555ab2aac8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/enum3.C
@@ -0,0 +1,17 @@
+// PR c++/38064
+// { dg-options "-std=c++0x" }
+// { dg-do run }
+
+enum class E { elem };
+
+template <class T>
+void f (T t);
+
+bool f (bool b) { return b; }
+
+int main()
+{
+ E e = E::elem;
+ if (!f (e == E::elem))
+ return 1;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit1.C b/gcc/testsuite/g++.dg/cpp0x/explicit1.C
new file mode 100644
index 00000000000..fe164fc8cb1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit1.C
@@ -0,0 +1,58 @@
+// Test for explicit conversion ops from N2437.
+// { dg-options "-std=c++0x" }
+
+class U; class V;
+class T
+{
+public:
+ T( U const & );
+ //implicit converting ctor
+ explicit T( V const & );
+ // explicit ctor
+};
+class U
+{
+};
+class V
+{
+};
+class W
+{
+public:
+ operator T() const;
+};
+class X
+{
+public:
+ explicit operator T() const; // theoretical
+};
+int main()
+{
+ U u; V v; W w; X x;
+ // Direct initialization:
+ T t1( u );
+ T t2( v );
+ T t3( w );
+ T t4( x );
+ // Copy initialization:
+ T t5 = u;
+ T t6 = v; // { dg-error "" }
+ T t7 = w;
+ T t8 = x; // { dg-error "" }
+ // Cast notation:
+ T t9 = (T) u;
+ T t10 = (T) v;
+ T t11 = (T) w;
+ T t12 = (T) x;
+ // Static cast:
+ T t13 = static_cast<T>( u );
+ T t14 = static_cast<T>( v );
+ T t15 = static_cast<T>( w );
+ T t16 = static_cast<T>( x );
+ // Function-style cast:
+ T t17 = T( u );
+ T t18 = T( v );
+ T t19 = T( w );
+ T t20 = T( x );
+ return 0;
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/explicit2.C b/gcc/testsuite/g++.dg/cpp0x/explicit2.C
new file mode 100644
index 00000000000..c2327c140d8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/explicit2.C
@@ -0,0 +1,29 @@
+// Test for explicit conversion ops in various conversion situations.
+// { dg-options "-std=c++0x" }
+
+typedef void (*pfn)();
+
+struct A
+{
+ explicit operator int() const;
+ explicit operator pfn() const;
+};
+
+int main()
+{
+ A a;
+ int i = a; // { dg-error "" }
+ const int &ir = a; // { dg-error "" }
+ a(); // { dg-error "" }
+ a + 1; // { dg-message "" } (error and note on same line)
+
+ int j (a);
+ (int)a;
+ static_cast<int>(a);
+}
+
+struct B
+{
+ int i;
+ B(const A& a): i(a) { }
+};
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/debug/dwarf2/nested-1.C b/gcc/testsuite/g++.dg/debug/dwarf2/nested-1.C
new file mode 100644
index 00000000000..336582c112a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/nested-1.C
@@ -0,0 +1,29 @@
+// Contributed by Dodji Seketeli <dodji@redhat.com>
+// Origin PR debug/40109
+// { dg-do compile }
+// { dg-options "-g -dA -O0" }
+
+namespace A
+{
+
+ class B
+ {
+ };
+ typedef A::B AB;
+};
+
+int
+main()
+{
+ A::AB ab;
+ return 0;
+}
+
+// { dg-final { scan-assembler "DW_TAG_typedef" } }
+//
+// What we want to do here is to be sure that the DIE of A::AB is generated
+// as a child of the DIE of the namespace A declaration.
+// So this test won't catch a regression on this fix yet. To write a proper
+// test for this fix, we would need a dwarf reader written in tcl,
+// or something along those lines.
+
diff --git a/gcc/testsuite/g++.dg/ext/dllexport2.C b/gcc/testsuite/g++.dg/ext/dllexport2.C
new file mode 100644
index 00000000000..71ccf670b4b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/dllexport2.C
@@ -0,0 +1,52 @@
+// { dg-do link }
+// { dg-require-dll "" }
+// { dg-additional-sources "dllexport2a.cc" }
+// { dg-options "-O2" }
+
+/* Test that inline functions declared "dllexport" appear in object
+ files, even if they are not called.
+
+ This behavior is required by the ARM C++ ABI:
+
+ Exporting a function that can be inlined should force the
+ creation and export of an out-of-line copy of it.
+
+ and should presumably also apply.
+
+ Visual Studio 2005 also honors that rule. */
+
+__declspec(dllexport) inline void i1() {}
+
+__declspec(dllexport) extern inline void e1() {}
+
+/* It is invalid to declare the function inline after its definition. */
+#if 0
+__declspec(dllexport) void i2() {}
+inline void i2();
+
+__declspec(dllexport) extern void e2() {}
+inline void e2();
+#endif
+
+__declspec(dllexport) inline void i3() {}
+void i3();
+
+__declspec(dllexport) inline void e3() {}
+extern void e3();
+
+__declspec(dllexport) void i4();
+inline void i4() {};
+
+__declspec(dllexport) extern void e4();
+inline void e4() {};
+
+__declspec(dllexport) inline void i5();
+void i5() {};
+
+__declspec(dllexport) inline void e5();
+extern void e5() {};
+
+/* Make sure that just declaring the function -- without defining it
+ -- does not cause errors. */
+__declspec(dllexport) inline void i6();
+__declspec(dllexport) extern inline void e6();
diff --git a/gcc/testsuite/g++.dg/ext/dllexport2a.cc b/gcc/testsuite/g++.dg/ext/dllexport2a.cc
new file mode 100644
index 00000000000..80caf321742
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/dllexport2a.cc
@@ -0,0 +1,21 @@
+extern void i1();
+extern void i3();
+extern void i4();
+extern void i5();
+
+extern void e1();
+extern void e3();
+extern void e4();
+extern void e5();
+
+int main () {
+ i1();
+ i3();
+ i4();
+ i5();
+
+ e1();
+ e3();
+ e4();
+ e5();
+}
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/ext/vector16.C b/gcc/testsuite/g++.dg/ext/vector16.C
new file mode 100644
index 00000000000..7964a881f4a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/vector16.C
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+#define vector __attribute__((vector_size(4*sizeof(int)) ))
+
+vector int a, b, c;
+
+
+/* Test that remainder works for vectors. */
+void f(void)
+{
+ a = b % c;
+}
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 d071762102b..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 */
@@ -54,10 +54,10 @@ handle_pre_generic (void *event_data, void *data)
}
int
-plugin_init (const char *plugin_name,
- struct plugin_gcc_version *version,
- int argc, struct plugin_argument *argv)
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
{
+ const char *plugin_name = plugin_info->base_name;
register_callback (plugin_name, PLUGIN_CXX_CP_PRE_GENERICIZE,
handle_pre_generic, NULL);
diff --git a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
index 839dc2b1c8a..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. */
@@ -78,11 +78,13 @@ static struct gimple_opt_pass pass_dumb_plugin_example =
both of which determine where the plugin pass should be inserted. */
int
-plugin_init (const char *plugin_name,
- struct plugin_gcc_version *version __attribute__((unused)),
- int argc, struct plugin_argument *argv)
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
{
struct plugin_pass pass_info;
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
char *ref_pass_name = NULL;
int ref_instance_number = 0;
int i;
diff --git a/gcc/testsuite/g++.dg/plugin/selfassign.c b/gcc/testsuite/g++.dg/plugin/selfassign.c
index 6fbce83c01d..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
@@ -294,10 +294,13 @@ static struct gimple_opt_pass pass_warn_self_assign =
Note that this function needs to be named exactly "plugin_init". */
int
-plugin_init (const char *plugin_name, struct plugin_gcc_version *version,
- int argc, struct plugin_argument *argv)
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
{
struct plugin_pass pass_info;
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
bool enabled = true;
int i;
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/dtor6.C b/gcc/testsuite/g++.dg/template/dtor6.C
new file mode 100644
index 00000000000..c44b780294c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/dtor6.C
@@ -0,0 +1,16 @@
+// PR c++/40139
+
+template<int> struct A
+{
+ static int i;
+};
+
+template<int N> int A<N>::i = { A::~A }; // { dg-error "non-static member function" }
+
+template class A<0>;
+
+struct X { };
+
+int i1 = X::~X; // { dg-error "non-static member function" }
+int i2 = &X::~X; // { dg-error "address of destructor" }
+int i3 = &A<0>::~A; // { dg-error "address of destructor" }
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/Wstrict-aliasing-float-ref-int-obj.C b/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C
index d88ed4314b3..8b82874f51d 100644
--- a/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C
+++ b/gcc/testsuite/g++.dg/warn/Wstrict-aliasing-float-ref-int-obj.C
@@ -4,8 +4,8 @@
int foo() {
int x;
- float& q = reinterpret_cast<float&> (x); /* { dg-message "initialized" } */
- q = 1.0; /* { dg-warning "does break strict-aliasing" } */
+ float& q = reinterpret_cast<float&> (x); /* { dg-message "initialized" "" { xfail *-*-* } } */
+ q = 1.0; /* { dg-warning "does break strict-aliasing" "" { xfail *-*-* } } */
return x;
}
diff --git a/gcc/testsuite/g++.dg/warn/translate-ice-1.C b/gcc/testsuite/g++.dg/warn/translate-ice-1.C
new file mode 100644
index 00000000000..22e103c2980
--- /dev/null
+++ b/gcc/testsuite/g++.dg/warn/translate-ice-1.C
@@ -0,0 +1,45 @@
+// Test ICE in caching printable names for a function.
+// { dg-options "-std=c++98 -pedantic -O2" }
+
+void g (int a) __attribute__((warning("g")));
+void g2 (int a, int *p);
+static inline __attribute__((__always_inline__)) void
+gg (int a)
+{
+ if (a == 0)
+ return g(a); // { dg-warning "attribute" }
+ __extension__ int v[a];
+ return g2(a, v);
+}
+
+void h (int a) __attribute__((warning("h")));
+void h2 (int a, int *p);
+static inline __attribute__((__always_inline__)) void
+hh (int a)
+{
+ if (a == 0)
+ return h(a); // { dg-warning "attribute" }
+ __extension__ int v[a];
+ return h2(a, v);
+}
+
+void i (int a) __attribute__((warning("i")));
+void i2 (int a, int *p);
+static inline __attribute__((__always_inline__)) void
+ii (int a)
+{
+ if (a == 0)
+ return i(a); // { dg-warning "attribute" }
+ __extension__ int v[a];
+ return i2(a, v);
+}
+
+void
+f (void)
+{
+ long long l; // { dg-warning "long long" }
+ const char *p = __PRETTY_FUNCTION__;
+ gg(0);
+ hh(0);
+ ii(0);
+}
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/20090518-1.c b/gcc/testsuite/gcc.c-torture/compile/20090518-1.c
new file mode 100644
index 00000000000..709504c405a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20090518-1.c
@@ -0,0 +1,6 @@
+float
+foo(int i)
+{
+ int j = i == 42;
+ return *(float *)&j;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/20090519-1.c b/gcc/testsuite/gcc.c-torture/compile/20090519-1.c
new file mode 100644
index 00000000000..54add6b2e1a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20090519-1.c
@@ -0,0 +1,11 @@
+typedef struct { int licensed; } __pmPDUInfo;
+void __pmDecodeXtendError (int *);
+void do_handshake(void)
+{
+ __pmPDUInfo *pduinfo;
+ int challenge;
+ __pmDecodeXtendError(&challenge);
+ pduinfo = (__pmPDUInfo *)&challenge;
+ *pduinfo = *pduinfo;
+}
+
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/pr40204.c b/gcc/testsuite/gcc.c-torture/compile/pr40204.c
new file mode 100644
index 00000000000..3193284ff7a
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40204.c
@@ -0,0 +1,14 @@
+/* PR middle-end/40204 */
+
+struct S
+{
+ unsigned int a : 4;
+ unsigned int b : 28;
+} s;
+char c;
+
+void
+f (void)
+{
+ s.a = (c >> 4) & ~(1 << 4);
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/pr40233.c b/gcc/testsuite/gcc.c-torture/compile/pr40233.c
new file mode 100644
index 00000000000..b3487edde74
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/pr40233.c
@@ -0,0 +1,10 @@
+typedef int aligned __attribute__((aligned(64)));
+struct Frame {
+ aligned i;
+};
+
+void foo(struct Frame *p)
+{
+ aligned *q = &p->i;
+ *q = 0;
+}
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/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/Wstrict-aliasing-converted-assigned.c b/gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c
index 1fef7947c9b..b77373d56bd 100644
--- a/gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c
+++ b/gcc/testsuite/gcc.dg/Wstrict-aliasing-converted-assigned.c
@@ -9,5 +9,5 @@ int foo()
return i;
}
-/* { dg-message "does break strict-aliasing" "" { target { *-*-* && lp64 } } 8 } */
-/* { dg-message "initialized" "" { target { *-*-* && lp64 } } 8 } */
+/* { dg-message "does break strict-aliasing" "" { target { *-*-* && lp64 } xfail *-*-* } 8 } */
+/* { dg-message "initialized" "" { target { *-*-* && lp64 } xfail *-*-* } 8 } */
diff --git a/gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c b/gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c
index fccc178d224..b90fb76c28b 100644
--- a/gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c
+++ b/gcc/testsuite/gcc.dg/Wstrict-aliasing-float-ptr-int-obj.c
@@ -11,12 +11,12 @@ int foo() {
float* r;
if (flag) {
- q = (float*) &x; /* { dg-message "initialized" } */
+ q = (float*) &x; /* { dg-message "initialized" "" { xfail *-*-* } } */
} else {
- q = (float*) &y; /* { dg-message "initialized" } */
+ q = (float*) &y; /* { dg-message "initialized" "" { xfail *-*-* } } */
}
- *q = 1.0; /* { dg-warning "does break strict-aliasing" } */
+ *q = 1.0; /* { dg-warning "does break strict-aliasing" "" { xfail *-*-* } } */
return x;
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/dll-6.c b/gcc/testsuite/gcc.dg/dll-6.c
new file mode 100644
index 00000000000..7907f40d1bd
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dll-6.c
@@ -0,0 +1,52 @@
+/* { dg-do link } */
+/* { dg-require-dll "" } */
+/* { dg-additional-sources "dll-6a.c" } */
+/* { dg-options "-w -O2 -std=gnu89" } */
+
+/* Test that inline functions declared "dllexport" appear in object
+ files, even if they are not called.
+
+ This behavior is required by the ARM C++ ABI:
+
+ Exporting a function that can be inlined should force the
+ creation and export of an out-of-line copy of it.
+
+ and should presumably also apply.
+
+ Visual Studio 2005 also honors that rule. */
+
+__declspec(dllexport) inline void i1() {}
+
+__declspec(dllexport) extern inline void e1() {}
+
+/* It is invalid to declare the function inline after its definition. */
+#if 0
+__declspec(dllexport) void i2() {}
+inline void i2();
+
+__declspec(dllexport) extern void e2() {}
+inline void e2();
+#endif
+
+__declspec(dllexport) inline void i3() {}
+void i3();
+
+__declspec(dllexport) inline void e3() {}
+extern void e3();
+
+__declspec(dllexport) void i4();
+inline void i4() {};
+
+__declspec(dllexport) extern void e4();
+inline void e4() {};
+
+__declspec(dllexport) inline void i5();
+void i5() {};
+
+__declspec(dllexport) inline void e5();
+extern void e5() {};
+
+/* Make sure that just declaring the function -- without defining it
+ -- does not cause errors. */
+__declspec(dllexport) inline void i6();
+__declspec(dllexport) extern inline void e6();
diff --git a/gcc/testsuite/gcc.dg/dll-6a.c b/gcc/testsuite/gcc.dg/dll-6a.c
new file mode 100644
index 00000000000..80caf321742
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dll-6a.c
@@ -0,0 +1,21 @@
+extern void i1();
+extern void i3();
+extern void i4();
+extern void i5();
+
+extern void e1();
+extern void e3();
+extern void e4();
+extern void e5();
+
+int main () {
+ i1();
+ i3();
+ i4();
+ i5();
+
+ e1();
+ e3();
+ e4();
+ e5();
+}
diff --git a/gcc/testsuite/gcc.dg/dll-7.c b/gcc/testsuite/gcc.dg/dll-7.c
new file mode 100644
index 00000000000..c3a5957ae6b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dll-7.c
@@ -0,0 +1,52 @@
+/* { dg-do link } */
+/* { dg-require-dll "" } */
+/* { dg-additional-sources "dll-7a.c" } */
+/* { dg-options "-w -O2 -std=gnu99" } */
+
+/* Test that inline functions declared "dllexport" appear in object
+ files, even if they are not called.
+
+ This behavior is required by the ARM C++ ABI:
+
+ Exporting a function that can be inlined should force the
+ creation and export of an out-of-line copy of it.
+
+ and should presumably also apply.
+
+ Visual Studio 2005 also honors that rule. */
+
+__declspec(dllexport) inline void i1() {}
+
+__declspec(dllexport) extern inline void e1() {}
+
+/* It is invalid to declare the function inline after its definition. */
+#if 0
+__declspec(dllexport) void i2() {}
+inline void i2();
+
+__declspec(dllexport) extern void e2() {}
+inline void e2();
+#endif
+
+__declspec(dllexport) inline void i3() {}
+void i3();
+
+__declspec(dllexport) inline void e3() {}
+extern void e3();
+
+__declspec(dllexport) void i4();
+inline void i4() {};
+
+__declspec(dllexport) extern void e4();
+inline void e4() {};
+
+__declspec(dllexport) inline void i5();
+void i5() {};
+
+__declspec(dllexport) inline void e5();
+extern void e5() {};
+
+/* Make sure that just declaring the function -- without defining it
+ -- does not cause errors. */
+__declspec(dllexport) inline void i6();
+__declspec(dllexport) extern inline void e6();
diff --git a/gcc/testsuite/gcc.dg/dll-7a.c b/gcc/testsuite/gcc.dg/dll-7a.c
new file mode 100644
index 00000000000..80caf321742
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/dll-7a.c
@@ -0,0 +1,21 @@
+extern void i1();
+extern void i3();
+extern void i4();
+extern void i5();
+
+extern void e1();
+extern void e3();
+extern void e4();
+extern void e5();
+
+int main () {
+ i1();
+ i3();
+ i4();
+ i5();
+
+ e1();
+ e3();
+ e4();
+ e5();
+}
diff --git a/gcc/testsuite/gcc.dg/falign-labels-1.c b/gcc/testsuite/gcc.dg/falign-labels-1.c
new file mode 100644
index 00000000000..1e9661790e3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/falign-labels-1.c
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+/* { dg-options "-falign-labels=8" { target { ! { m68k*-*-* || fido*-*-* } } } } */
+
+/* On ARMv7-A CPUs, this test resulted in incorrect code generation.
+ The code generated for the switch statement expected the jump table
+ to immediately follow the jump instruction, but -falign-labels
+ caused the label preceding the table to be aligned. */
+/* M68K and fido only support -falign-labels argument <= 2. */
+
+volatile int x;
+
+int main(void)
+{
+ int y;
+
+ x = 0;
+
+ switch(x)
+ {
+ case 0:
+ y = 2 * x;
+ break;
+ case 1:
+ y = -3 * x;
+ break;
+ case 2:
+ y = x + 5;
+ break;
+ case 3:
+ y = x - 7;
+ break;
+ default:
+ break;
+ }
+
+ x = y;
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/ipa/modif-1.c b/gcc/testsuite/gcc.dg/ipa/modif-1.c
index bc1706c5650..db6915a9d9e 100644
--- a/gcc/testsuite/gcc.dg/ipa/modif-1.c
+++ b/gcc/testsuite/gcc.dg/ipa/modif-1.c
@@ -15,12 +15,11 @@ void func4 (int *pi);
void the_test (struct whatever u, struct whatever v,
struct whatever w, struct whatever x,
- int i, int j, int k, int l)
+ int i, int k, int l)
{
struct whatever *pw = &w;
int *pk = &k;
- j = l+3;
v.first = 9;
func1 (u);
@@ -28,7 +27,6 @@ void the_test (struct whatever u, struct whatever v,
func2 (pw);
func2 (&x);
func3 (i);
- func3 (j);
func4 (pk);
func4 (&l);
}
@@ -40,5 +38,4 @@ void the_test (struct whatever u, struct whatever v,
/* { dg-final { scan-ipa-dump-not "param 4\[^\\n\]*modified" "inline" } } */
/* { dg-final { scan-ipa-dump "param 5\[^\\n\]*modified" "inline" } } */
/* { dg-final { scan-ipa-dump "param 6\[^\\n\]*modified" "inline" } } */
-/* { dg-final { scan-ipa-dump "param 7\[^\\n\]*modified" "inline" } } */
/* { dg-final { cleanup-ipa-dump "inline" } } */
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..136404ae65f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/plugin/ggcplug.c
@@ -0,0 +1,109 @@
+/* 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"
+
+
+/* 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". */
+
+
+/* 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
+};
+
+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;
+ 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);
+ }
+ }
+}
+
+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 6fbce83c01d..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
@@ -294,10 +294,13 @@ static struct gimple_opt_pass pass_warn_self_assign =
Note that this function needs to be named exactly "plugin_init". */
int
-plugin_init (const char *plugin_name, struct plugin_gcc_version *version,
- int argc, struct plugin_argument *argv)
+plugin_init (struct plugin_name_args *plugin_info,
+ struct plugin_gcc_version *version)
{
struct plugin_pass pass_info;
+ const char *plugin_name = plugin_info->base_name;
+ int argc = plugin_info->argc;
+ struct plugin_argument *argv = plugin_info->argv;
bool enabled = true;
int i;
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/pr40172-1.c b/gcc/testsuite/gcc.dg/pr40172-1.c
new file mode 100644
index 00000000000..a834a8a998e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40172-1.c
@@ -0,0 +1,31 @@
+/* PR middle-end/40172 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -W -Werror -Wlogical-op" } */
+
+struct rtx_def;
+typedef struct rtx_def *rtx;
+
+extern int foo;
+extern int bar;
+extern int xxx;
+
+int
+test (void)
+{
+ if (((rtx) 0 != (rtx) 0) && xxx ? foo : bar)
+ return 1;
+ else if ((foo & 0) && xxx)
+ return 2;
+ else if (foo & 0)
+ return 3;
+ else if (0 && xxx)
+ return 4;
+ else if (0)
+ return 5;
+ if (((int) 0 != (int) 0) && bar ? foo : xxx)
+ return 6;
+ else if (0 != 0 && foo ? xxx : bar)
+ return 7;
+ else
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr40172-2.c b/gcc/testsuite/gcc.dg/pr40172-2.c
new file mode 100644
index 00000000000..17aabb8b5f3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40172-2.c
@@ -0,0 +1,16 @@
+/* PR middle-end/40172 */
+/* { dg-do compile } */
+/* { dg-options "-Wall -W -Werror" } */
+
+extern int xxx;
+
+#define XXX xxx
+
+int
+test (void)
+{
+ if (!XXX && xxx)
+ return 4;
+ else
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr40172-3.c b/gcc/testsuite/gcc.dg/pr40172-3.c
new file mode 100644
index 00000000000..ea74fce37c6
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr40172-3.c
@@ -0,0 +1,17 @@
+/* PR middle-end/40172 */
+/* { dg-do compile */
+/* { dg-xfail-if "" { "*-*-*" } { "*" } { "" } } */
+/* { dg-options "-Wall -W -Werror -Wlogical-op" } */
+
+extern int xxx;
+
+#define XXX xxx
+
+int
+test (void)
+{
+ if (!XXX && xxx)
+ return 4;
+ else
+ return 0;
+}
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/simd-1b.c b/gcc/testsuite/gcc.dg/simd-1b.c
index 56d94b91c68..1e2b597b565 100644
--- a/gcc/testsuite/gcc.dg/simd-1b.c
+++ b/gcc/testsuite/gcc.dg/simd-1b.c
@@ -14,7 +14,7 @@ void
hanneke ()
{
/* Operators on compatible SIMD types. */
- a %= b; /* { dg-error "invalid operands to binary %" } */
+ a %= b;
c &= d;
a |= b;
c ^= d;
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/pr40087.c b/gcc/testsuite/gcc.dg/tree-ssa/pr40087.c
new file mode 100644
index 00000000000..22e2b629ed7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr40087.c
@@ -0,0 +1,30 @@
+/* { dg-do run } */
+/* { dg-options "-O1 " } */
+
+extern void abort (void);
+
+static void __attribute__((always_inline))
+reverse(int *first, int *last)
+{
+ if (first == last--)
+ return;
+ while (first != last)
+ {
+ int t = *first;
+ *first = *last;
+ *last = t;
+ if (++first == last--)
+ break;
+ }
+}
+
+int main()
+{
+ int seq[] = { 1, 2, 3, 4, 5, 6, 7, 8 };
+
+ reverse(seq, seq + 8);
+ if (seq[3] != 5 || seq[4] != 4)
+ abort ();
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-2.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-2.c
index ec30bc904d7..177c4bcace4 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 -fdump-tree-optimized --param sra-max-structure-size=32" } */
+/* { dg-options "-O1 -fno-tree-fre -fdump-tree-optimized --param sra-max-structure-size=32" } */
/* Test for SRA. */
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-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-14.c
index 24b58ee941a..81b82fe4880 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-14.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-14.c
@@ -8,6 +8,7 @@ struct Foo
void *data;
double size;
};
+void bar(double *);
void foo(double (*q)[4])
{
struct Foo tmp1;
@@ -23,6 +24,7 @@ void foo(double (*q)[4])
this store to tmp1 here. */
tmp1.size -= 1.0;
}
+ bar(a);
}
/* { dg-final { scan-tree-dump "Inserted .* &a" "fre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-15.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-15.c
index a557f27f319..d24cd1e4c38 100644
--- a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-15.c
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-15.c
@@ -8,6 +8,7 @@ struct Foo
void *data;
double size;
};
+void bar(double *);
void foo(double (*q)[4])
{
struct Foo tmp1;
@@ -22,6 +23,7 @@ void foo(double (*q)[4])
this store to tmp1 here. */
tmp1.size -= 1.0;
}
+ bar(a);
}
/* { dg-final { scan-tree-dump "Replaced" "fre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-24.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-24.c
new file mode 100644
index 00000000000..705993a4fb3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-24.c
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre" } */
+
+int foo(void)
+{
+ int a[16] = {};
+ return a[3];
+}
+
+int bar(void)
+{
+ int a[16];
+ __builtin_memset (a, 0, sizeof(a));
+ return a[3];
+}
+
+struct X { int i; };
+int baz(void)
+{
+ struct X a,b;
+ a.i = 0;
+ b = a;
+ return b.i;
+}
+
+int bazzoo (void)
+{
+ struct X b, a = {};
+ b = a;
+ return b.i;
+}
+
+/* { dg-final { scan-tree-dump-times "= 0;" 5 "fre" } } */
+/* { dg-final { cleanup-tree-dump "fre" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-25.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-25.c
new file mode 100644
index 00000000000..f7f99bf74f5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-25.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre" } */
+
+struct X { int i; int j; };
+void bar (struct X *);
+int foo (struct X *p)
+{
+ struct X x;
+ p->i = 1;
+ x = *p;
+ x.j = 2;
+ return p->i - x.i;
+}
+
+/* We should optimize this to return 0. */
+
+/* { dg-final { scan-tree-dump "= 0;" "fre" } } */
+/* { dg-final { cleanup-tree-dump "fre" } } */
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/vect/bb-slp-1.c b/gcc/testsuite/gcc.dg/vect/bb-slp-1.c
new file mode 100644
index 00000000000..57e5665247d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-1.c
@@ -0,0 +1,62 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 32
+
+unsigned int out[N*8];
+unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
+
+__attribute__ ((noinline)) int
+main1 (int dummy)
+{
+ int i;
+ unsigned int *pin = &in[0];
+ unsigned int *pout = &out[0];
+
+ for (i = 0; i < N; i++)
+ {
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ /* Avoid loop vectorization. */
+ if (dummy == 32)
+ abort ();
+ }
+
+ /* check results: */
+ for (i = 0; i < N; i++)
+ {
+ if (out[i*8] != in[i*8]
+ || out[i*8 + 1] != in[i*8 + 1]
+ || out[i*8 + 2] != in[i*8 + 2]
+ || out[i*8 + 3] != in[i*8 + 3]
+ || out[i*8 + 4] != in[i*8 + 4]
+ || out[i*8 + 5] != in[i*8 + 5]
+ || out[i*8 + 6] != in[i*8 + 6]
+ || out[i*8 + 7] != in[i*8 + 7])
+ abort ();
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (33);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-10.c b/gcc/testsuite/gcc.dg/vect/bb-slp-10.c
new file mode 100644
index 00000000000..abac3c31a40
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-10.c
@@ -0,0 +1,53 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int *pin = &in[0];
+ unsigned int *pout = &out[2];
+ unsigned int a0, a1, a2, a3;
+
+ /* Misaligned store. */
+ a0 = *pin++ + 23;
+ a1 = *pin++ + 142;
+ a2 = *pin++ + 2;
+ a3 = *pin++ + 31;
+
+ *pout++ = a0 * x;
+ *pout++ = a1 * y;
+ *pout++ = a2 * x;
+ *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)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 0 "slp" } } */
+/* { dg-final { scan-tree-dump-times "unsupported alignment in basic block." 1 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-11.c b/gcc/testsuite/gcc.dg/vect/bb-slp-11.c
new file mode 100644
index 00000000000..456f9618139
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-11.c
@@ -0,0 +1,52 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int *pin = &in[0];
+ unsigned int *pout = &out[0];
+ short a0, a1, a2, a3;
+
+ a0 = *pin++ + 23;
+ a1 = *pin++ + 142;
+ a2 = *pin++ + 2;
+ a3 = *pin++ + 31;
+
+ *pout++ = a0 * x;
+ *pout++ = a1 * y;
+ *pout++ = a2 * x;
+ *pout++ = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[2] + 2) * x
+ || out[3] != (in[3] + 31) * y)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 0 "slp" } } */
+/* { dg-final { scan-tree-dump-times "SLP with multiple types" 1 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-13.c b/gcc/testsuite/gcc.dg/vect/bb-slp-13.c
new file mode 100644
index 00000000000..5005ae5019f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-13.c
@@ -0,0 +1,49 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int a0, a1, a2, a3;
+
+ a0 = in[0] + 23;
+ a1 = in[1] + 142;
+ a2 = in[2] + 2;
+ a3 = in[3] + 31;
+
+ out[0] = a0 * x;
+ out[1] = a1 * y;
+ out[2] = a2 * x;
+ out[3] = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[2] + 2) * x
+ || out[3] != (in[3] + 31) * y)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target vect_int_mult } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-14.c b/gcc/testsuite/gcc.dg/vect/bb-slp-14.c
new file mode 100644
index 00000000000..673a163c92f
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-14.c
@@ -0,0 +1,50 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int a0, a1, a2, a3;
+
+ /* Not consecutive load with permutation - not supported. */
+ a0 = in[0] + 23;
+ a1 = in[1] + 142;
+ a2 = in[1] + 2;
+ a3 = in[3] + 31;
+
+ out[0] = a0 * x;
+ out[1] = a1 * y;
+ out[2] = a2 * x;
+ out[3] = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[1] + 2) * x
+ || out[3] != (in[3] + 31) * y)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 0 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-15.c b/gcc/testsuite/gcc.dg/vect/bb-slp-15.c
new file mode 100644
index 00000000000..ba8bc757e86
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-15.c
@@ -0,0 +1,54 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int a0, a1, a2, a3;
+
+ if (x > y)
+ x = x + y;
+ else
+ y = x;
+
+ a0 = in[0] + 23;
+ a1 = in[1] + 142;
+ a2 = in[2] + 2;
+ a3 = in[3] + 31;
+
+ out[0] = a0 * x;
+ out[1] = a1 * y;
+ out[2] = a2 * x;
+ out[3] = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[2] + 2) * x
+ || out[3] != (in[3] + 31) * y)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target vect_int_mult } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-16.c b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c
new file mode 100644
index 00000000000..16cd7a18d67
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-16.c
@@ -0,0 +1,71 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 32
+
+unsigned int out[N*8];
+unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63, 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
+unsigned int arr[N] = {0,1,2,3,4,5,6,7};
+
+__attribute__ ((noinline)) int
+main1 (int dummy)
+{
+ int i;
+ unsigned int *pin = &in[0];
+ unsigned int *pout = &out[0];
+ unsigned int a = 0;
+
+ for (i = 0; i < N; i++)
+ {
+ *pout++ = *pin++ + a;
+ *pout++ = *pin++ + a;
+ *pout++ = *pin++ + a;
+ *pout++ = *pin++ + a;
+ *pout++ = *pin++ + a;
+ *pout++ = *pin++ + a;
+ *pout++ = *pin++ + a;
+ *pout++ = *pin++ + a;
+ if (arr[i] = i)
+ a = i;
+ else
+ a = 2;
+ }
+
+ a = 0;
+ /* check results: */
+ for (i = 0; i < N; i++)
+ {
+ if (out[i*8] != in[i*8] + a
+ || out[i*8 + 1] != in[i*8 + 1] + a
+ || out[i*8 + 2] != in[i*8 + 2] + a
+ || out[i*8 + 3] != in[i*8 + 3] + a
+ || out[i*8 + 4] != in[i*8 + 4] + a
+ || out[i*8 + 5] != in[i*8 + 5] + a
+ || out[i*8 + 6] != in[i*8 + 6] + a
+ || out[i*8 + 7] != in[i*8 + 7] + a)
+ abort ();
+
+ if (arr[i] = i)
+ a = i;
+ else
+ a = 2;
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (33);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-17.c b/gcc/testsuite/gcc.dg/vect/bb-slp-17.c
new file mode 100644
index 00000000000..36227391d2e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-17.c
@@ -0,0 +1,60 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int b[N];
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int a0, a1, a2, a3;
+
+ if (x > y)
+ x = x + y;
+ else
+ y = x;
+
+ a0 = in[0] + 23;
+ a1 = in[1] + 142;
+ a2 = in[2] + 2;
+ a3 = in[3] + 31;
+
+ b[0] = a0;
+ b[1] = a1;
+
+ out[0] = a0 * x;
+ out[1] = a1 * y;
+ out[2] = a2 * x;
+ out[3] = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[2] + 2) * x
+ || out[3] != (in[3] + 31) * y
+ || b[0] != in[0] + 23
+ || b[1] != in[1] + 142)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target vect_int_mult } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-18.c b/gcc/testsuite/gcc.dg/vect/bb-slp-18.c
new file mode 100644
index 00000000000..ab99f822aff
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-18.c
@@ -0,0 +1,49 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int a0, a1, a2, a3;
+
+ a0 = in[0] + 23;
+ a1 = in[1] + 142;
+ a2 = in[2] + 2;
+ a3 = in[3] + 31;
+
+ out[0] = a0 * x;
+ out[1] = a1 * y;
+ out[2] = a2 * x;
+ out[3] = a3 * y;
+
+ /* Check results. */
+ if (out[0] != a0 * x
+ || out[1] != a1 * y
+ || out[2] != a2 * x
+ || out[3] != a3 * y)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target vect_int_mult } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-19.c b/gcc/testsuite/gcc.dg/vect/bb-slp-19.c
new file mode 100644
index 00000000000..5ee83a1945e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-19.c
@@ -0,0 +1,56 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned short out[N];
+unsigned short in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 ()
+{
+ int i;
+ unsigned short *pin = &in[0];
+ unsigned short *pout = &out[0];
+
+ /* A group of 9 shorts - unsupported for now. */
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *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[4] != in[4]
+ || out[5] != in[5]
+ || out[6] != in[6]
+ || out[7] != in[7]
+ || out[8] != in[8])
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { xfail *-*-* } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-2.c b/gcc/testsuite/gcc.dg/vect/bb-slp-2.c
new file mode 100644
index 00000000000..1de31986829
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-2.c
@@ -0,0 +1,59 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N*8];
+unsigned int in[N*8] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63};
+
+__attribute__ ((noinline)) int
+main1 (int dummy)
+{
+ int i;
+ unsigned int *pin = &in[0];
+ unsigned int *pout = &out[0];
+
+ for (i = 0; i < N*2; i++)
+ {
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+
+ /* Avoid loop vectorization. */
+ if (dummy == 32)
+ abort ();
+ }
+
+ /* check results: */
+ for (i = 0; i < N; i++)
+ {
+ if (out[i*8] != in[i*8]
+ || out[i*8 + 1] != in[i*8 + 1]
+ || out[i*8 + 2] != in[i*8 + 2]
+ || out[i*8 + 3] != in[i*8 + 3]
+ || out[i*8 + 4] != in[i*8 + 4]
+ || out[i*8 + 5] != in[i*8 + 5]
+ || out[i*8 + 6] != in[i*8 + 6]
+ || out[i*8 + 7] != in[i*8 + 7])
+ abort ();
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (33);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-20.c b/gcc/testsuite/gcc.dg/vect/bb-slp-20.c
new file mode 100644
index 00000000000..a40a629d1e7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-20.c
@@ -0,0 +1,68 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+int b[N];
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int a0, a1, a2, a3;
+
+ if (x > y)
+ x = x + y;
+ else
+ y = x;
+
+ /* Two SLP instances in the basic block, only one is supported for now,
+ the second one contains type conversion. */
+ a0 = in[0] + 23;
+ a1 = in[1] + 142;
+ a2 = in[2] + 2;
+ a3 = in[3] + 31;
+
+ b[0] = -a0;
+ b[1] = -a1;
+ b[2] = -a2;
+ b[3] = -a3;
+
+ out[0] = a0 * x;
+ out[1] = a1 * y;
+ out[2] = a2 * x;
+ out[3] = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[2] + 2) * x
+ || out[3] != (in[3] + 31) * y
+ || b[0] != -(in[0] + 23)
+ || b[1] != -(in[1] + 142)
+ || b[2] != -(in[2] + 2)
+ || b[3] != -(in[3] + 31))
+
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target vect_int_mult } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "slp" { target vect_int_mult } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-21.c b/gcc/testsuite/gcc.dg/vect/bb-slp-21.c
new file mode 100644
index 00000000000..f0b4f6b1ac8
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-21.c
@@ -0,0 +1,68 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int b[N];
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int a0, a1, a2, a3;
+
+ /* Two SLP instances in one basic block. */
+ if (x > y)
+ x = x + y;
+ else
+ y = x;
+
+ a0 = in[0] + 23;
+ a1 = in[1] + 142;
+ a2 = in[2] + 2;
+ a3 = in[3] + 31;
+
+ b[0] = a0;
+ b[1] = a1;
+ b[2] = a2;
+ b[3] = a3;
+
+ out[0] = a0 * x;
+ out[1] = a1 * y;
+ out[2] = a2 * x;
+ out[3] = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[2] + 2) * x
+ || out[3] != (in[3] + 31) * y
+ || b[0] != (in[0] + 23)
+ || b[1] != (in[1] + 142)
+ || b[2] != (in[2] + 2)
+ || b[3] != (in[3] + 31))
+
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 1 "slp" { target { ! {vect_int_mult } } } } } */
+/* { dg-final { scan-tree-dump-times "vectorizing stmts using SLP" 2 "slp" { target vect_int_mult } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-22.c b/gcc/testsuite/gcc.dg/vect/bb-slp-22.c
new file mode 100644
index 00000000000..3e6e685f118
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-22.c
@@ -0,0 +1,67 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int b[N];
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int a0, a1, a2, a3;
+
+ a0 = in[0] + 23;
+ a1 = in[1] + 142;
+ a2 = in[2] + 2;
+ a3 = in[3] + 31;
+
+ if (x > y)
+ {
+ b[0] = a0;
+ b[1] = a1;
+ b[2] = a2;
+ b[3] = a3;
+ }
+ else
+ {
+ out[0] = a0 * x;
+ out[1] = a1 * y;
+ out[2] = a2 * x;
+ out[3] = a3 * y;
+ }
+
+ /* Check results. */
+ if ((x <= y
+ && (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[2] + 2) * x
+ || out[3] != (in[3] + 31) * y))
+ || (x > y
+ && (b[0] != (in[0] + 23)
+ || b[1] != (in[1] + 142)
+ || b[2] != (in[2] + 2)
+ || b[3] != (in[3] + 31))))
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target { ! {vect_int_mult } } } } } */
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 2 "slp" { target vect_int_mult } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-3.c b/gcc/testsuite/gcc.dg/vect/bb-slp-3.c
new file mode 100644
index 00000000000..07ad7129ad7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-3.c
@@ -0,0 +1,45 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 ()
+{
+ int i;
+ unsigned int *pin = &in[0];
+ unsigned int *pout = &out[0];
+
+ *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])
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-4.c b/gcc/testsuite/gcc.dg/vect/bb-slp-4.c
new file mode 100644
index 00000000000..3e74fff29b5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-4.c
@@ -0,0 +1,45 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned short out[N];
+unsigned short in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 ()
+{
+ int i;
+ unsigned short *pin = &in[0];
+ unsigned short *pout = &out[0];
+
+ *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])
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 0 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-5.c b/gcc/testsuite/gcc.dg/vect/bb-slp-5.c
new file mode 100644
index 00000000000..0775d998c8d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-5.c
@@ -0,0 +1,53 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned short out[N];
+unsigned short in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 ()
+{
+ int i;
+ unsigned short *pin = &in[0];
+ unsigned short *pout = &out[0];
+
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *pout++ = *pin++;
+ *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[4] != in[4]
+ || out[5] != in[5]
+ || out[6] != in[6]
+ || out[7] != in[7])
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 ();
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-6.c b/gcc/testsuite/gcc.dg/vect/bb-slp-6.c
new file mode 100644
index 00000000000..d351691c2fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-6.c
@@ -0,0 +1,51 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int *pin = &in[0];
+ unsigned int *pout = &out[0];
+ unsigned int a0, a1, a2, a3;
+
+ a0 = *pin++ + 23;
+ a1 = *pin++ + 142;
+ a2 = *pin++ + 2;
+ a3 = *pin++ + 31;
+
+ *pout++ = a0 * x;
+ *pout++ = a1 * y;
+ *pout++ = a2 * x;
+ *pout++ = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[2] + 2) * x
+ || out[3] != (in[3] + 31) * y)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target vect_int_mult } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-7.c b/gcc/testsuite/gcc.dg/vect/bb-slp-7.c
new file mode 100644
index 00000000000..e3fac8d5dbe
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-7.c
@@ -0,0 +1,52 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int *pin = &in[0];
+ unsigned int *pout = &out[0];
+ unsigned int a0, a1, a2, a3;
+
+ /* Non isomorphic. */
+ a0 = *pin++ + 23;
+ a1 = *pin++ + 142;
+ a2 = *pin++ + 2;
+ a3 = *pin++ * 31;
+
+ *pout++ = a0 * x;
+ *pout++ = a1 * y;
+ *pout++ = a2 * x;
+ *pout++ = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[2] + 2) * x
+ || out[3] != (in[3] * 31) * y)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 0 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-8.c b/gcc/testsuite/gcc.dg/vect/bb-slp-8.c
new file mode 100644
index 00000000000..b0c1be77a3e
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-8.c
@@ -0,0 +1,50 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y, unsigned int *pin, unsigned int *pout)
+{
+ int i;
+ unsigned int a0, a1, a2, a3;
+
+ /* pin and pout may alias. */
+ a0 = *pin++ + 23;
+ a1 = *pin++ + 142;
+ a2 = *pin++ + 2;
+ a3 = *pin++ + 31;
+
+ *pout++ = a0 * x;
+ *pout++ = a1 * y;
+ *pout++ = a2 * x;
+ *pout++ = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[0] + 23) * x
+ || out[1] != (in[1] + 142) * y
+ || out[2] != (in[2] + 2) * x
+ || out[3] != (in[3] + 31) * y)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3, &in[0], &out[0]);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 0 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/bb-slp-9.c b/gcc/testsuite/gcc.dg/vect/bb-slp-9.c
new file mode 100644
index 00000000000..e8fe1507365
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/bb-slp-9.c
@@ -0,0 +1,53 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int *pin = &in[1];
+ unsigned int *pout = &out[0];
+ unsigned int a0, a1, a2, a3;
+
+ /* Misaligned load. */
+ a0 = *pin++ + 23;
+ a1 = *pin++ + 142;
+ a2 = *pin++ + 2;
+ a3 = *pin++ + 31;
+
+ *pout++ = a0 * x;
+ *pout++ = a1 * y;
+ *pout++ = a2 * x;
+ *pout++ = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in[1] + 23) * x
+ || out[1] != (in[2] + 142) * y
+ || out[2] != (in[3] + 2) * x
+ || out[3] != (in[4] + 31) * y)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 0 "slp" } } */
+/* { dg-final { scan-tree-dump-times "unsupported alignment in basic block." 1 "slp" } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/no-tree-reassoc-bb-slp-12.c b/gcc/testsuite/gcc.dg/vect/no-tree-reassoc-bb-slp-12.c
new file mode 100644
index 00000000000..d0b2ed4fff7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/no-tree-reassoc-bb-slp-12.c
@@ -0,0 +1,53 @@
+/* { dg-require-effective-target vect_int } */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include "tree-vect.h"
+
+#define N 16
+
+unsigned int out[N];
+unsigned int in1[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
+unsigned int in2[N] = {10,11,12,13,14,15,16,17,18,19,110,111,112,113,114,115};
+
+__attribute__ ((noinline)) int
+main1 (unsigned int x, unsigned int y)
+{
+ int i;
+ unsigned int *pin1 = &in1[0];
+ unsigned int *pin2 = &in2[0];
+ unsigned int *pout = &out[0];
+ unsigned int a0, a1, a2, a3;
+
+ a0 = *pin2++ - *pin1++ + 23;
+ a1 = *pin2++ - *pin1++ + 142;
+ a2 = *pin2++ - *pin1++ + 2;
+ a3 = *pin2++ - *pin1++ + 31;
+
+ *pout++ = a0 * x;
+ *pout++ = a1 * y;
+ *pout++ = a2 * x;
+ *pout++ = a3 * y;
+
+ /* Check results. */
+ if (out[0] != (in2[0] - in1[0] + 23) * x
+ || out[1] != (in2[1] - in1[1] + 142) * y
+ || out[2] != (in2[2] - in1[2] + 2) * x
+ || out[3] != (in2[3] - in1[3] + 31) * y)
+ abort();
+
+ return 0;
+}
+
+int main (void)
+{
+ check_vect ();
+
+ main1 (2, 3);
+
+ return 0;
+}
+
+/* { dg-final { scan-tree-dump-times "basic block vectorized using SLP" 1 "slp" { target vect_int_mult } } } */
+/* { dg-final { cleanup-tree-dump "slp" } } */
+
diff --git a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c
index 13fbc82a42f..65e36fe8015 100644
--- a/gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c
+++ b/gcc/testsuite/gcc.dg/vect/no-vfa-vect-43.c
@@ -22,41 +22,53 @@ void bar (float *pa, float *pb, float *pc)
__attribute__ ((noinline)) int
-main1 (float *pa)
+main1 (float *pa, float *pb, float *pc)
{
int i;
- float pb[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
- float pc[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+ float b[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+ float c[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+
+ for (i = 0; i < N; i++)
+ {
+ b[i] = pb[i];
+ c[i] = pc[i];
+ }
/* Vectorizable: pa may not alias pb and/or pc, even though their
addresses escape. &pa would need to escape to point to escaped memory. */
for (i = 0; i < N; i++)
{
- pa[i] = pb[i] * pc[i];
+ pa[i] = b[i] * c[i];
}
- bar (pa,pb,pc);
+ bar (pa,b,c);
return 0;
}
__attribute__ ((noinline)) int
-main2 (float * pa)
+main2 (float *pa, float *pb, float *pc)
{
int i;
- float pb[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
- float pc[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+ float b[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+ float c[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+
+ for (i = 0; i < N; i++)
+ {
+ b[i] = pb[i];
+ c[i] = pc[i];
+ }
/* Vectorizable: pb and pc addresses do not escape. */
for (i = 0; i < N; i++)
{
- pa[i] = pb[i] * pc[i];
+ pa[i] = b[i] * c[i];
}
/* check results: */
for (i = 0; i < N; i++)
{
- if (pa[i] != (pb[i] * pc[i]))
+ if (pa[i] != (b[i] * c[i]))
abort ();
}
@@ -67,14 +79,16 @@ int main (void)
{
int i;
float a[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+ float b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
+ float c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
check_vect ();
- main1 (a);
- main2 (a);
+ main1 (a,b,c);
+ main2 (a,b,c);
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 2 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 2 "vect" } } */
/* { dg-final { scan-tree-dump-times "Alignment of access forced using versioning" 2 "vect" { target vect_no_align } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/pr40238.c b/gcc/testsuite/gcc.dg/vect/pr40238.c
new file mode 100644
index 00000000000..91cf0982439
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vect/pr40238.c
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+
+extern int xdo_rb_ctr_row( int *pos_code);
+
+int xgp_ahd_interpolate (int tile)
+{
+ int p[4];
+
+ switch (tile) {
+ default:
+ case 0:
+ case 1:
+ p[0] = 0; p[1] = 1; p[2] = 2; p[3] = 3;
+ break;
+ case 2:
+ case 3:
+ p[0] = 1; p[1] = 0; p[2] = 3; p[3] = 2;
+ break;
+ case 4:
+ case 5:
+ p[0] = 3; p[1] = 2; p[2] = 1; p[3] = 0;
+ break;
+ case 6:
+ case 7:
+ p[0] = 2; p[1] = 3; p[2] = 0; p[3] = 1;
+ break;
+ }
+
+ xdo_rb_ctr_row(p);
+ xdo_rb_ctr_row(p);
+ return 0;
+}
+
+/* { dg-final { cleanup-tree-dump "vect" } } */
+
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.dg/vect/vect-40.c b/gcc/testsuite/gcc.dg/vect/vect-40.c
index a73d1551643..d2c17d1d97d 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-40.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-40.c
@@ -26,13 +26,16 @@ void bar (float *pa, float *pb, float *pc)
vect-46.c is similar to this one with one difference:
the loop bound is unknown. */
+float b[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)))
+ = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
+float c[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)))
+ = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+
__attribute__ ((noinline)) int
main1 ()
{
int i;
float a[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
- float b[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
- float c[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
float *pa = a;
float *pb = b;
float *pc = c;
diff --git a/gcc/testsuite/gcc.dg/vect/vect-42.c b/gcc/testsuite/gcc.dg/vect/vect-42.c
index f1764e13ecf..29688638603 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-42.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-42.c
@@ -27,15 +27,22 @@ void bar (float *pa, float *pb, float *pc)
No aliasing problems. */
__attribute__ ((noinline)) int
-main1 (float * __restrict__ pa)
+main1 (float * __restrict__ pa, float *pb, float *pc)
{
+ float b[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
+ float c[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
int i;
- float pb[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
- float pc[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+ /* We also vectorize this loop. */
for (i = 0; i < N; i++)
{
- pa[i] = pb[i] * pc[i];
+ b[i] = pb[i];
+ c[i] = pc[i];
+ }
+
+ for (i = 0; i < N; i++)
+ {
+ pa[i] = b[i] * c[i];
}
return 0;
@@ -45,18 +52,18 @@ int main (void)
{
int i;
float a[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
- float b[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
- float c[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+ float b[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
+ float c[N] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
check_vect ();
- main1 (a);
+ main1 (a,b,c);
bar (a,b,c);
return 0;
}
-/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" } } */
+/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" } } */
/* { dg-final { scan-tree-dump-times "Alignment of access forced using versioning" 1 "vect" { target { vect_no_align || { ! vector_alignment_reachable } } } } } */
-/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 2 "vect" { xfail { vect_no_align || { ! vector_alignment_reachable } } } } } */
+/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 4 "vect" { xfail { vect_no_align || { ! vector_alignment_reachable } } } } } */
/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 1 "vect" { xfail {vect_no_align || { ! vector_alignment_reachable } } } } } */
/* { dg-final { cleanup-tree-dump "vect" } } */
diff --git a/gcc/testsuite/gcc.dg/vect/vect-46.c b/gcc/testsuite/gcc.dg/vect/vect-46.c
index 2588a7b291e..d506d4329c0 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-46.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-46.c
@@ -26,11 +26,16 @@ void bar (float *pa, float *pb, float *pc)
vect-40.c is similar to this one with one difference:
the loop bound is known. */
+float b[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)))
+ = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57};
+float c[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)))
+ = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+
__attribute__ ((noinline)) int
main1 (int n)
{
int i;
- float a[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))); float b[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45,48,51,54,57}; float c[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+ float a[N] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__)));
float *pa = a;
float *pb = b;
float *pc = c;
diff --git a/gcc/testsuite/gcc.dg/vect/vect-76.c b/gcc/testsuite/gcc.dg/vect/vect-76.c
index 7097e7a821e..d7713024224 100644
--- a/gcc/testsuite/gcc.dg/vect/vect-76.c
+++ b/gcc/testsuite/gcc.dg/vect/vect-76.c
@@ -11,13 +11,13 @@
more involved than just an ssa_name. */
int ib[N+OFF] __attribute__ ((__aligned__(__BIGGEST_ALIGNMENT__))) = {0, 1, 3, 5, 7, 11, 13, 17, 0, 2, 6, 10};
+int ic[N+OFF] = {0, 1, 3, 5, 7, 11, 13, 17, 0, 2, 6, 10};
__attribute__ ((noinline))
int main1 (int *pib)
{
int i;
int ia[N+OFF];
- int ic[N+OFF] = {0, 1, 3, 5, 7, 11, 13, 17, 0, 2, 6, 10};
for (i = OFF; i < N; i++)
{
diff --git a/gcc/testsuite/gcc.dg/vect/vect.exp b/gcc/testsuite/gcc.dg/vect/vect.exp
index d9c47f6c1c0..42435eb3130 100644
--- a/gcc/testsuite/gcc.dg/vect/vect.exp
+++ b/gcc/testsuite/gcc.dg/vect/vect.exp
@@ -122,6 +122,8 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/nodump-*.\[cS\]]] \
"" $DEFAULT_VECTCFLAGS
lappend DEFAULT_VECTCFLAGS "-fdump-tree-vect-details"
+set VECT_SLP_CFLAGS $DEFAULT_VECTCFLAGS
+lappend VECT_SLP_CFLAGS "-fdump-tree-slp-details"
# Main loop.
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/pr*.\[cS\]]] \
@@ -130,10 +132,14 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/vect-*.\[cS\]]] \
"" $DEFAULT_VECTCFLAGS
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/slp-*.\[cS\]]] \
"" $DEFAULT_VECTCFLAGS
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/bb-slp*.\[cS\]]] \
+ "" $VECT_SLP_CFLAGS
+
#### Tests with special options
global SAVED_DEFAULT_VECTCFLAGS
set SAVED_DEFAULT_VECTCFLAGS $DEFAULT_VECTCFLAGS
+set SAVED_VECT_SLP_CFLAGS $VECT_SLP_CFLAGS
# --param vect-max-version-for-alias-checks=0 tests
set DEFAULT_VECTCFLAGS $SAVED_DEFAULT_VECTCFLAGS
@@ -262,6 +268,11 @@ dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/O3-*.\[cS\]]] \
dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/O1-*.\[cS\]]] \
"" $O1_VECTCFLAGS
+# -fno-tree-reassoc
+set VECT_SLP_CFLAGS $SAVED_VECT_SLP_CFLAGS
+lappend VECT_SLP_CFLAGS "-fno-tree-reassoc"
+dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/no-tree-reassoc-bb-slp-*.\[cS\]]] \
+ "" $VECT_SLP_CFLAGS
# Clean up.
set dg-do-what-default ${save-dg-do-what-default}
diff --git a/gcc/testsuite/gcc.dg/vector-4.c b/gcc/testsuite/gcc.dg/vector-4.c
new file mode 100644
index 00000000000..7964a881f4a
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/vector-4.c
@@ -0,0 +1,11 @@
+/* { dg-do compile } */
+#define vector __attribute__((vector_size(4*sizeof(int)) ))
+
+vector int a, b, c;
+
+
+/* Test that remainder works for vectors. */
+void f(void)
+{
+ a = b % c;
+}
diff --git a/gcc/testsuite/gcc.target/arm/neon-vmla-1.c b/gcc/testsuite/gcc.target/arm/neon-vmla-1.c
new file mode 100644
index 00000000000..3592ab979ac
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/neon-vmla-1.c
@@ -0,0 +1,10 @@
+/* { dg-require-effective-target arm_neon_hw } */
+/* { dg-options "-O2 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize" } */
+/* { dg-final { scan-assembler "vmla\\.f32" } } */
+
+/* Verify that VMLA is used. */
+void f1(int n, float a, float x[], float y[]) {
+ int i;
+ for (i = 0; i < n; ++i)
+ y[i] = a * x[i] + y[i];
+}
diff --git a/gcc/testsuite/gcc.target/arm/neon-vmls-1.c b/gcc/testsuite/gcc.target/arm/neon-vmls-1.c
new file mode 100644
index 00000000000..1b3fcbbbbc9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/neon-vmls-1.c
@@ -0,0 +1,10 @@
+/* { dg-require-effective-target arm_neon_hw } */
+/* { dg-options "-O2 -mfpu=neon -mfloat-abi=softfp -ftree-vectorize" } */
+/* { dg-final { scan-assembler "vmls\\.f32" } } */
+
+/* Verify that VMLS is used. */
+void f1(int n, float a, float x[], float y[]) {
+ int i;
+ for (i = 0; i < n; ++i)
+ y[i] = y[i] - a * x[i];
+}
diff --git a/gcc/testsuite/gcc.target/arm/thumb2-mul-space-2.c b/gcc/testsuite/gcc.target/arm/thumb2-mul-space-2.c
new file mode 100644
index 00000000000..b53df2fa12a
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb2-mul-space-2.c
@@ -0,0 +1,15 @@
+/* In Thumb-2 mode, when optimizing for size, generate a "muls"
+ instruction and use the resulting condition flags rather than a
+ separate compare instruction. */
+/* { dg-options "-mthumb -Os" } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-final { scan-assembler "muls" } } */
+/* { dg-final { scan-assembler-not "cmp" } } */
+
+int x;
+
+void f(int i, int j)
+{
+ if (i * j < 0)
+ x = 1;
+}
diff --git a/gcc/testsuite/gcc.target/arm/thumb2-mul-space-3.c b/gcc/testsuite/gcc.target/arm/thumb2-mul-space-3.c
new file mode 100644
index 00000000000..143a6deee79
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb2-mul-space-3.c
@@ -0,0 +1,17 @@
+/* In Thumb-2 mode, when optimizing for size, generate a "muls"
+ instruction and use the resulting condition flags rather than a
+ separate compare instruction. */
+/* { dg-options "-mthumb -Os" } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-final { scan-assembler "muls" } } */
+/* { dg-final { scan-assembler-not "cmp" } } */
+
+int x;
+
+int f(int i, int j)
+{
+ i = i * j;
+ if (i < 0)
+ x = 1;
+ return i;
+}
diff --git a/gcc/testsuite/gcc.target/arm/thumb2-mul-space.c b/gcc/testsuite/gcc.target/arm/thumb2-mul-space.c
new file mode 100644
index 00000000000..8cf0cb40f41
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb2-mul-space.c
@@ -0,0 +1,10 @@
+/* Use 16-bit multiply instruction in Thumb-2 mode when optimizing for
+ size. */
+/* { dg-options "-mthumb -Os" } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-final { scan-assembler "muls" } } */
+
+int f(int i, int j)
+{
+ return i * j;
+}
diff --git a/gcc/testsuite/gcc.target/arm/thumb2-mul-speed.c b/gcc/testsuite/gcc.target/arm/thumb2-mul-speed.c
new file mode 100644
index 00000000000..03cccdb654b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/arm/thumb2-mul-speed.c
@@ -0,0 +1,27 @@
+/* Do not use 16-bit multiply instructions in Thumb-2 mode when
+ optimizing for speed. */
+/* { dg-options "-mthumb -O2" } */
+/* { dg-require-effective-target arm_thumb2_ok } */
+/* { dg-final { scan-assembler-not "muls" } } */
+
+int f(int i, int j)
+{
+ return i * j;
+}
+
+int x;
+
+void g(int i, int j)
+{
+ if (i * j < 0)
+ x = 1;
+}
+
+int h(int i, int j)
+{
+ i = i * j;
+ if (i < 0)
+ x = 1;
+ return i;
+}
+
diff --git a/gcc/testsuite/gcc.target/i386/movbe-1.c b/gcc/testsuite/gcc.target/i386/movbe-1.c
new file mode 100644
index 00000000000..391d4ad9814
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/movbe-1.c
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mmovbe" } */
+
+extern int x;
+
+void
+foo (int i)
+{
+ x = __builtin_bswap32 (i);
+}
+
+int
+bar ()
+{
+ return __builtin_bswap32 (x);
+}
+
+/* { dg-final { scan-assembler-times "movbe\[ \t\]" 2 } } */
diff --git a/gcc/testsuite/gcc.target/i386/movbe-2.c b/gcc/testsuite/gcc.target/i386/movbe-2.c
new file mode 100644
index 00000000000..d898f20dce4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/movbe-2.c
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mmovbe" } */
+
+extern long long x;
+
+void
+foo (long long i)
+{
+ x = __builtin_bswap64 (i);
+}
+
+long long
+bar ()
+{
+ return __builtin_bswap64 (x);
+}
+
+/* { dg-final { scan-assembler-times "movbe\[ \t\]" 4 { target ilp32 } } } */
+/* { dg-final { scan-assembler-times "movbe\[ \t\]" 2 { target lp64 } } } */
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/ia64/mfused-madd-vect.c b/gcc/testsuite/gcc.target/ia64/mfused-madd-vect.c
new file mode 100644
index 00000000000..e166e85daed
--- /dev/null
+++ b/gcc/testsuite/gcc.target/ia64/mfused-madd-vect.c
@@ -0,0 +1,33 @@
+/* { dg-do compile */
+/* { dg-options "-O2 -ftree-vectorize" } */
+/* { dg-final { scan-assembler-not "fpmpy" } } */
+
+/* fpma and fpms will show in either way because there are no
+ specific vector add/sub instructions. So we just check for fpmpy. */
+
+#define N 16
+extern bar(float *, float *, float *, float *);
+void foo()
+{
+ int i;
+ float a[N], b[N], c[N], d[N];
+ bar(a,b,c,d);
+ for (i = 0; i < N; i++) {
+ a[i] = b[i] + c[i] * d[i];
+ }
+ bar(a,b,c,d);
+#if 0
+ for (i = 0; i < N; i++) {
+ a[i] = b[i] - c[i] * d[i];
+ }
+ bar(a,b,c,d);
+#endif
+ for (i = 0; i < N; i++) {
+ a[i] = b[i] * c[i] + d[i];
+ }
+ bar(a,b,c,d);
+ for (i = 0; i < N; i++) {
+ a[i] = b[i] * c[i] - d[i];
+ }
+ bar(a,b,c,d);
+}
diff --git a/gcc/testsuite/gcc.target/ia64/mfused-madd.c b/gcc/testsuite/gcc.target/ia64/mfused-madd.c
new file mode 100644
index 00000000000..8ecb31f0dd3
--- /dev/null
+++ b/gcc/testsuite/gcc.target/ia64/mfused-madd.c
@@ -0,0 +1,64 @@
+/* { dg-do compile */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "fmpy" } } */
+/* { dg-final { scan-assembler-not "fadd" } } */
+/* { dg-final { scan-assembler-not "fsub" } } */
+/* { dg-final { scan-assembler "fma" } } */
+/* { dg-final { scan-assembler "fms" } } */
+/* { dg-final { scan-assembler "fnma" } } */
+
+float foo01(float a, float b, float c) {return (a + b * c);}
+float foo02(float a, float b, float c) {return (a - b * c);}
+float foo03(float a, float b, float c) {return (a * b + c);}
+float foo04(float a, float b, float c) {return (a * b - c);}
+
+double foo05(double a, double b, double c) {return (a + b * c);}
+double foo06(double a, double b, double c) {return (a - b * c);}
+double foo07(double a, double b, double c) {return (a * b + c);}
+double foo08(double a, double b, double c) {return (a * b - c);}
+
+__float80 foo09(__float80 a, __float80 b, __float80 c) {return (a + b * c);}
+__float80 foo10(__float80 a, __float80 b, __float80 c) {return (a - b * c);}
+__float80 foo11(__float80 a, __float80 b, __float80 c) {return (a * b + c);}
+__float80 foo12(__float80 a, __float80 b, __float80 c) {return (a * b - c);}
+
+
+
+float foo20(double a, double b, double c) {return (float) (a + b * c);}
+float foo21(double a, double b, double c) {return (float) (a - b * c);}
+float foo22(double a, double b, double c) {return (float) (a * b + c);}
+float foo23(double a, double b, double c) {return (float) (a * b - c);}
+
+float foo24(__float80 a, __float80 b, __float80 c) {return (float) (a + b * c);}
+float foo25(__float80 a, __float80 b, __float80 c) {return (float) (a - b * c);}
+float foo26(__float80 a, __float80 b, __float80 c) {return (float) (a * b + c);}
+float foo27(__float80 a, __float80 b, __float80 c) {return (float) (a * b - c);}
+
+double foo28(__float80 a, __float80 b, __float80 c) {return (double) (a + b * c);}
+double foo29(__float80 a, __float80 b, __float80 c) {return (double) (a - b * c);}
+double foo30(__float80 a, __float80 b, __float80 c) {return (double) (a * b + c);}
+double foo31(__float80 a, __float80 b, __float80 c) {return (double) (a * b - c);}
+
+
+float foo001(float a, float b, double c) { return (a + b * c); }
+float foo002(float a, float b, double c) { return (a - b * c); }
+
+float foo005(float a, double b, double c) { return (a + b * c); }
+float foo006(float a, double b, double c) { return (a - b * c); }
+float foo007(float a, double b, double c) { return (a * b + c); }
+float foo008(float a, double b, double c) { return (a * b - c); }
+
+double foo009(double a, float b, double c) { return (a + b * c); }
+double foo010(double a, float b, double c) { return (a - b * c); }
+double foo011(double a, float b, double c) { return (a * b + c); }
+double foo012(double a, float b, double c) { return (a * b - c); }
+
+float foo013(float a, double b, __float80 c) { return (a + b * c); }
+float foo014(float a, double b, __float80 c) { return (a - b * c); }
+float foo017(double a, float b, __float80 c) { return (a + b * c); }
+float foo018(double a, float b, __float80 c) { return (a - b * c); }
+
+float foo021(float a, __float80 b, double c) { return (a + b * c); }
+float foo022(float a, __float80 b, double c) { return (a - b * c); }
+float foo023(float a, __float80 b, double c) { return (a * b + c); }
+float foo024(float a, __float80 b, double c) { return (a * b - c); }
diff --git a/gcc/testsuite/gcc.target/ia64/mno-fused-madd-vect.c b/gcc/testsuite/gcc.target/ia64/mno-fused-madd-vect.c
new file mode 100644
index 00000000000..0e24bf6cda8
--- /dev/null
+++ b/gcc/testsuite/gcc.target/ia64/mno-fused-madd-vect.c
@@ -0,0 +1,31 @@
+/* { dg-do compile */
+/* { dg-options "-O2 -mno-fused-madd -ftree-vectorize" } */
+/* { dg-final { scan-assembler "fpmpy" } } */
+
+/* fpma and fpms will show in either way because there are no
+ specific vector add/sub instructions. So we just check for fpmpy. */
+
+#define N 16
+extern bar(float *, float *, float *, float *);
+void foo()
+{
+ int i;
+ float a[N], b[N], c[N], d[N];
+ bar(a,b,c,d);
+ for (i = 0; i < N; i++) {
+ a[i] = b[i] + c[i] * d[i];
+ }
+ bar(a,b,c,d);
+ for (i = 0; i < N; i++) {
+ a[i] = b[i] - c[i] * d[i];
+ }
+ bar(a,b,c,d);
+ for (i = 0; i < N; i++) {
+ a[i] = b[i] * c[i] + d[i];
+ }
+ bar(a,b,c,d);
+ for (i = 0; i < N; i++) {
+ a[i] = b[i] * c[i] - d[i];
+ }
+ bar(a,b,c,d);
+}
diff --git a/gcc/testsuite/gcc.target/ia64/mno-fused-madd.c b/gcc/testsuite/gcc.target/ia64/mno-fused-madd.c
new file mode 100644
index 00000000000..d8ccc947681
--- /dev/null
+++ b/gcc/testsuite/gcc.target/ia64/mno-fused-madd.c
@@ -0,0 +1,64 @@
+/* { dg-do compile */
+/* { dg-options "-O2 -mno-fused-madd" } */
+/* { dg-final { scan-assembler-not "fma" } } */
+/* { dg-final { scan-assembler-not "fms" } } */
+/* { dg-final { scan-assembler-not "fnma" } } */
+/* { dg-final { scan-assembler "fmpy" } } */
+/* { dg-final { scan-assembler "fadd" } } */
+/* { dg-final { scan-assembler "fsub" } } */
+
+float foo01(float a, float b, float c) {return (a + b * c);}
+float foo02(float a, float b, float c) {return (a - b * c);}
+float foo03(float a, float b, float c) {return (a * b + c);}
+float foo04(float a, float b, float c) {return (a * b - c);}
+
+double foo05(double a, double b, double c) {return (a + b * c);}
+double foo06(double a, double b, double c) {return (a - b * c);}
+double foo07(double a, double b, double c) {return (a * b + c);}
+double foo08(double a, double b, double c) {return (a * b - c);}
+
+__float80 foo09(__float80 a, __float80 b, __float80 c) {return (a + b * c);}
+__float80 foo10(__float80 a, __float80 b, __float80 c) {return (a - b * c);}
+__float80 foo11(__float80 a, __float80 b, __float80 c) {return (a * b + c);}
+__float80 foo12(__float80 a, __float80 b, __float80 c) {return (a * b - c);}
+
+
+
+float foo20(double a, double b, double c) {return (float) (a + b * c);}
+float foo21(double a, double b, double c) {return (float) (a - b * c);}
+float foo22(double a, double b, double c) {return (float) (a * b + c);}
+float foo23(double a, double b, double c) {return (float) (a * b - c);}
+
+float foo24(__float80 a, __float80 b, __float80 c) {return (float) (a + b * c);}
+float foo25(__float80 a, __float80 b, __float80 c) {return (float) (a - b * c);}
+float foo26(__float80 a, __float80 b, __float80 c) {return (float) (a * b + c);}
+float foo27(__float80 a, __float80 b, __float80 c) {return (float) (a * b - c);}
+
+double foo28(__float80 a, __float80 b, __float80 c) {return (double) (a + b * c);}
+double foo29(__float80 a, __float80 b, __float80 c) {return (double) (a - b * c);}
+double foo30(__float80 a, __float80 b, __float80 c) {return (double) (a * b + c);}
+double foo31(__float80 a, __float80 b, __float80 c) {return (double) (a * b - c);}
+
+
+float foo001(float a, float b, double c) { return (a + b * c); }
+float foo002(float a, float b, double c) { return (a - b * c); }
+
+float foo005(float a, double b, double c) { return (a + b * c); }
+float foo006(float a, double b, double c) { return (a - b * c); }
+float foo007(float a, double b, double c) { return (a * b + c); }
+float foo008(float a, double b, double c) { return (a * b - c); }
+
+double foo009(double a, float b, double c) { return (a + b * c); }
+double foo010(double a, float b, double c) { return (a - b * c); }
+double foo011(double a, float b, double c) { return (a * b + c); }
+double foo012(double a, float b, double c) { return (a * b - c); }
+
+float foo013(float a, double b, __float80 c) { return (a + b * c); }
+float foo014(float a, double b, __float80 c) { return (a - b * c); }
+float foo017(double a, float b, __float80 c) { return (a + b * c); }
+float foo018(double a, float b, __float80 c) { return (a - b * c); }
+
+float foo021(float a, __float80 b, double c) { return (a + b * c); }
+float foo022(float a, __float80 b, double c) { return (a - b * c); }
+float foo023(float a, __float80 b, double c) { return (a * b + c); }
+float foo024(float a, __float80 b, double c) { return (a * b - c); }
diff --git a/gcc/testsuite/gcc.target/m68k/tls-gd-xgot.c b/gcc/testsuite/gcc.target/m68k/tls-gd-xgot.c
new file mode 100644
index 00000000000..2a4900b5a08
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-gd-xgot.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } { "*" } { "" } } */
+/* { dg-options "-O2 -fpic -mxgot" } */
+/* { dg-final { scan-assembler "#foo@TLSGD,\%\[ad\]\[0-7\]" } } */
+/* { dg-final { scan-assembler "bsr.l __tls_get_addr@PLTPC" } } */
+
+extern int __thread foo;
+
+int *
+bar (void)
+{
+ return &foo;
+}
diff --git a/gcc/testsuite/gcc.target/m68k/tls-gd.c b/gcc/testsuite/gcc.target/m68k/tls-gd.c
new file mode 100644
index 00000000000..2b69fbdc1b4
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-gd.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } { "*" } { "" } } */
+/* { dg-options "-O2 -fpic" } */
+/* { dg-final { scan-assembler "foo@TLSGD\\(\%a5\\)" } } */
+/* { dg-final { scan-assembler "bsr.l __tls_get_addr@PLTPC" } } */
+
+extern int __thread foo;
+
+int *
+bar (void)
+{
+ return &foo;
+}
diff --git a/gcc/testsuite/gcc.target/m68k/tls-ie-xgot.c b/gcc/testsuite/gcc.target/m68k/tls-ie-xgot.c
new file mode 100644
index 00000000000..d3fbfdaa4b6
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-ie-xgot.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } { "*" } { "" } } */
+/* { dg-options "-O2 -mxgot" } */
+/* { dg-final { scan-assembler "jsr __m68k_read_tp" } } */
+/* { dg-final { scan-assembler "#foo@TLSIE,\%\[ad\]\[0-7\]" } } */
+
+extern int __thread foo;
+
+int *
+bar (void)
+{
+ return &foo;
+}
diff --git a/gcc/testsuite/gcc.target/m68k/tls-ie.c b/gcc/testsuite/gcc.target/m68k/tls-ie.c
new file mode 100644
index 00000000000..2661f9fc053
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-ie.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } { "*" } { "" } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "jsr __m68k_read_tp" } } */
+/* { dg-final { scan-assembler "foo@TLSIE\\(\%a5\\)" } } */
+
+extern int __thread foo;
+
+int *
+bar (void)
+{
+ return &foo;
+}
diff --git a/gcc/testsuite/gcc.target/m68k/tls-ld-xgot-xtls.c b/gcc/testsuite/gcc.target/m68k/tls-ld-xgot-xtls.c
new file mode 100644
index 00000000000..4817de01d44
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-ld-xgot-xtls.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } { "*" } { "" } } */
+/* { dg-options "-O2 -fpic -mxgot -mxtls" } */
+/* { dg-final { scan-assembler "#foo@TLSLDM,\%\[ad\]\[0-7\]" } } */
+/* { dg-final { scan-assembler "bsr.l __tls_get_addr@PLTPC" } } */
+/* { dg-final { scan-assembler "#foo@TLSLDO,\%\[ad\]\[0-7\]" } } */
+
+static int __thread foo;
+
+int *
+bar (void)
+{
+ return &foo;
+}
diff --git a/gcc/testsuite/gcc.target/m68k/tls-ld-xgot.c b/gcc/testsuite/gcc.target/m68k/tls-ld-xgot.c
new file mode 100644
index 00000000000..f95f7192855
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-ld-xgot.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } { "*" } { "" } } */
+/* { dg-options "-O2 -fpic -mxgot" } */
+/* { dg-final { scan-assembler "#foo@TLSLDM,\%\[ad\]\[0-7\]" } } */
+/* { dg-final { scan-assembler "bsr.l __tls_get_addr@PLTPC" } } */
+/* { dg-final { scan-assembler "lea \\(foo@TLSLDO,\%a0\\)" } } */
+
+static int __thread foo;
+
+int *
+bar (void)
+{
+ return &foo;
+}
diff --git a/gcc/testsuite/gcc.target/m68k/tls-ld-xtls.c b/gcc/testsuite/gcc.target/m68k/tls-ld-xtls.c
new file mode 100644
index 00000000000..1bc3eaf7de5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-ld-xtls.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } { "*" } { "" } } */
+/* { dg-options "-O2 -fpic -mxtls" } */
+/* { dg-final { scan-assembler "foo@TLSLDM\\(\%a5\\)" } } */
+/* { dg-final { scan-assembler "bsr.l __tls_get_addr@PLTPC" } } */
+/* { dg-final { scan-assembler "#foo@TLSLDO,\%\[ad\]\[0-7\]" } } */
+
+static int __thread foo;
+
+int *
+bar (void)
+{
+ return &foo;
+}
diff --git a/gcc/testsuite/gcc.target/m68k/tls-ld.c b/gcc/testsuite/gcc.target/m68k/tls-ld.c
new file mode 100644
index 00000000000..556a11718ca
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-ld.c
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } { "*" } { "" } } */
+/* { dg-options "-O2 -fpic" } */
+/* { dg-final { scan-assembler "foo@TLSLDM\\(\%a5\\)" } } */
+/* { dg-final { scan-assembler "bsr.l __tls_get_addr@PLTPC" } } */
+/* { dg-final { scan-assembler "lea \\(foo@TLSLDO,\%a0\\)" } } */
+
+static int __thread foo;
+
+int *
+bar (void)
+{
+ return &foo;
+}
diff --git a/gcc/testsuite/gcc.target/m68k/tls-le-xtls.c b/gcc/testsuite/gcc.target/m68k/tls-le-xtls.c
new file mode 100644
index 00000000000..90061153f89
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-le-xtls.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } { "*" } { "" } } */
+/* { dg-options "-O2 -mxtls" } */
+/* { dg-final { scan-assembler "jsr __m68k_read_tp" } } */
+/* { dg-final { scan-assembler "#foo@TLSLE,\%\[ad\]\[0-7\]" } } */
+
+static int __thread foo;
+
+int *
+bar (void)
+{
+ return &foo;
+}
diff --git a/gcc/testsuite/gcc.target/m68k/tls-le.c b/gcc/testsuite/gcc.target/m68k/tls-le.c
new file mode 100644
index 00000000000..1c0eab23886
--- /dev/null
+++ b/gcc/testsuite/gcc.target/m68k/tls-le.c
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-skip-if "" { ! *-linux-* } { "*" } { "" } } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler "jsr __m68k_read_tp" } } */
+/* { dg-final { scan-assembler "lea \\(foo@TLSLE,\%a0\\)" } } */
+
+static int __thread foo;
+
+int *
+bar (void)
+{
+ return &foo;
+}
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/mips/extend-1.c b/gcc/testsuite/gcc.target/mips/extend-1.c
new file mode 100644
index 00000000000..952d4a0932c
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/extend-1.c
@@ -0,0 +1,14 @@
+/* { dg-options "-O -mgp64 isa=!octeon" } */
+/* { dg-final { scan-assembler-times "\tdsll\t" 5 } } */
+/* { dg-final { scan-assembler-times "\tdsra\t" 5 } } */
+/* { dg-final { scan-assembler-not "\tsll\t" } } */
+
+#define TEST_CHAR(T, N) \
+ NOMIPS16 T f##N (long long d, T *a, T *r) { T b = (char) d; *r = b + *a; }
+#define TEST_SHORT(T, N) \
+ NOMIPS16 T g##N (long long d, T *a, T *r) { T b = (short) d; *r = b + *a; }
+#define TEST(T, N) TEST_CHAR (T, N) TEST_SHORT (T, N)
+
+TEST (int, 1);
+TEST (long long, 2);
+TEST_CHAR (short, 3);
diff --git a/gcc/testsuite/gcc.target/mips/octeon-exts-2.c b/gcc/testsuite/gcc.target/mips/octeon-exts-2.c
index fc5df639d02..42f2a3f8586 100644
--- a/gcc/testsuite/gcc.target/mips/octeon-exts-2.c
+++ b/gcc/testsuite/gcc.target/mips/octeon-exts-2.c
@@ -1,6 +1,7 @@
/* { dg-do compile } */
-/* { dg-options "-O -march=octeon -meb" } */
-/* { dg-final { scan-assembler-times "\texts\t" 4 } } */
+/* { dg-options "-O -march=octeon -meb -dp" } */
+/* Don't match exts in sign-extension. */
+/* { dg-final { scan-assembler-times "\texts\t\[^\\n\]*extv" 4 } } */
struct bar
{
diff --git a/gcc/testsuite/gcc.target/mips/octeon-exts-5.c b/gcc/testsuite/gcc.target/mips/octeon-exts-5.c
index e7a4738b96f..6ec7ac7296f 100644
--- a/gcc/testsuite/gcc.target/mips/octeon-exts-5.c
+++ b/gcc/testsuite/gcc.target/mips/octeon-exts-5.c
@@ -1,7 +1,8 @@
/* -mel version of octeon-exts-2.c. */
/* { dg-do compile } */
-/* { dg-options "-O -march=octeon -mel" } */
-/* { dg-final { scan-assembler-times "\texts\t" 4 } } */
+/* { dg-options "-O -march=octeon -mel -dp" } */
+/* Don't match exts in sign-extension. */
+/* { dg-final { scan-assembler-times "\texts\t\[^\\n\]*extv" 4 } } */
struct bar
{
diff --git a/gcc/testsuite/gcc.target/mips/octeon-exts-6.c b/gcc/testsuite/gcc.target/mips/octeon-exts-6.c
new file mode 100644
index 00000000000..d04e27331d9
--- /dev/null
+++ b/gcc/testsuite/gcc.target/mips/octeon-exts-6.c
@@ -0,0 +1,14 @@
+/* { dg-options "-O -march=octeon -mgp64" } */
+/* { dg-final { scan-assembler-times "\texts\t" 5 } } */
+/* { dg-final { scan-assembler-not "\t(dsll|dsra)\t" } } */
+/* { dg-final { scan-assembler-not "\tsll\t" } } */
+
+#define TEST_CHAR(T, N) \
+ NOMIPS16 T f##N (long long d, T *a, T *r) { T b = (char) d; *r = b + *a; }
+#define TEST_SHORT(T, N) \
+ NOMIPS16 T g##N (long long d, T *a, T *r) { T b = (short) d; *r = b + *a; }
+#define TEST(T, N) TEST_CHAR (T, N) TEST_SHORT (T, N)
+
+TEST (int, 1);
+TEST (long long, 2);
+TEST_CHAR (short, 3);
diff --git a/gcc/testsuite/gcc.target/x86_64/abi/asm-support.S b/gcc/testsuite/gcc.target/x86_64/abi/asm-support.S
index 61b66e1490a..cb1e31ea785 100644
--- a/gcc/testsuite/gcc.target/x86_64/abi/asm-support.S
+++ b/gcc/testsuite/gcc.target/x86_64/abi/asm-support.S
@@ -49,7 +49,9 @@ snapshot:
.type snapshot_ret, @function
snapshot_ret:
movq %rdi, rdi(%rip)
+ subq $8, %rsp
call *callthis(%rip)
+ addq $8, %rsp
movq %rax, rax(%rip)
movq %rdx, rdx(%rip)
movdqu %xmm0, xmm_regs+0(%rip)
diff --git a/gcc/testsuite/gfortran.dg/array_memset_2.f90 b/gcc/testsuite/gfortran.dg/array_memset_2.f90
index 58ce8fe6442..7805f7b9420 100644
--- a/gcc/testsuite/gfortran.dg/array_memset_2.f90
+++ b/gcc/testsuite/gfortran.dg/array_memset_2.f90
@@ -20,8 +20,8 @@ program test
data c /2*1.0/
a(1,:) = 0. ! This can't be optimized to a memset.
- b(1,:) = 0. ! This is optimized to memset.
- c = 0. ! This is optimized to memset.
+ b(1,:) = 0. ! This is optimized to = {}.
+ c = 0. ! This is optimized to = {}.
d(:,1) = 0. ! This can't be otimized to a memset.
call bar(e)
@@ -33,6 +33,6 @@ program test
end program
-! { dg-final { scan-tree-dump-times "memset" 2 "original" } }
+! { dg-final { scan-tree-dump-times "= {}" 2 "original" } }
! { dg-final { cleanup-tree-dump "original" } }
! { dg-final { cleanup-modules "foo" } }
diff --git a/gcc/testsuite/gfortran.dg/bound_4.f90 b/gcc/testsuite/gfortran.dg/bound_4.f90
index dd934519d53..b63ce9ec6a9 100644
--- a/gcc/testsuite/gfortran.dg/bound_4.f90
+++ b/gcc/testsuite/gfortran.dg/bound_4.f90
@@ -12,14 +12,14 @@ end program test
subroutine ha0020(mf3)
implicit none
- integer xca(1), xda(1), mf3
+ integer xca(2), xda(2), mf3
xca = 1
xda = -1
- xca(1:1) = xda(1:2:mf3)
+ xca(1:2:-1) = xda(1:2:mf3)
- if (any (xca /= -1)) call abort
+ if (any (xca /= 1)) call abort
if (any(xda(1:2:mf3) /= xda(1:0))) call abort
if (size(xda(1:2:mf3)) /= 0) call abort
if (any(shape(xda(1:2:mf3)) /= 0)) call abort
diff --git a/gcc/testsuite/gfortran.dg/bounds_check_14.f90 b/gcc/testsuite/gfortran.dg/bounds_check_14.f90
index 0b7edfe565b..1e5a4aeeee3 100644
--- a/gcc/testsuite/gfortran.dg/bounds_check_14.f90
+++ b/gcc/testsuite/gfortran.dg/bounds_check_14.f90
@@ -13,14 +13,14 @@ end program test
subroutine ha0020(mf3)
implicit none
- integer xca(1), xda(1), mf3
+ integer xca(2), xda(2), mf3
xca = 1
xda = -1
- xca(1:1) = xda(1:2:mf3)
+ xca(1:2:-1) = xda(1:2:mf3)
- if (any (xca /= -1)) call abort
+ if (any (xca /= 1)) call abort
if (any(xda(1:2:mf3) /= xda(1:0))) call abort
if (size(xda(1:2:mf3)) /= 0) call abort
if (any(shape(xda(1:2:mf3)) /= 0)) call abort
diff --git a/gcc/testsuite/gfortran.dg/bounds_check_fail_3.f90 b/gcc/testsuite/gfortran.dg/bounds_check_fail_3.f90
new file mode 100644
index 00000000000..0826b7d5efc
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bounds_check_fail_3.f90
@@ -0,0 +1,12 @@
+! { dg-do run }
+! { dg-options "-fbounds-check" }
+! { dg-shouldfail "foo" }
+ integer x(10), m, n
+ x = (/ (i, i = 1, 10) /)
+ m = -3
+ n = -2
+ x(7:1:m) = x(6:2:n)
+ if (any(x /= (/ 2, 2, 3, 4, 5, 6, 6, 8, 9, 10 /))) call abort()
+ x(8:1:m) = x(5:2:n)
+ end
+! { dg-output "line 10 .* bound mismatch, .* dimension 1 .* array \'x\' \\\(3/2\\\)" }
diff --git a/gcc/testsuite/gfortran.dg/bounds_check_fail_4.f90 b/gcc/testsuite/gfortran.dg/bounds_check_fail_4.f90
new file mode 100644
index 00000000000..dee3ca8d66e
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/bounds_check_fail_4.f90
@@ -0,0 +1,12 @@
+! { dg-do run }
+! { dg-options "-fbounds-check" }
+! { dg-shouldfail "foo" }
+ integer x(10), m, n
+ x = (/ (i, i = 1, 10) /)
+ m = -3
+ n = -2
+ x(7:1:m) = x(1:3) + x(6:2:n)
+ if (any(x /= (/ 5, 2, 3, 6, 5, 6, 7, 8, 9, 10 /))) call abort()
+ x(8:1:m) = x(1:3) + x(5:2:n)
+ end
+! { dg-output "line 10 .* bound mismatch, .* dimension 1 .* array \'x\' \\\(2/3\\\)" }
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/c_kind_int128_test1.f03 b/gcc/testsuite/gfortran.dg/c_kind_int128_test1.f03
index 6be1ac20b64..b1919614b2e 100644
--- a/gcc/testsuite/gfortran.dg/c_kind_int128_test1.f03
+++ b/gcc/testsuite/gfortran.dg/c_kind_int128_test1.f03
@@ -2,7 +2,6 @@
! { dg-options "-std=f2003" }
! { dg-require-effective-target fortran_integer_16 }
!
-! Note: int_fast*_t currently not supported.
subroutine c_kind_int128_1
use, intrinsic :: iso_c_binding
@@ -10,15 +9,16 @@ subroutine c_kind_int128_1
integer(c_int128_t) :: a ! { dg-error "has no IMPLICIT type" }
integer(c_int_least128_t) :: b ! { dg-error "has no IMPLICIT type" }
-! integer(c_int_fast128_t) :: c
-
+ integer(c_int_fast128_t) :: c ! { dg-error "has no IMPLICIT type" }
+
end subroutine c_kind_int128_1
+
subroutine c_kind_int128_2
use, intrinsic :: iso_c_binding
integer(c_int128_t) :: a ! { dg-error "has not been declared or is a variable" }
integer(c_int_least128_t) :: b ! { dg-error "has not been declared or is a variable" }
-! integer(c_int_fast128_t) :: c
-
+ integer(c_int_fast128_t) :: c ! { dg-error "has not been declared or is a variable" }
+
end subroutine c_kind_int128_2
diff --git a/gcc/testsuite/gfortran.dg/c_kind_int128_test2.f03 b/gcc/testsuite/gfortran.dg/c_kind_int128_test2.f03
index 2f22b72d0be..4fe2dac2913 100644
--- a/gcc/testsuite/gfortran.dg/c_kind_int128_test2.f03
+++ b/gcc/testsuite/gfortran.dg/c_kind_int128_test2.f03
@@ -2,7 +2,7 @@
! { dg-options "-std=gnu" }
! { dg-require-effective-target fortran_integer_16 }
!
-! Note: int_fast*_t currently not supported.
+! Note: int_fast128_t currently not supported.
program c_kind_int128
use, intrinsic :: iso_c_binding
diff --git a/gcc/testsuite/gfortran.dg/c_kind_params.f90 b/gcc/testsuite/gfortran.dg/c_kind_params.f90
index 871ae822b56..4176157887a 100644
--- a/gcc/testsuite/gfortran.dg/c_kind_params.f90
+++ b/gcc/testsuite/gfortran.dg/c_kind_params.f90
@@ -5,16 +5,16 @@
! the -w option is needed to make f951 not report a warning for
! the -std=c99 option that the C file needs.
!
-! Note: int_fast*_t currently not supported, cf. PR 448.
module c_kind_params
use, intrinsic :: iso_c_binding
implicit none
contains
subroutine param_test(my_short, my_int, my_long, my_long_long, &
- my_int8_t, my_int_least8_t, my_int16_t, &
- my_int_least16_t, my_int32_t, my_int_least32_t, &
- my_int64_t, my_int_least64_t, &
+ my_int8_t, my_int_least8_t, my_int_fast8_t, &
+ my_int16_t, my_int_least16_t, my_int_fast16_t, &
+ my_int32_t, my_int_least32_t, my_int_fast32_t, &
+ my_int64_t, my_int_least64_t, my_int_fast64_t, &
my_intmax_t, my_intptr_t, my_float, my_double, my_long_double, &
my_char, my_bool) bind(c)
integer(c_short), value :: my_short
@@ -23,16 +23,16 @@ contains
integer(c_long_long), value :: my_long_long
integer(c_int8_t), value :: my_int8_t
integer(c_int_least8_t), value :: my_int_least8_t
-! integer(c_int_fast8_t), value :: my_int_fast8_t
+ integer(c_int_fast8_t), value :: my_int_fast8_t
integer(c_int16_t), value :: my_int16_t
integer(c_int_least16_t), value :: my_int_least16_t
-! integer(c_int_fast16_t), value :: my_int_fast16_t
+ integer(c_int_fast16_t), value :: my_int_fast16_t
integer(c_int32_t), value :: my_int32_t
integer(c_int_least32_t), value :: my_int_least32_t
-! integer(c_int_fast32_t), value :: my_int_fast32_t
+ integer(c_int_fast32_t), value :: my_int_fast32_t
integer(c_int64_t), value :: my_int64_t
integer(c_int_least64_t), value :: my_int_least64_t
-! integer(c_int_fast64_t), value :: my_int_fast64_t
+ integer(c_int_fast64_t), value :: my_int_fast64_t
integer(c_intmax_t), value :: my_intmax_t
integer(c_intptr_t), value :: my_intptr_t
real(c_float), value :: my_float
@@ -48,19 +48,19 @@ contains
if(my_int8_t /= 1_c_int8_t) call abort()
if(my_int_least8_t /= 2_c_int_least8_t ) call abort()
- print *, 'c_int_fast8_t is: ', c_int_fast8_t
+ if(my_int_fast8_t /= 3_c_int_fast8_t ) call abort()
if(my_int16_t /= 1_c_int16_t) call abort()
if(my_int_least16_t /= 2_c_int_least16_t) call abort()
- print *, 'c_int_fast16_t is: ', c_int_fast16_t
+ if(my_int_fast16_t /= 3_c_int_fast16_t ) call abort()
if(my_int32_t /= 1_c_int32_t) call abort()
if(my_int_least32_t /= 2_c_int_least32_t) call abort()
- print *, 'c_int_fast32_t is: ', c_int_fast32_t
+ if(my_int_fast32_t /= 3_c_int_fast32_t ) call abort()
if(my_int64_t /= 1_c_int64_t) call abort()
if(my_int_least64_t /= 2_c_int_least64_t) call abort()
- print *, 'c_int_fast64_t is: ', c_int_fast64_t
+ if(my_int_fast64_t /= 3_c_int_fast64_t ) call abort()
if(my_intmax_t /= 1_c_intmax_t) call abort()
if(my_intptr_t /= 0_c_intptr_t) call abort()
diff --git a/gcc/testsuite/gfortran.dg/c_kinds.c b/gcc/testsuite/gfortran.dg/c_kinds.c
index f79a70f7532..8fb658a98e8 100644
--- a/gcc/testsuite/gfortran.dg/c_kinds.c
+++ b/gcc/testsuite/gfortran.dg/c_kinds.c
@@ -3,15 +3,14 @@
#include <stdint.h>
-/* Note: int_fast*_t is currently not supported, cf. PR 448 */
void param_test(short int my_short, int my_int, long int my_long,
long long int my_long_long, int8_t my_int8_t,
- int_least8_t my_int_least8_t, /*int_fast8_t my_int_fast8_t,*/
+ int_least8_t my_int_least8_t, int_fast8_t my_int_fast8_t,
int16_t my_int16_t, int_least16_t my_int_least16_t,
- /*int_fast16_t my_int_fast16_t,*/ int32_t my_int32_t,
- int_least32_t my_int_least32_t, /*int_fast32_t my_int_fast32_t,*/
+ int_fast16_t my_int_fast16_t, int32_t my_int32_t,
+ int_least32_t my_int_least32_t, int_fast32_t my_int_fast32_t,
int64_t my_int64_t, int_least64_t my_int_least64_t,
- /*int_fast64_t my_int_fast64_t,*/ intmax_t my_intmax_t,
+ int_fast64_t my_int_fast64_t, intmax_t my_intmax_t,
intptr_t my_intptr_t, float my_float, double my_double,
long double my_long_double, char my_char, _Bool my_bool);
@@ -43,10 +42,10 @@ int main(int argc, char **argv)
_Bool my_bool = 1;
param_test(my_short, my_int, my_long, my_long_long, my_int8_t,
- my_int_least8_t, /*my_int_fast8_t, */ my_int16_t,
- my_int_least16_t,/* my_int_fast16_t,*/ my_int32_t,
- my_int_least32_t,/* my_int_fast32_t,*/ my_int64_t,
- my_int_least64_t,/* my_int_fast64_t,*/ my_intmax_t,
+ my_int_least8_t, my_int_fast8_t, my_int16_t,
+ my_int_least16_t, my_int_fast16_t, my_int32_t,
+ my_int_least32_t, my_int_fast32_t, my_int64_t,
+ my_int_least64_t, my_int_fast64_t, my_intmax_t,
my_intptr_t, my_float, my_double, my_long_double, my_char,
my_bool);
diff --git a/gcc/testsuite/gfortran.dg/default_format_1.f90 b/gcc/testsuite/gfortran.dg/default_format_1.f90
index 75f08af0f8d..e374f1b895d 100644
--- a/gcc/testsuite/gfortran.dg/default_format_1.f90
+++ b/gcc/testsuite/gfortran.dg/default_format_1.f90
@@ -1,7 +1,6 @@
-! { dg-do run { xfail spu-*-* *-*-cygwin* } }
+! { dg-do run { xfail spu-*-* } }
! Test XFAILed on Darwin because the system's printf() lacks
-! proper support for denormals. XFAILed on cygwin as the result
-! is off by one bit in some cases.
+! proper support for denormals.
!
! This tests that the default formats for formatted I/O of reals are
! wide enough and have enough precision, by checking that values can
diff --git a/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90 b/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90
index adecd50c4d0..debc113ffc1 100644
--- a/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90
+++ b/gcc/testsuite/gfortran.dg/default_format_denormal_1.f90
@@ -1,4 +1,4 @@
-! { dg-do run { xfail alpha*-*-* *-*-darwin[89]* *-*-freebsd* *-*-mingw* spu-*-* } }
+! { dg-do run { xfail alpha*-*-* *-*-darwin[89]* *-*-freebsd* *-*-mingw* *-*-cygwin* spu-*-* } }
! Test XFAILed on these platforms because the system's printf() lacks
! proper support for denormals.
!
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/erf_2.F90 b/gcc/testsuite/gfortran.dg/erf_2.F90
new file mode 100644
index 00000000000..d418d5fccb9
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/erf_2.F90
@@ -0,0 +1,52 @@
+! { dg-do run }
+! { dg-options "-fno-range-check -ffree-line-length-none " }
+! { dg-options "-fno-range-check -ffree-line-length-none -mieee" { target alpha*-*-* } } */
+!
+! Check that simplification functions and runtime library agree on ERF,
+! ERFC and ERFC_SCALED.
+
+program test
+ implicit none
+
+ interface check
+ procedure check_r4
+ procedure check_r8
+ end interface check
+
+ real(kind=4) :: x4
+ real(kind=8) :: x8
+
+#define CHECK(a) \
+ x8 = a ; x4 = a ; \
+ call check(erf(real(a,kind=8)), erf(x8)) ; \
+ call check(erf(real(a,kind=4)), erf(x4)) ; \
+ call check(erfc(real(a,kind=8)), erfc(x8)) ; \
+ call check(erfc(real(a,kind=4)), erfc(x4)) ; \
+ call check(erfc_scaled(real(a,kind=8)), erfc_scaled(x8)) ; \
+ call check(erfc_scaled(real(a,kind=4)), erfc_scaled(x4)) ;
+
+ CHECK(0.0)
+ CHECK(0.9)
+ CHECK(1.9)
+ CHECK(19.)
+ CHECK(190.)
+
+ CHECK(-0.0)
+ CHECK(-0.9)
+ CHECK(-1.9)
+ CHECK(-19.)
+ CHECK(-190.)
+
+contains
+
+ subroutine check_r4 (a, b)
+ real(kind=4), intent(in) :: a, b
+ if (abs(a - b) > 10 * spacing(a)) call abort
+ end subroutine
+
+ subroutine check_r8 (a, b)
+ real(kind=8), intent(in) :: a, b
+ if (abs(a - b) > 10 * spacing(a)) call abort
+ end subroutine
+
+end program test
diff --git a/gcc/testsuite/gfortran.dg/erfc_scaled_2.f90 b/gcc/testsuite/gfortran.dg/erfc_scaled_2.f90
new file mode 100644
index 00000000000..97fa91fb915
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/erfc_scaled_2.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+!
+! Check that ERFC_SCALED can be used in initialization expressions
+ real, parameter :: r = 100*erfc_scaled(12.7)
+ integer(kind=int(r)) :: i
+
+ real(kind=8), parameter :: r8 = 100*erfc_scaled(6.77)
+ integer(kind=int(r8)) :: j
+
+ i = 12
+ j = 8
+ print *, i, j
+
+ end
diff --git a/gcc/testsuite/gfortran.dg/interface_27.f90 b/gcc/testsuite/gfortran.dg/interface_27.f90
new file mode 100644
index 00000000000..a3f1e4b2620
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/interface_27.f90
@@ -0,0 +1,41 @@
+! { dg-do compile }
+!
+! PR 40039: Procedures as actual arguments: Check intent of arguments
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+module m
+
+contains
+
+subroutine a(x,f)
+ real :: x
+ interface
+ real function f(y)
+ real,intent(in) :: y
+ end function
+ end interface
+ print *,f(x)
+end subroutine
+
+real function func(z)
+ real,intent(inout) :: z
+ func = z**2
+end function
+
+subroutine caller
+ interface
+ real function p(y)
+ real,intent(in) :: y
+ end function
+ end interface
+ pointer :: p
+
+ call a(4.3,func) ! { dg-error "Type/rank mismatch in argument" }
+ p => func ! { dg-error "Interfaces don't match in procedure pointer assignment" }
+end subroutine
+
+end module
+
+! { dg-final { cleanup-modules "m" } }
+
diff --git a/gcc/testsuite/gfortran.dg/interface_28.f90 b/gcc/testsuite/gfortran.dg/interface_28.f90
new file mode 100644
index 00000000000..53495a44348
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/interface_28.f90
@@ -0,0 +1,39 @@
+! { dg-do compile }
+!
+! PR 36947: Attributes not fully checked comparing actual vs dummy procedure
+!
+! Contributed by Walter Spector <w6ws@earthlink.net>
+
+module testsub
+ contains
+ subroutine test(sub)
+ interface
+ subroutine sub(x)
+ integer, intent(in), optional:: x
+ end subroutine
+ end interface
+ print *, "In test(), about to call sub()"
+ call sub()
+ end subroutine
+end module
+
+module sub
+ contains
+ subroutine subActual(x)
+ ! actual subroutine's argment is different in intent and optional
+ integer, intent(inout):: x
+ print *, "In subActual():", x
+ end subroutine
+end module
+
+program interfaceCheck
+ use testsub
+ use sub
+
+ integer :: a
+
+ call test(subActual) ! { dg-error "Type/rank mismatch in argument" }
+end program
+
+! { dg-final { cleanup-modules "sub testsub" } }
+
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/proc_ptr_11.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_11.f90
index 5c39f995d34..92d65423157 100644
--- a/gcc/testsuite/gfortran.dg/proc_ptr_11.f90
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_11.f90
@@ -23,6 +23,7 @@ program bsp
interface
function p3(x)
real(8) :: p3,x
+ intent(in) :: x
end function p3
end interface
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_18.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_18.f90
new file mode 100644
index 00000000000..79cd68a513f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_18.f90
@@ -0,0 +1,25 @@
+! { dg-do run }
+!
+! PR 40176: Fortran 2003: Procedure pointers with array return value
+!
+! Original test case by Barron Bichon <barron.bichon@swri.org>
+! Modified by Janus Weil <janus@gcc.gnu.org>
+
+PROGRAM test_prog
+
+ PROCEDURE(triple), POINTER :: f
+
+ f => triple
+ if (sum(f(2.,4.)-triple(2.,4.))>1E-3) call abort()
+
+CONTAINS
+
+ FUNCTION triple(a,b) RESULT(tre)
+ REAL, INTENT(in) :: a, b
+ REAL :: tre(2)
+ tre(1) = 3.*a
+ tre(2) = 3.*b
+ END FUNCTION triple
+
+END PROGRAM test_prog
+
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_19.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_19.f90
new file mode 100644
index 00000000000..a78a8d46432
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_19.f90
@@ -0,0 +1,35 @@
+! { dg-do run }
+!
+! PR 40176: Fortran 2003: Procedure pointers with array return value
+!
+! This example tests for a bug in procedure pointer assignments,
+! where the rhs is a dummy.
+!
+! Original test case by Barron Bichon <barron.bichon@swri.org>
+! Modified by Janus Weil <janus@gcc.gnu.org>
+
+PROGRAM test_prog
+
+ PROCEDURE(add), POINTER :: forig, fset
+
+ forig => add
+
+ CALL set_ptr(forig,fset)
+
+ if (forig(1,2) /= fset(1,2)) call abort()
+
+CONTAINS
+
+ SUBROUTINE set_ptr(f1,f2)
+ PROCEDURE(add), POINTER :: f1, f2
+ f2 => f1
+ END SUBROUTINE set_ptr
+
+ FUNCTION add(a,b)
+ INTEGER :: a,b,add
+ add = a+b
+
+ END FUNCTION add
+
+END PROGRAM test_prog
+
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_comp_10.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_comp_10.f90
new file mode 100644
index 00000000000..382f4125533
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_comp_10.f90
@@ -0,0 +1,31 @@
+! { dg-do compile }
+!
+! PR 40176: Fortran 2003: Procedure pointers with array return value
+!
+! Contributed by Janus Weil <janus@gcc.gnu.org>
+
+module m
+
+abstract interface
+ function ai()
+ real, dimension(3) :: ai
+ end function
+end interface
+
+type t
+ procedure(ai), pointer, nopass :: ppc
+end type
+
+procedure(ai), pointer :: pp
+
+end module
+
+program test
+use m
+type(t) :: obj
+obj%ppc => pp
+pp => obj%ppc
+end
+
+! { dg-final { cleanup-modules "m" } }
+
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_comp_8.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_comp_8.f90
new file mode 100644
index 00000000000..ed06c2bc651
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_comp_8.f90
@@ -0,0 +1,58 @@
+! { dg-do run }
+!
+! PR 40164: Fortran 2003: "Arrays of procedure pointers" (using PPCs)
+!
+! Original test case by Barron Bichon <barron.bichon@swri.org>
+! Adapted by Janus Weil <janus@gcc.gnu.org>
+
+PROGRAM test_prog
+
+ ABSTRACT INTERFACE
+ FUNCTION fn_template(n,x) RESULT(y)
+ INTEGER, INTENT(in) :: n
+ REAL, INTENT(in) :: x(n)
+ REAL :: y(n)
+ END FUNCTION fn_template
+ END INTERFACE
+
+ TYPE PPA
+ PROCEDURE(fn_template), POINTER, NOPASS :: f
+ END TYPE PPA
+
+ TYPE ProcPointerArray
+ PROCEDURE(add), POINTER, NOPASS :: f
+ END TYPE ProcPointerArray
+
+ TYPE (ProcPointerArray) :: f_array(3)
+ PROCEDURE(add), POINTER :: f
+ real :: r
+
+ f_array(1)%f => add
+ f => f_array(1)%f
+ f_array(2)%f => sub
+ f_array(3)%f => f_array(1)%f
+
+ r = f(1.,2.)
+ if (abs(r-3.)>1E-3) call abort()
+ r = f_array(1)%f(4.,2.)
+ if (abs(r-6.)>1E-3) call abort()
+ r = f_array(2)%f(5.,3.)
+ if (abs(r-2.)>1E-3) call abort()
+ if (abs(f_array(1)%f(1.,3.)-f_array(3)%f(2.,2.))>1E-3) call abort()
+
+CONTAINS
+
+ FUNCTION add(a,b) RESULT(sum)
+ REAL, INTENT(in) :: a, b
+ REAL :: sum
+ sum = a + b
+ END FUNCTION add
+
+ FUNCTION sub(a,b) RESULT(diff)
+ REAL, INTENT(in) :: a, b
+ REAL :: diff
+ diff = a - b
+ END FUNCTION sub
+
+END PROGRAM test_prog
+
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_comp_9.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_comp_9.f90
new file mode 100644
index 00000000000..951db485fb0
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_comp_9.f90
@@ -0,0 +1,37 @@
+! { dg-do run }
+!
+! PR 40176: Fortran 2003: Procedure pointers with array return value
+!
+! Original test case by Barron Bichon <barron.bichon@swri.org>
+! Modified by Janus Weil <janus@gcc.gnu.org>
+
+PROGRAM test_prog
+
+ TYPE ProcPointerType
+ PROCEDURE(triple), POINTER, NOPASS :: f
+ END TYPE ProcPointerType
+
+ TYPE (ProcPointerType) :: ppt
+ PROCEDURE(triple), POINTER :: f
+ REAL :: tres(2)
+
+ ppt%f => triple
+ f => ppt%f
+ tres = f(2,[2.,4.])
+ if (abs(tres(1)-6.)>1E-3) call abort()
+ if (abs(tres(2)-12.)>1E-3) call abort()
+ tres = ppt%f(2,[3.,5.])
+ if (abs(tres(1)-9.)>1E-3) call abort()
+ if (abs(tres(2)-15.)>1E-3) call abort()
+
+CONTAINS
+
+ FUNCTION triple(n,x) RESULT(tre)
+ INTEGER, INTENT(in) :: n
+ REAL, INTENT(in) :: x(2)
+ REAL :: tre(2)
+ tre = 3.*x
+ END FUNCTION triple
+
+END PROGRAM test_prog
+
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_result_1.f90 b/gcc/testsuite/gfortran.dg/proc_ptr_result_1.f90
index 1261791ae73..f3f7252a6ad 100644
--- a/gcc/testsuite/gfortran.dg/proc_ptr_result_1.f90
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_result_1.f90
@@ -114,7 +114,7 @@ contains
pointer :: f
interface
integer function f(x)
- integer :: x
+ integer,intent(in) :: x
end function
end interface
f => iabs
@@ -123,7 +123,7 @@ contains
function g()
interface
integer function g(x)
- integer :: x
+ integer,intent(in) :: x
end function g
end interface
pointer :: g
@@ -133,13 +133,13 @@ contains
function h(arg)
interface
subroutine arg(b)
- integer :: b
+ integer,intent(inout) :: b
end subroutine arg
end interface
pointer :: h
interface
subroutine h(a)
- integer :: a
+ integer,intent(inout) :: a
end subroutine h
end interface
h => arg
@@ -150,6 +150,7 @@ contains
interface
function i(x)
integer :: i,x
+ intent(in) :: x
end function i
end interface
i => iabs
diff --git a/gcc/testsuite/gfortran.dg/string_1.f90 b/gcc/testsuite/gfortran.dg/string_1.f90
new file mode 100644
index 00000000000..11dc5b7a340
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/string_1.f90
@@ -0,0 +1,14 @@
+! { dg-do compile }
+!
+program main
+ implicit none
+ integer(kind=8), parameter :: l1 = 2_8**32_8
+ character (len=2_8**32_8+4_8), parameter :: s = "" ! { dg-error "too large" }
+ character (len=2_8**32_8+4_8) :: ch ! { dg-error "too large" }
+ character (len=l1 + 1_8) :: v ! { dg-error "too large" }
+ character (len=int(huge(0_4),kind=8) + 1_8) :: z ! { dg-error "too large" }
+ character (len=int(huge(0_4),kind=8) + 0_8) :: w
+
+ print *, len(s)
+
+end program main
diff --git a/gcc/testsuite/gfortran.dg/string_2.f90 b/gcc/testsuite/gfortran.dg/string_2.f90
new file mode 100644
index 00000000000..c94c4141bc5
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/string_2.f90
@@ -0,0 +1,12 @@
+! { dg-do compile }
+!
+program main
+ implicit none
+ character(len=10) :: s
+
+ s = ''
+ print *, s(1:2_8**32_8+3_8) ! { dg-error "exceeds the string length" }
+ print *, s(2_8**32_8+3_8:2_8**32_8+4_8) ! { dg-error "exceeds the string length" }
+ print *, len(s(1:2_8**32_8+3_8)) ! { dg-error "exceeds the string length" }
+
+end program main
diff --git a/gcc/testsuite/gfortran.dg/string_3.f90 b/gcc/testsuite/gfortran.dg/string_3.f90
new file mode 100644
index 00000000000..7daf8d31ae6
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/string_3.f90
@@ -0,0 +1,19 @@
+! { dg-do compile }
+!
+subroutine foo(i)
+ implicit none
+ integer, intent(in) :: i
+ character(len=i) :: s
+
+ s = ''
+ print *, s(1:2_8**32_8+3_8) ! { dg-error "too large" }
+ print *, s(2_8**32_8+3_8:2_8**32_8+4_8) ! { dg-error "too large" }
+ print *, len(s(1:2_8**32_8+3_8)) ! { dg-error "too large" }
+ print *, len(s(2_8**32_8+3_8:2_8**32_8+4_8)) ! { dg-error "too large" }
+
+ print *, s(2_8**32_8+3_8:1)
+ print *, s(2_8**32_8+4_8:2_8**32_8+3_8)
+ print *, len(s(2_8**32_8+3_8:1))
+ print *, len(s(2_8**32_8+4_8:2_8**32_8+3_8))
+
+end subroutine
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/addr6.adb b/gcc/testsuite/gnat.dg/addr6.adb
new file mode 100644
index 00000000000..e357132d66f
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/addr6.adb
@@ -0,0 +1,31 @@
+-- { dg-do compile }
+
+procedure Addr6 is
+
+ type Byte is mod 2**8;
+
+ type Byte_Arr1 is array (Positive range <>) of Byte;
+ for Byte_Arr1'Alignment use 4;
+
+ type Byte_Arr2 is array (Positive range <>) of Byte;
+
+ function Length return Natural is
+ begin
+ return 1;
+ end;
+
+ function Empty return Byte_Arr2 is
+ Null_Arr : Byte_Arr2 (1 .. 0);
+ begin
+ return Null_Arr;
+ end;
+
+ A1 : Byte_Arr1 (1 .. Length);
+
+ A2 : Byte_Arr2 (A1'Range);
+ for A2'Alignment use 4;
+ for A2'Address use A1'Address;
+
+begin
+ A2 := Empty;
+end;
diff --git a/gcc/testsuite/gnat.dg/loop_optimization6.adb b/gcc/testsuite/gnat.dg/loop_optimization6.adb
new file mode 100644
index 00000000000..42f1717f1ad
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/loop_optimization6.adb
@@ -0,0 +1,25 @@
+-- { dg-do compile }
+-- { dg-options "-O -gnatp -fdump-tree-optimized" }
+
+package body Loop_Optimization6 is
+ procedure Foo is
+ begin
+ for I in 1 .. 1_000_000 loop
+ A := A + 1;
+ end loop;
+ end Foo;
+
+ procedure Bar is
+ begin
+ for J in 1 .. 1_000 loop
+ Foo;
+ end loop;
+ end Bar;
+
+ procedure Main is
+ begin
+ Bar;
+ end;
+end Loop_Optimization6;
+
+-- { dg-final { scan-tree-dump-not "goto" "optimized"} }
diff --git a/gcc/testsuite/gnat.dg/loop_optimization6.ads b/gcc/testsuite/gnat.dg/loop_optimization6.ads
new file mode 100644
index 00000000000..9b8a2670322
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/loop_optimization6.ads
@@ -0,0 +1,4 @@
+package Loop_Optimization6 is
+ A : Integer := 0;
+ procedure Main;
+end Loop_Optimization6;
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/specs/rep_clause3.ads b/gcc/testsuite/gnat.dg/specs/rep_clause3.ads
new file mode 100644
index 00000000000..438c6046868
--- /dev/null
+++ b/gcc/testsuite/gnat.dg/specs/rep_clause3.ads
@@ -0,0 +1,36 @@
+package Rep_Clause3 is
+
+ type Record1 is
+ record
+ Page_Handle : Integer range 0 .. 255;
+ Page_Owner : Integer range 0 .. 15;
+ end record;
+ for Record1 use
+ record
+ Page_Handle at 0 range 0 .. 15;
+ Page_Owner at 0 range 16 .. 19;
+ end record;
+ for Record1'Size use 20;
+
+ type Range_A is range 1 .. 7;
+ for Range_A'Size use 16;
+
+ type Array_Type is array (Range_A) of Record1;
+ pragma Pack (Array_Type);
+ for Array_Type'Size use 7 * 20;
+-- for array_Type'alignment use 1;
+
+ type Record2 is
+ record
+ Page_Tree_Index : Range_A;
+ Page_Tree : Array_Type;
+ end record;
+
+ for Record2 use
+ record
+ Page_Tree_Index at 0 range 0 .. 15;
+ Page_Tree at 0 range 16 .. 15 + (7 * 20);
+ end record;
+ for Record2'Size use 16 + (7 * 20);
+
+end Rep_Clause3;
diff --git a/gcc/testsuite/lib/target-supports.exp b/gcc/testsuite/lib/target-supports.exp
index 3282d6d7b48..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 {
@@ -1477,6 +1489,17 @@ proc check_effective_target_arm_thumb1_ok { } {
} "-mthumb"]
}
+# Return 1 is this is an ARM target where -mthumb causes Thumb-2 to be
+# used.
+
+proc check_effective_target_arm_thumb2_ok { } {
+ return [check_no_compiler_messages arm_thumb2_ok assembly {
+ #if !defined(__thumb2__)
+ #error FOO
+ #endif
+ } "-mthumb"]
+}
+
# Return 1 if the target supports executing NEON instructions, 0
# otherwise. Cache the result.
diff --git a/gcc/timevar.def b/gcc/timevar.def
index e6853756e66..53967b38476 100644
--- a/gcc/timevar.def
+++ b/gcc/timevar.def
@@ -121,6 +121,7 @@ DEFTIMEVAR (TV_TREE_LOOP_UNSWITCH , "tree loop unswitching")
DEFTIMEVAR (TV_COMPLETE_UNROLL , "complete unrolling")
DEFTIMEVAR (TV_TREE_PARALLELIZE_LOOPS, "tree parallelize loops")
DEFTIMEVAR (TV_TREE_VECTORIZATION , "tree vectorization")
+DEFTIMEVAR (TV_TREE_SLP_VECTORIZATION, "tree slp vectorization")
DEFTIMEVAR (TV_GRAPHITE_TRANSFORMS , "GRAPHITE loop transforms")
DEFTIMEVAR (TV_TREE_LINEAR_TRANSFORM , "tree loop linear")
DEFTIMEVAR (TV_TREE_LOOP_DISTRIBUTION, "tree loop distribution")
diff --git a/gcc/toplev.h b/gcc/toplev.h
index cf03d5c6ce1..37e6f2dc1a8 100644
--- a/gcc/toplev.h
+++ b/gcc/toplev.h
@@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
#ifndef GCC_TOPLEV_H
#define GCC_TOPLEV_H
#include "input.h"
+#include "bversion.h"
/* If non-NULL, return one past-the-end of the matching SUBPART of
the WHOLE string. */
@@ -49,7 +50,7 @@ extern void _fatal_insn (const char *, const_rtx, const char *, int, const char
/* None of these functions are suitable for ATTRIBUTE_PRINTF, because
each language front end can extend them with its own set of format
specifiers. We must use custom format checks. */
-#if GCC_VERSION >= 4001
+#if (ENABLE_CHECKING && GCC_VERSION >= 4001) || GCC_VERSION == BUILDING_GCC_VERSION
#define ATTRIBUTE_GCC_DIAG(m, n) __attribute__ ((__format__ (GCC_DIAG_STYLE, m, n))) ATTRIBUTE_NONNULL(m)
#else
#define ATTRIBUTE_GCC_DIAG(m, n) ATTRIBUTE_NONNULL(m)
diff --git a/gcc/tree-cfg.c b/gcc/tree-cfg.c
index a0706bdaf66..afc69576e79 100644
--- a/gcc/tree-cfg.c
+++ b/gcc/tree-cfg.c
@@ -1289,9 +1289,6 @@ replace_uses_by (tree name, tree val)
FOR_EACH_IMM_USE_STMT (stmt, imm_iter, name)
{
- if (gimple_code (stmt) != GIMPLE_PHI)
- push_stmt_changes (&stmt);
-
FOR_EACH_IMM_USE_ON_STMT (use, imm_iter)
{
replace_exp (use, val);
@@ -1318,7 +1315,7 @@ replace_uses_by (tree name, tree val)
if (cfgcleanup_altered_bbs)
bitmap_set_bit (cfgcleanup_altered_bbs, gimple_bb (stmt)->index);
- /* FIXME. This should go in pop_stmt_changes. */
+ /* FIXME. This should go in update_stmt. */
for (i = 0; i < gimple_num_ops (stmt); i++)
{
tree op = gimple_op (stmt, i);
@@ -1330,8 +1327,7 @@ replace_uses_by (tree name, tree val)
}
maybe_clean_or_replace_eh_stmt (stmt, stmt);
-
- pop_stmt_changes (&stmt);
+ update_stmt (stmt);
}
}
@@ -2045,18 +2041,6 @@ remove_useless_stmts_1 (gimple_stmt_iterator *gsi, struct rus_data *data)
}
break;
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- /* If we do not optimize remove GIMPLE_CHANGE_DYNAMIC_TYPE as
- expansion is confused about them and we only remove them
- during alias computation otherwise. */
- if (!optimize)
- {
- data->last_was_goto = false;
- gsi_remove (gsi, false);
- break;
- }
- /* Fallthru. */
-
default:
data->last_was_goto = false;
gsi_next (gsi);
@@ -4038,10 +4022,6 @@ verify_types_in_gimple_stmt (gimple stmt)
case GIMPLE_ASM:
return false;
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
- return (!is_gimple_val (gimple_cdt_location (stmt))
- || !POINTER_TYPE_P (TREE_TYPE (gimple_cdt_location (stmt))));
-
case GIMPLE_PHI:
return verify_gimple_phi (stmt);
diff --git a/gcc/tree-complex.c b/gcc/tree-complex.c
index 2835220c206..3f1992b716b 100644
--- a/gcc/tree-complex.c
+++ b/gcc/tree-complex.c
@@ -604,6 +604,7 @@ extract_component (gimple_stmt_iterator *gsi, tree t, bool imagpart_p,
case INDIRECT_REF:
case COMPONENT_REF:
case ARRAY_REF:
+ case VIEW_CONVERT_EXPR:
{
tree inner_type = TREE_TYPE (TREE_TYPE (t));
diff --git a/gcc/tree-data-ref.c b/gcc/tree-data-ref.c
index de2ad5f921b..2181f469ca0 100644
--- a/gcc/tree-data-ref.c
+++ b/gcc/tree-data-ref.c
@@ -668,8 +668,9 @@ canonicalize_base_object_address (tree addr)
return build_fold_addr_expr (TREE_OPERAND (addr, 0));
}
-/* Analyzes the behavior of the memory reference DR in the innermost loop that
- contains it. Returns true if analysis succeed or false otherwise. */
+/* Analyzes the behavior of the memory reference DR in the innermost loop or
+ basic block that contains it. Returns true if analysis succeed or false
+ otherwise. */
bool
dr_analyze_innermost (struct data_reference *dr)
@@ -683,6 +684,7 @@ dr_analyze_innermost (struct data_reference *dr)
int punsignedp, pvolatilep;
affine_iv base_iv, offset_iv;
tree init, dinit, step;
+ bool in_loop = (loop && loop->num);
if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "analyze_innermost: ");
@@ -699,23 +701,43 @@ dr_analyze_innermost (struct data_reference *dr)
}
base = build_fold_addr_expr (base);
- if (!simple_iv (loop, loop_containing_stmt (stmt), base, &base_iv, false))
+ if (in_loop)
{
- if (dump_file && (dump_flags & TDF_DETAILS))
- fprintf (dump_file, "failed: evolution of base is not affine.\n");
- return false;
+ if (!simple_iv (loop, loop_containing_stmt (stmt), base, &base_iv,
+ false))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file, "failed: evolution of base is not affine.\n");
+ return false;
+ }
}
+ else
+ {
+ base_iv.base = base;
+ base_iv.step = ssize_int (0);
+ base_iv.no_overflow = true;
+ }
+
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);
@@ -752,17 +774,23 @@ dr_analyze_indices (struct data_reference *dr, struct loop *nest)
struct loop *loop = loop_containing_stmt (stmt);
VEC (tree, heap) *access_fns = NULL;
tree ref = unshare_expr (DR_REF (dr)), aref = ref, op;
- tree base, off, access_fn;
- basic_block before_loop = block_before_loop (nest);
-
+ tree base, off, access_fn = NULL_TREE;
+ basic_block before_loop = NULL;
+
+ if (nest)
+ before_loop = block_before_loop (nest);
+
while (handled_component_p (aref))
{
if (TREE_CODE (aref) == ARRAY_REF)
{
op = TREE_OPERAND (aref, 1);
- access_fn = analyze_scalar_evolution (loop, op);
- access_fn = instantiate_scev (before_loop, loop, access_fn);
- VEC_safe_push (tree, heap, access_fns, access_fn);
+ if (nest)
+ {
+ access_fn = analyze_scalar_evolution (loop, op);
+ access_fn = instantiate_scev (before_loop, loop, access_fn);
+ VEC_safe_push (tree, heap, access_fns, access_fn);
+ }
TREE_OPERAND (aref, 1) = build_int_cst (TREE_TYPE (op), 0);
}
@@ -770,7 +798,7 @@ dr_analyze_indices (struct data_reference *dr, struct loop *nest)
aref = TREE_OPERAND (aref, 0);
}
- if (INDIRECT_REF_P (aref))
+ if (nest && INDIRECT_REF_P (aref))
{
op = TREE_OPERAND (aref, 0);
access_fn = analyze_scalar_evolution (loop, op);
@@ -1223,7 +1251,17 @@ dr_may_alias_p (const struct data_reference *a, const struct data_reference *b)
return false;
/* Query the alias oracle. */
- if (!refs_may_alias_p (DR_REF (a), DR_REF (b)))
+ if (!DR_IS_READ (a) && !DR_IS_READ (b))
+ {
+ if (!refs_output_dependent_p (DR_REF (a), DR_REF (b)))
+ return false;
+ }
+ else if (DR_IS_READ (a) && !DR_IS_READ (b))
+ {
+ if (!refs_anti_dependent_p (DR_REF (a), DR_REF (b)))
+ return false;
+ }
+ else if (!refs_may_alias_p (DR_REF (a), DR_REF (b)))
return false;
if (!addr_a || !addr_b)
@@ -1322,8 +1360,9 @@ initialize_data_dependence_relation (struct data_reference *a,
/* If the base of the object is not invariant in the loop nest, we cannot
analyze it. TODO -- in fact, it would suffice to record that there may
be arbitrary dependences in the loops where the base object varies. */
- if (!object_address_invariant_in_loop_p (VEC_index (loop_p, loop_nest, 0),
- DR_BASE_OBJECT (a)))
+ if (loop_nest
+ && !object_address_invariant_in_loop_p (VEC_index (loop_p, loop_nest, 0),
+ DR_BASE_OBJECT (a)))
{
DDR_ARE_DEPENDENT (res) = chrec_dont_know;
return res;
@@ -3993,7 +4032,8 @@ compute_all_dependences (VEC (data_reference_p, heap) *datarefs,
{
ddr = initialize_data_dependence_relation (a, b, loop_nest);
VEC_safe_push (ddr_p, heap, *dependence_relations, ddr);
- compute_affine_dependence (ddr, VEC_index (loop_p, loop_nest, 0));
+ if (loop_nest)
+ compute_affine_dependence (ddr, VEC_index (loop_p, loop_nest, 0));
}
if (compute_self_and_rr)
@@ -4100,9 +4140,10 @@ find_data_references_in_stmt (struct loop *nest, gimple stmt,
dr = create_data_ref (nest, *ref->pos, stmt, ref->is_read);
gcc_assert (dr != NULL);
- /* FIXME -- data dependence analysis does not work correctly for objects with
- invariant addresses. Let us fail here until the problem is fixed. */
- if (dr_address_invariant_p (dr))
+ /* FIXME -- data dependence analysis does not work correctly for objects
+ with invariant addresses in loop nests. Let us fail here until the
+ problem is fixed. */
+ if (dr_address_invariant_p (dr) && nest)
{
free_data_ref (dr);
if (dump_file && (dump_flags & TDF_DETAILS))
@@ -4119,6 +4160,33 @@ find_data_references_in_stmt (struct loop *nest, gimple stmt,
/* Search the data references in LOOP, and record the information into
DATAREFS. Returns chrec_dont_know when failing to analyze a
+ difficult case, returns NULL_TREE otherwise. */
+
+static tree
+find_data_references_in_bb (struct loop *loop, basic_block bb,
+ VEC (data_reference_p, heap) **datarefs)
+{
+ gimple_stmt_iterator bsi;
+
+ for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
+ {
+ gimple stmt = gsi_stmt (bsi);
+
+ if (!find_data_references_in_stmt (loop, stmt, datarefs))
+ {
+ struct data_reference *res;
+ res = XCNEW (struct data_reference);
+ VEC_safe_push (data_reference_p, heap, *datarefs, res);
+
+ return chrec_dont_know;
+ }
+ }
+
+ return NULL_TREE;
+}
+
+/* Search the data references in LOOP, and record the information into
+ DATAREFS. Returns chrec_dont_know when failing to analyze a
difficult case, returns NULL_TREE otherwise.
TODO: This function should be made smarter so that it can handle address
@@ -4130,7 +4198,6 @@ find_data_references_in_loop (struct loop *loop,
{
basic_block bb, *bbs;
unsigned int i;
- gimple_stmt_iterator bsi;
bbs = get_loop_body_in_dom_order (loop);
@@ -4138,20 +4205,11 @@ find_data_references_in_loop (struct loop *loop,
{
bb = bbs[i];
- for (bsi = gsi_start_bb (bb); !gsi_end_p (bsi); gsi_next (&bsi))
- {
- gimple stmt = gsi_stmt (bsi);
-
- if (!find_data_references_in_stmt (loop, stmt, datarefs))
- {
- struct data_reference *res;
- res = XCNEW (struct data_reference);
- VEC_safe_push (data_reference_p, heap, *datarefs, res);
-
- free (bbs);
- return chrec_dont_know;
- }
- }
+ if (find_data_references_in_bb (loop, bb, datarefs) == chrec_dont_know)
+ {
+ free (bbs);
+ return chrec_dont_know;
+ }
}
free (bbs);
@@ -4288,6 +4346,26 @@ compute_data_dependences_for_loop (struct loop *loop,
return res;
}
+/* Returns true when the data dependences for the basic block BB have been
+ computed, false otherwise.
+ DATAREFS is initialized to all the array elements contained in this basic
+ block, DEPENDENCE_RELATIONS contains the relations between the data
+ references. Compute read-read and self relations if
+ COMPUTE_SELF_AND_READ_READ_DEPENDENCES is TRUE. */
+bool
+compute_data_dependences_for_bb (basic_block bb,
+ bool compute_self_and_read_read_dependences,
+ VEC (data_reference_p, heap) **datarefs,
+ VEC (ddr_p, heap) **dependence_relations)
+{
+ if (find_data_references_in_bb (NULL, bb, datarefs) == chrec_dont_know)
+ return false;
+
+ compute_all_dependences (*datarefs, dependence_relations, NULL,
+ compute_self_and_read_read_dependences);
+ return true;
+}
+
/* Entry point (for testing only). Analyze all the data references
and the dependence relations in LOOP.
diff --git a/gcc/tree-data-ref.h b/gcc/tree-data-ref.h
index 690301a6f94..dfce23309f5 100644
--- a/gcc/tree-data-ref.h
+++ b/gcc/tree-data-ref.h
@@ -383,6 +383,9 @@ bool dr_analyze_innermost (struct data_reference *);
extern bool compute_data_dependences_for_loop (struct loop *, bool,
VEC (data_reference_p, heap) **,
VEC (ddr_p, heap) **);
+extern bool compute_data_dependences_for_bb (basic_block, bool,
+ VEC (data_reference_p, heap) **,
+ VEC (ddr_p, heap) **);
extern tree find_data_references_in_loop (struct loop *,
VEC (data_reference_p, heap) **);
extern void print_direction_vector (FILE *, lambda_vector, int);
diff --git a/gcc/tree-dfa.c b/gcc/tree-dfa.c
index d00324a348e..d4a379c333c 100644
--- a/gcc/tree-dfa.c
+++ b/gcc/tree-dfa.c
@@ -651,11 +651,7 @@ get_virtual_var (tree var)
return var;
}
-/* Mark all the naked symbols in STMT for SSA renaming.
-
- NOTE: This function should only be used for brand new statements.
- If the caller is modifying an existing statement, it should use the
- combination push_stmt_changes/pop_stmt_changes. */
+/* Mark all the naked symbols in STMT for SSA renaming. */
void
mark_symbols_for_renaming (gimple stmt)
diff --git a/gcc/tree-flow-inline.h b/gcc/tree-flow-inline.h
index 6a1ae4ce7db..e6de3772c3c 100644
--- a/gcc/tree-flow-inline.h
+++ b/gcc/tree-flow-inline.h
@@ -1136,6 +1136,21 @@ ref_contains_array_ref (const_tree ref)
return false;
}
+/* Return true if REF has an VIEW_CONVERT_EXPR somewhere in it. */
+
+static inline bool
+contains_view_convert_expr_p (const_tree ref)
+{
+ while (handled_component_p (ref))
+ {
+ if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
+ return true;
+ ref = TREE_OPERAND (ref, 0);
+ }
+
+ return false;
+}
+
/* Return true, if the two ranges [POS1, SIZE1] and [POS2, SIZE2]
overlap. SIZE1 and/or SIZE2 can be (unsigned)-1 in which case the
range is open-ended. Otherwise return false. */
diff --git a/gcc/tree-flow.h b/gcc/tree-flow.h
index a02eca5275b..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);
@@ -881,13 +880,6 @@ tree vn_lookup_with_vuses (tree, VEC (tree, gc) *);
/* In tree-ssa-sink.c */
bool is_hidden_global_store (gimple);
-/* In tree-sra.c */
-void insert_edge_copies_seq (gimple_seq, basic_block);
-void sra_insert_before (gimple_stmt_iterator *, gimple_seq);
-void sra_insert_after (gimple_stmt_iterator *, gimple_seq);
-void sra_init_cache (void);
-bool sra_type_can_be_decomposed_p (tree);
-
/* In tree-loop-linear.c */
extern void linear_transform_loops (void);
extern unsigned perfect_loop_nest_depth (struct loop *);
@@ -918,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 78cb716d7ad..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);
@@ -3072,7 +3072,6 @@ estimate_num_insns (gimple stmt, eni_weights *weights)
case GIMPLE_NOP:
case GIMPLE_PHI:
case GIMPLE_RETURN:
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
case GIMPLE_PREDICT:
return 0;
@@ -3156,12 +3155,6 @@ estimate_num_insns_fn (tree fndecl, eni_weights *weights)
void
init_inline_once (void)
{
- eni_inlining_weights.call_cost = PARAM_VALUE (PARAM_INLINE_CALL_COST);
- eni_inlining_weights.target_builtin_call_cost = 1;
- eni_inlining_weights.div_mod_cost = 10;
- eni_inlining_weights.omp_cost = 40;
- eni_inlining_weights.time_based = true;
-
eni_size_weights.call_cost = 1;
eni_size_weights.target_builtin_call_cost = 1;
eni_size_weights.div_mod_cost = 1;
@@ -3429,13 +3422,6 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
/* Declare the return variable for the function. */
retvar = declare_return_variable (id, return_slot, modify_dest, &use_retvar);
- if (DECL_IS_OPERATOR_NEW (fn))
- {
- gcc_assert (TREE_CODE (retvar) == VAR_DECL
- && POINTER_TYPE_P (TREE_TYPE (retvar)));
- DECL_NO_TBAA_P (retvar) = 1;
- }
-
/* Add local vars in this inlined callee to caller. */
t_step = id->src_cfun->local_decls;
for (; t_step; t_step = TREE_CHAIN (t_step))
@@ -3459,6 +3445,13 @@ expand_call_inline (basic_block bb, gimple stmt, copy_body_data *id)
duplicate our body before altering anything. */
copy_body (id, bb->count, bb->frequency, bb, return_block);
+ /* Reset the escaped and callused solutions. */
+ if (cfun->gimple_df)
+ {
+ pt_solution_reset (&cfun->gimple_df->escaped);
+ pt_solution_reset (&cfun->gimple_df->callused);
+ }
+
/* Clean up. */
pointer_map_destroy (id->decl_map);
id->decl_map = st;
@@ -4192,7 +4185,6 @@ copy_decl_to_var (tree decl, copy_body_data *id)
TREE_READONLY (copy) = TREE_READONLY (decl);
TREE_THIS_VOLATILE (copy) = TREE_THIS_VOLATILE (decl);
DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
- DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (decl);
return copy_decl_for_dup_finish (id, decl, copy);
}
@@ -4219,7 +4211,6 @@ copy_result_decl_to_var (tree decl, copy_body_data *id)
{
TREE_ADDRESSABLE (copy) = TREE_ADDRESSABLE (decl);
DECL_GIMPLE_REG_P (copy) = DECL_GIMPLE_REG_P (decl);
- DECL_NO_TBAA_P (copy) = DECL_NO_TBAA_P (decl);
}
return copy_decl_for_dup_finish (id, decl, copy);
diff --git a/gcc/tree-mudflap.c b/gcc/tree-mudflap.c
index 0c07b97c873..5f4f5ac0b29 100644
--- a/gcc/tree-mudflap.c
+++ b/gcc/tree-mudflap.c
@@ -447,6 +447,26 @@ execute_mudflap_function_ops (void)
return 0;
}
+/* 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;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (!(e->flags & EDGE_ABNORMAL))
+ n_copies++;
+
+ 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);
+}
+
/* Create and initialize local shadow variables for the lookup cache
globals. Put their decls in the *_l globals for use by
mf_build_check_statement_for. */
diff --git a/gcc/tree-parloops.c b/gcc/tree-parloops.c
index 4e9b102973a..2ec26196bc1 100644
--- a/gcc/tree-parloops.c
+++ b/gcc/tree-parloops.c
@@ -1886,6 +1886,16 @@ parallelize_loops (void)
free_stmt_vec_info_vec ();
htab_delete (reduction_list);
+
+ /* Parallelization will cause new function calls to be inserted through
+ which local variables will escape. Reset the points-to solutions
+ for ESCAPED and CALLUSED. */
+ if (changed)
+ {
+ pt_solution_reset (&cfun->gimple_df->escaped);
+ pt_solution_reset (&cfun->gimple_df->callused);
+ }
+
return changed;
}
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index a123341920e..f300d0eea96 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -338,6 +338,7 @@ extern struct gimple_opt_pass pass_graphite_transforms;
extern struct gimple_opt_pass pass_if_conversion;
extern struct gimple_opt_pass pass_loop_distribution;
extern struct gimple_opt_pass pass_vectorize;
+extern struct gimple_opt_pass pass_slp_vectorize;
extern struct gimple_opt_pass pass_complete_unroll;
extern struct gimple_opt_pass pass_complete_unrolli;
extern struct gimple_opt_pass pass_parallelize_loops;
@@ -349,6 +350,7 @@ extern struct gimple_opt_pass pass_ccp;
extern struct gimple_opt_pass pass_phi_only_cprop;
extern struct gimple_opt_pass pass_build_ssa;
extern struct gimple_opt_pass pass_build_alias;
+extern struct gimple_opt_pass pass_build_ealias;
extern struct gimple_opt_pass pass_dominator;
extern struct gimple_opt_pass pass_dce;
extern struct gimple_opt_pass pass_dce_loop;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index d9d31eee79b..02b63654df2 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -423,6 +423,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 +575,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))
{
@@ -1544,17 +1663,6 @@ dump_generic_node (pretty_printer *buffer, tree node, int spc, int flags,
is_expr = false;
break;
- case CHANGE_DYNAMIC_TYPE_EXPR:
- pp_string (buffer, "<<<change_dynamic_type (");
- dump_generic_node (buffer, CHANGE_DYNAMIC_TYPE_NEW_TYPE (node), spc + 2,
- flags, false);
- pp_string (buffer, ") ");
- dump_generic_node (buffer, CHANGE_DYNAMIC_TYPE_LOCATION (node), spc + 2,
- flags, false);
- pp_string (buffer, ")>>>");
- is_expr = false;
- break;
-
case LABEL_EXPR:
op0 = TREE_OPERAND (node, 0);
/* If this is for break or continue, don't bother printing it. */
@@ -2013,62 +2121,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 < ");
diff --git a/gcc/tree-scalar-evolution.c b/gcc/tree-scalar-evolution.c
index b3990c6bfe1..bac6e594d8f 100644
--- a/gcc/tree-scalar-evolution.c
+++ b/gcc/tree-scalar-evolution.c
@@ -1141,11 +1141,10 @@ static t_bool
follow_ssa_edge_expr (struct loop *loop, gimple at_stmt, tree expr,
gimple halting_phi, tree *evolution_of_loop, int limit)
{
- t_bool res = t_false;
- tree rhs0, rhs1;
- tree type = TREE_TYPE (expr);
- enum tree_code code;
-
+ enum tree_code code = TREE_CODE (expr);
+ tree type = TREE_TYPE (expr), rhs0, rhs1;
+ t_bool res;
+
/* The EXPR is one of the following cases:
- an SSA_NAME,
- an INTEGER_CST,
@@ -1154,10 +1153,10 @@ follow_ssa_edge_expr (struct loop *loop, gimple at_stmt, tree expr,
- a MINUS_EXPR,
- an ASSERT_EXPR,
- other cases are not yet handled. */
- code = TREE_CODE (expr);
+
switch (code)
{
- case NOP_EXPR:
+ CASE_CONVERT:
/* This assignment is under the form "a_1 = (cast) rhs. */
res = follow_ssa_edge_expr (loop, at_stmt, TREE_OPERAND (expr, 0),
halting_phi, evolution_of_loop, limit);
@@ -1168,43 +1167,42 @@ follow_ssa_edge_expr (struct loop *loop, gimple at_stmt, tree expr,
/* This assignment is under the form "a_1 = 7". */
res = t_false;
break;
-
+
case SSA_NAME:
/* This assignment is under the form: "a_1 = b_2". */
res = follow_ssa_edge
(loop, SSA_NAME_DEF_STMT (expr), halting_phi, evolution_of_loop, limit);
break;
-
+
case POINTER_PLUS_EXPR:
case PLUS_EXPR:
case MINUS_EXPR:
/* This case is under the form "rhs0 +- rhs1". */
rhs0 = TREE_OPERAND (expr, 0);
rhs1 = TREE_OPERAND (expr, 1);
- STRIP_TYPE_NOPS (rhs0);
- STRIP_TYPE_NOPS (rhs1);
- return follow_ssa_edge_binary (loop, at_stmt, type, rhs0, code, rhs1,
- halting_phi, evolution_of_loop, limit);
+ type = TREE_TYPE (rhs0);
+ STRIP_USELESS_TYPE_CONVERSION (rhs0);
+ STRIP_USELESS_TYPE_CONVERSION (rhs1);
+ res = follow_ssa_edge_binary (loop, at_stmt, type, rhs0, code, rhs1,
+ halting_phi, evolution_of_loop, limit);
+ break;
case ASSERT_EXPR:
- {
- /* This assignment is of the form: "a_1 = ASSERT_EXPR <a_2, ...>"
- It must be handled as a copy assignment of the form a_1 = a_2. */
- tree op0 = ASSERT_EXPR_VAR (expr);
- if (TREE_CODE (op0) == SSA_NAME)
- res = follow_ssa_edge (loop, SSA_NAME_DEF_STMT (op0),
- halting_phi, evolution_of_loop, limit);
- else
- res = t_false;
- break;
- }
-
+ /* This assignment is of the form: "a_1 = ASSERT_EXPR <a_2, ...>"
+ It must be handled as a copy assignment of the form a_1 = a_2. */
+ rhs0 = ASSERT_EXPR_VAR (expr);
+ if (TREE_CODE (rhs0) == SSA_NAME)
+ res = follow_ssa_edge (loop, SSA_NAME_DEF_STMT (rhs0),
+ halting_phi, evolution_of_loop, limit);
+ else
+ res = t_false;
+ break;
default:
res = t_false;
break;
}
-
+
return res;
}
@@ -1215,34 +1213,39 @@ static t_bool
follow_ssa_edge_in_rhs (struct loop *loop, gimple stmt,
gimple halting_phi, tree *evolution_of_loop, int limit)
{
- tree type = TREE_TYPE (gimple_assign_lhs (stmt));
enum tree_code code = gimple_assign_rhs_code (stmt);
+ tree type = gimple_expr_type (stmt), rhs1, rhs2;
+ t_bool res;
- switch (get_gimple_rhs_class (code))
+ switch (code)
{
- case GIMPLE_BINARY_RHS:
- return follow_ssa_edge_binary (loop, stmt, type,
- gimple_assign_rhs1 (stmt), code,
- gimple_assign_rhs2 (stmt),
- halting_phi, evolution_of_loop, limit);
- case GIMPLE_SINGLE_RHS:
- return follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt),
- halting_phi, evolution_of_loop, limit);
- case GIMPLE_UNARY_RHS:
- if (code == NOP_EXPR)
- {
- /* This assignment is under the form "a_1 = (cast) rhs. */
- t_bool res
- = follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt),
+ CASE_CONVERT:
+ /* This assignment is under the form "a_1 = (cast) rhs. */
+ res = follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt),
+ halting_phi, evolution_of_loop, limit);
+ *evolution_of_loop = chrec_convert (type, *evolution_of_loop, stmt);
+ break;
+
+ case POINTER_PLUS_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ rhs1 = gimple_assign_rhs1 (stmt);
+ rhs2 = gimple_assign_rhs2 (stmt);
+ type = TREE_TYPE (rhs1);
+ res = follow_ssa_edge_binary (loop, stmt, type, rhs1, code, rhs2,
halting_phi, evolution_of_loop, limit);
- *evolution_of_loop = chrec_convert (type, *evolution_of_loop, stmt);
- return res;
- }
- /* FALLTHRU */
+ break;
default:
- return t_false;
+ if (get_gimple_rhs_class (code) == GIMPLE_SINGLE_RHS)
+ res = follow_ssa_edge_expr (loop, stmt, gimple_assign_rhs1 (stmt),
+ halting_phi, evolution_of_loop, limit);
+ else
+ res = t_false;
+ break;
}
+
+ return res;
}
/* Checks whether the I-th argument of a PHI comes from a backedge. */
diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c
index 626a253d152..0f689417163 100644
--- a/gcc/tree-sra.c
+++ b/gcc/tree-sra.c
@@ -236,7 +236,7 @@ is_sra_scalar_type (tree type)
instantiated, just that if we decide to break up the type into
separate pieces that it can be done. */
-bool
+static bool
sra_type_can_be_decomposed_p (tree type)
{
unsigned int cache = TYPE_UID (TYPE_MAIN_VARIANT (type)) * 2;
@@ -1267,6 +1267,26 @@ build_element_name (struct sra_elt *elt)
return XOBFINISH (&sra_obstack, char *);
}
+/* 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;
+
+ FOR_EACH_EDGE (e, ei, bb->succs)
+ if (!(e->flags & EDGE_ABNORMAL))
+ n_copies++;
+
+ 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);
+}
+
/* Instantiate an element as an independent variable. */
static void
@@ -2789,29 +2809,9 @@ generate_element_init (struct sra_elt *elt, tree init, gimple_seq *seq_p)
return ret;
}
-/* 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. */
-
-void
-insert_edge_copies_seq (gimple_seq seq, basic_block bb)
-{
- edge e;
- edge_iterator ei;
- unsigned n_copies = -1;
-
- FOR_EACH_EDGE (e, ei, bb->succs)
- if (!(e->flags & EDGE_ABNORMAL))
- n_copies++;
-
- 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);
-}
-
/* Helper function to insert LIST before GSI, and set up line number info. */
-void
+static void
sra_insert_before (gimple_stmt_iterator *gsi, gimple_seq seq)
{
gimple stmt = gsi_stmt (*gsi);
@@ -2823,7 +2823,7 @@ sra_insert_before (gimple_stmt_iterator *gsi, gimple_seq seq)
/* Similarly, but insert after GSI. Handles insertion onto edges as well. */
-void
+static void
sra_insert_after (gimple_stmt_iterator *gsi, gimple_seq seq)
{
gimple stmt = gsi_stmt (*gsi);
@@ -3601,7 +3601,7 @@ debug_sra_elt_name (struct sra_elt *elt)
fputc ('\n', stderr);
}
-void
+static void
sra_init_cache (void)
{
if (sra_type_decomp_cache)
diff --git a/gcc/tree-ssa-alias.c b/gcc/tree-ssa-alias.c
index 8982280fb2c..e68fb51f012 100644
--- a/gcc/tree-ssa-alias.c
+++ b/gcc/tree-ssa-alias.c
@@ -155,10 +155,13 @@ ptr_deref_may_alias_global_p (tree ptr)
if (!pi)
return true;
+ /* ??? This does not use TBAA to prune globals ptr may not access. */
return pt_solution_includes_global (&pi->pt);
}
-/* Return true if dereferencing PTR may alias DECL. */
+/* Return true if dereferencing PTR may alias DECL.
+ The caller is responsible for applying TBAA to see if PTR
+ may access DECL at all. */
static bool
ptr_deref_may_alias_decl_p (tree ptr, tree decl)
@@ -190,7 +193,9 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
return pt_solution_includes (&pi->pt, decl);
}
-/* Return true if dereferenced PTR1 and PTR2 may alias. */
+/* Return true if dereferenced PTR1 and PTR2 may alias.
+ The caller is responsible for applying TBAA to see if accesses
+ through PTR1 and PTR2 may conflict at all. */
static bool
ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
@@ -222,6 +227,8 @@ ptr_derefs_may_alias_p (tree ptr1, tree ptr2)
if (!pi1 || !pi2)
return true;
+ /* ??? This does not use TBAA to prune decls from the intersection
+ that not both pointers may access. */
return pt_solutions_intersect (&pi1->pt, &pi2->pt);
}
@@ -323,7 +330,14 @@ dump_alias_info (FILE *file)
dump_variable (file, var);
}
- fprintf (file, "\n\nFlow-insensitive points-to information for %s\n\n", funcname);
+ fprintf (file, "\nCall clobber information\n");
+
+ fprintf (file, "\nESCAPED");
+ dump_points_to_solution (file, &cfun->gimple_df->escaped);
+ fprintf (file, "\nCALLUSED");
+ dump_points_to_solution (file, &cfun->gimple_df->callused);
+
+ fprintf (file, "\n\nFlow-insensitive points-to information\n\n");
for (i = 1; i < num_ssa_names; i++)
{
@@ -373,37 +387,45 @@ get_ptr_info (tree t)
return pi;
}
-/* Dump points-to information for SSA_NAME PTR into FILE. */
+/* Dump the points-to set *PT into FILE. */
void
-dump_points_to_info_for (FILE *file, tree ptr)
+dump_points_to_solution (FILE *file, struct pt_solution *pt)
{
- struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
+ if (pt->anything)
+ fprintf (file, ", points-to anything");
- print_generic_expr (file, ptr, dump_flags);
+ if (pt->nonlocal)
+ fprintf (file, ", points-to non-local");
- if (pi)
+ if (pt->escaped)
+ fprintf (file, ", points-to escaped");
+
+ if (pt->null)
+ fprintf (file, ", points-to NULL");
+
+ if (pt->vars)
{
- if (pi->pt.anything)
- fprintf (file, ", points-to anything");
+ fprintf (file, ", points-to vars: ");
+ dump_decl_set (file, pt->vars);
+ if (pt->vars_contains_global)
+ fprintf (file, " (includes global vars)");
+ }
+}
- if (pi->pt.nonlocal)
- fprintf (file, ", points-to non-local");
+/* Dump points-to information for SSA_NAME PTR into FILE. */
- if (pi->pt.escaped)
- fprintf (file, ", points-to escaped");
+void
+dump_points_to_info_for (FILE *file, tree ptr)
+{
+ struct ptr_info_def *pi = SSA_NAME_PTR_INFO (ptr);
- if (pi->pt.null)
- fprintf (file, ", points-to NULL");
+ print_generic_expr (file, ptr, dump_flags);
- if (pi->pt.vars)
- {
- fprintf (file, ", points-to vars: ");
- dump_decl_set (file, pi->pt.vars);
- if (pi->pt.vars_contains_global)
- fprintf (file, " (includes global vars)");
- }
- }
+ if (pi)
+ dump_points_to_solution (file, &pi->pt);
+ else
+ fprintf (file, ", points-to anything");
fprintf (file, "\n");
}
@@ -417,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. */
@@ -653,26 +724,35 @@ 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)
+refs_may_alias_p_1 (ao_ref *ref1, ao_ref *ref2, bool tbaa_p)
{
tree base1, base2;
HOST_WIDE_INT offset1 = 0, offset2 = 0;
HOST_WIDE_INT size1 = -1, size2 = -1;
HOST_WIDE_INT max_size1 = -1, max_size2 = -1;
bool var1_p, var2_p, ind1_p, ind2_p;
-
- 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));
+ alias_set_type set;
+
+ 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);
@@ -694,35 +774,38 @@ refs_may_alias_p_1 (tree ref1, tree ref2)
base2, offset2, max_size2);
/* First defer to TBAA if possible. */
- if (flag_strict_aliasing
- && !alias_sets_conflict_p (get_alias_set (ref1), get_alias_set (ref2)))
+ if (tbaa_p
+ && flag_strict_aliasing
+ && !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. */
ind1_p = INDIRECT_REF_P (base1);
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),
- offset2, max_size2, -1,
- ref1, base1,
- offset1, max_size1, -1);
+ return indirect_ref_may_alias_decl_p (ref2->ref, TREE_OPERAND (base2, 0),
+ offset2, max_size2, set,
+ 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),
- offset1, max_size1, -1,
- ref2, base2,
- offset2, max_size2, -1);
+ return indirect_ref_may_alias_decl_p (ref1->ref, TREE_OPERAND (base1, 0),
+ offset1, max_size1, set,
+ ref2->ref, base2,
+ offset2, max_size2, set);
else if (ind1_p && ind2_p)
- return indirect_refs_may_alias_p (ref1, TREE_OPERAND (base1, 0),
- offset1, max_size1, -1,
- ref2, TREE_OPERAND (base2, 0),
- offset2, max_size2, -1);
+ return indirect_refs_may_alias_p (ref1->ref, TREE_OPERAND (base1, 0),
+ offset1, max_size1, set,
+ ref2->ref, TREE_OPERAND (base2, 0),
+ offset2, max_size2, set);
gcc_unreachable ();
}
@@ -730,7 +813,11 @@ refs_may_alias_p_1 (tree ref1, tree ref2)
bool
refs_may_alias_p (tree ref1, tree ref2)
{
- bool res = refs_may_alias_p_1 (ref1, ref2);
+ 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
@@ -738,6 +825,29 @@ refs_may_alias_p (tree ref1, tree ref2)
return res;
}
+/* Returns true if there is a anti-dependence for the STORE that
+ executes after the LOAD. */
+
+bool
+refs_anti_dependent_p (tree load, tree store)
+{
+ 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
+ STORE1 and STORE2. */
+
+bool
+refs_output_dependent_p (tree store1, tree store2)
+{
+ 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,
otherwise return false. */
@@ -865,7 +975,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;
@@ -874,7 +984,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;
@@ -915,10 +1025,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
@@ -931,34 +1044,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);
@@ -982,7 +1113,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);
}
@@ -996,7 +1127,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);
@@ -1044,11 +1175,19 @@ get_continuation_for_phi (gimple phi, tree ref, bitmap *visited)
WALKER returns non-NULL the walk stops and its result is returned.
At the end of a non-successful walk NULL is returned.
+ TRANSLATE if non-NULL is called with a pointer to REF, the virtual
+ use which definition is a statement that may clobber REF and DATA.
+ If TRANSLATE returns (void *)-1 the walk stops and NULL is returned.
+ If TRANSLATE returns non-NULL the walk stops and its result is returned.
+ If TRANSLATE returns NULL the walk continues and TRANSLATE is supposed
+ to adjust REF and *DATA to make that valid.
+
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 *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;
@@ -1071,8 +1210,22 @@ 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))
- break;
+ if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
+ {
+ if (!translate)
+ break;
+ res = (*translate) (ref, vuse, data);
+ /* Failed lookup and translation. */
+ if (res == (void *)-1)
+ {
+ res = NULL;
+ break;
+ }
+ /* Lookup succeeded. */
+ else if (res != NULL)
+ break;
+ /* Translation succeeded, continue walking. */
+ }
vuse = gimple_vuse (def_stmt);
}
}
diff --git a/gcc/tree-ssa-alias.h b/gcc/tree-ssa-alias.h
index 5f951ae1625..115d3935512 100644
--- a/gcc/tree-ssa-alias.h
+++ b/gcc/tree-ssa-alias.h
@@ -74,20 +74,57 @@ 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);
+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 *);
+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 *);
extern struct ptr_info_def *get_ptr_info (tree);
extern void dump_alias_info (FILE *);
extern void debug_alias_info (void);
+extern void dump_points_to_solution (FILE *, struct pt_solution *);
extern void dump_points_to_info_for (FILE *, tree);
extern void debug_points_to_info_for (tree);
extern void dump_alias_stats (FILE *);
diff --git a/gcc/tree-ssa-ccp.c b/gcc/tree-ssa-ccp.c
index 437d4267dd3..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)
@@ -3023,14 +3066,9 @@ optimize_stack_restore (gimple_stmt_iterator i)
return NULL_TREE;
stack_save_gsi = gsi_for_stmt (stack_save);
- push_stmt_changes (gsi_stmt_ptr (&stack_save_gsi));
rhs = build_int_cst (TREE_TYPE (gimple_call_arg (call, 0)), 0);
if (!update_call_from_tree (&stack_save_gsi, rhs))
- {
- discard_stmt_changes (gsi_stmt_ptr (&stack_save_gsi));
- return NULL_TREE;
- }
- pop_stmt_changes (gsi_stmt_ptr (&stack_save_gsi));
+ return NULL_TREE;
/* No effect, so the statement will be deleted. */
return integer_zero_node;
@@ -3252,8 +3290,6 @@ execute_fold_all_builtins (void)
}
old_stmt = stmt;
- push_stmt_changes (gsi_stmt_ptr (&i));
-
if (!update_call_from_tree (&i, result))
{
gimplify_and_update_call_from_tree (&i, result);
@@ -3261,7 +3297,7 @@ execute_fold_all_builtins (void)
}
stmt = gsi_stmt (i);
- pop_stmt_changes (gsi_stmt_ptr (&i));
+ update_stmt (stmt);
if (maybe_clean_or_replace_eh_stmt (old_stmt, stmt)
&& gimple_purge_dead_eh_edges (bb))
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-copyrename.c b/gcc/tree-ssa-copyrename.c
index 0ac02bab04c..ed221c2f3e0 100644
--- a/gcc/tree-ssa-copyrename.c
+++ b/gcc/tree-ssa-copyrename.c
@@ -233,20 +233,6 @@ copy_rename_partition_coalesce (var_map map, tree var1, tree var2, FILE *debug)
return false;
}
- /* Don't coalesce if the aliasing sets of the types are different. */
- if (POINTER_TYPE_P (TREE_TYPE (root1))
- && POINTER_TYPE_P (TREE_TYPE (root2))
- && ((get_alias_set (TREE_TYPE (TREE_TYPE (root1)))
- != get_alias_set (TREE_TYPE (TREE_TYPE (root2))))
- || (DECL_P (root1) && DECL_P (root2)
- && DECL_NO_TBAA_P (root1) != DECL_NO_TBAA_P (root2))))
- {
- if (debug)
- fprintf (debug, " : 2 different aliasing sets. No coalesce.\n");
- return false;
- }
-
-
/* Merge the two partitions. */
p3 = partition_union (map->var_partition, p1, p2);
diff --git a/gcc/tree-ssa-dce.c b/gcc/tree-ssa-dce.c
index 0c205710425..b252ece37f4 100644
--- a/gcc/tree-ssa-dce.c
+++ b/gcc/tree-ssa-dce.c
@@ -295,7 +295,6 @@ mark_stmt_if_obviously_necessary (gimple stmt, bool aggressive)
case GIMPLE_ASM:
case GIMPLE_RESX:
case GIMPLE_RETURN:
- case GIMPLE_CHANGE_DYNAMIC_TYPE:
mark_stmt_necessary (stmt, true);
return;
@@ -984,10 +983,9 @@ eliminate_unnecessary_stmts (void)
fprintf (dump_file, "\n");
}
- push_stmt_changes (gsi_stmt_ptr (&gsi));
gimple_call_set_lhs (stmt, NULL_TREE);
maybe_clean_or_replace_eh_stmt (stmt, stmt);
- pop_stmt_changes (gsi_stmt_ptr (&gsi));
+ update_stmt (stmt);
release_ssa_name (name);
}
notice_special_calls (stmt);
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index a041f0e2e27..55a13b9d012 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -134,7 +134,7 @@ static VEC(expr_hash_elt_t,heap) *avail_exprs_stack;
expressions are removed from AVAIL_EXPRS. Else we may change the
hash code for an expression and be unable to find/remove it from
AVAIL_EXPRS. */
-static VEC(gimple_p,heap) *stmts_to_rescan;
+static VEC(gimple,heap) *stmts_to_rescan;
/* Structure for entries in the expression hash table. */
@@ -626,7 +626,7 @@ tree_ssa_dominator_optimize (void)
avail_exprs = htab_create (1024, real_avail_expr_hash, avail_expr_eq, free_expr_hash_elt);
avail_exprs_stack = VEC_alloc (expr_hash_elt_t, heap, 20);
const_and_copies_stack = VEC_alloc (tree, heap, 20);
- stmts_to_rescan = VEC_alloc (gimple_p, heap, 20);
+ stmts_to_rescan = VEC_alloc (gimple, heap, 20);
need_eh_cleanup = BITMAP_ALLOC (NULL);
/* Setup callbacks for the generic dominator tree walker. */
@@ -742,7 +742,7 @@ tree_ssa_dominator_optimize (void)
VEC_free (expr_hash_elt_t, heap, avail_exprs_stack);
VEC_free (tree, heap, const_and_copies_stack);
- VEC_free (gimple_p, heap, stmts_to_rescan);
+ VEC_free (gimple, heap, stmts_to_rescan);
/* Free the value-handle array. */
threadedge_finalize_values ();
@@ -1047,17 +1047,16 @@ dom_opt_finalize_block (struct dom_walk_data *walk_data, basic_block bb)
/* If we queued any statements to rescan in this block, then
go ahead and rescan them now. */
- while (VEC_length (gimple_p, stmts_to_rescan) > 0)
+ while (VEC_length (gimple, stmts_to_rescan) > 0)
{
- gimple *stmt_p = VEC_last (gimple_p, stmts_to_rescan);
- gimple stmt = *stmt_p;
+ gimple stmt = VEC_last (gimple, stmts_to_rescan);
basic_block stmt_bb = gimple_bb (stmt);
if (stmt_bb != bb)
break;
- VEC_pop (gimple_p, stmts_to_rescan);
- pop_stmt_changes (stmt_p);
+ VEC_pop (gimple, stmts_to_rescan);
+ update_stmt (stmt);
}
}
@@ -2130,7 +2129,6 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
update_stmt_if_modified (stmt);
opt_stats.num_stmts++;
- push_stmt_changes (gsi_stmt_ptr (&si));
if (dump_file && (dump_flags & TDF_DETAILS))
{
@@ -2253,21 +2251,12 @@ optimize_stmt (struct dom_walk_data *walk_data ATTRIBUTE_UNUSED,
}
}
+ /* Queue the statement to be re-scanned after all the
+ AVAIL_EXPRS have been processed. The change buffer stack for
+ all the pushed statements will be processed when this queue
+ is emptied. */
if (may_have_exposed_new_symbols)
- {
- /* Queue the statement to be re-scanned after all the
- AVAIL_EXPRS have been processed. The change buffer stack for
- all the pushed statements will be processed when this queue
- is emptied. */
- VEC_safe_push (gimple_p, heap, stmts_to_rescan, gsi_stmt_ptr (&si));
- }
- else
- {
- /* Otherwise, just discard the recently pushed change buffer. If
- not, the STMTS_TO_RESCAN queue will get out of synch with the
- change buffer stack. */
- discard_stmt_changes (gsi_stmt_ptr (&si));
- }
+ VEC_safe_push (gimple, heap, stmts_to_rescan, gsi_stmt (si));
}
/* Search for an existing instance of STMT in the AVAIL_EXPRS table.
@@ -2565,8 +2554,6 @@ propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_name
print_gimple_stmt (dump_file, use_stmt, 0, dump_flags);
}
- push_stmt_changes (&use_stmt);
-
/* Propagate the RHS into this use of the LHS. */
FOR_EACH_IMM_USE_ON_STMT (use_p, iter)
propagate_value (use_p, rhs);
@@ -2601,7 +2588,6 @@ propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_name
bitmap_set_bit (interesting_names, SSA_NAME_VERSION (result));
}
- discard_stmt_changes (&use_stmt);
continue;
}
@@ -2618,9 +2604,8 @@ propagate_rhs_into_lhs (gimple stmt, tree lhs, tree rhs, bitmap interesting_name
fold_stmt_inplace (use_stmt);
/* Sometimes propagation can expose new operands to the
- renamer. Note this will call update_stmt at the
- appropriate time. */
- pop_stmt_changes (&use_stmt);
+ renamer. */
+ update_stmt (use_stmt);
/* Dump details. */
if (dump_file && (dump_flags & TDF_DETAILS))
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 31f2ad71640..8cf6ea12c1a 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -717,6 +717,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
tree *rhsp, *lhsp;
gimple use_stmt = gsi_stmt (*use_stmt_gsi);
enum tree_code rhs_code;
+ bool res = true;
gcc_assert (TREE_CODE (def_rhs) == ADDR_EXPR);
@@ -764,19 +765,26 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
/* Now see if the LHS node is an INDIRECT_REF using NAME. If so,
propagate the ADDR_EXPR into the use of NAME and fold the result. */
if (TREE_CODE (lhs) == INDIRECT_REF
- && TREE_OPERAND (lhs, 0) == name
- && may_propagate_address_into_dereference (def_rhs, lhs)
- && (lhsp != gimple_assign_lhs_ptr (use_stmt)
- || useless_type_conversion_p (TREE_TYPE (TREE_OPERAND (def_rhs, 0)),
- TREE_TYPE (rhs))))
+ && TREE_OPERAND (lhs, 0) == name)
{
- *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
- fold_stmt_inplace (use_stmt);
- tidy_after_forward_propagate_addr (use_stmt);
+ if (may_propagate_address_into_dereference (def_rhs, lhs)
+ && (lhsp != gimple_assign_lhs_ptr (use_stmt)
+ || useless_type_conversion_p
+ (TREE_TYPE (TREE_OPERAND (def_rhs, 0)), TREE_TYPE (rhs))))
+ {
+ *lhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
+ fold_stmt_inplace (use_stmt);
+ tidy_after_forward_propagate_addr (use_stmt);
- /* Continue propagating into the RHS if this was not the only use. */
- if (single_use_p)
- return true;
+ /* Continue propagating into the RHS if this was not the only use. */
+ if (single_use_p)
+ return true;
+ }
+ else
+ /* We can have a struct assignment dereferencing our name twice.
+ Note that we didn't propagate into the lhs to not falsely
+ claim we did when propagating into the rhs. */
+ res = false;
}
/* Strip away any outer COMPONENT_REF, ARRAY_REF or ADDR_EXPR
@@ -796,7 +804,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
*rhsp = unshare_expr (TREE_OPERAND (def_rhs, 0));
fold_stmt_inplace (use_stmt);
tidy_after_forward_propagate_addr (use_stmt);
- return true;
+ return res;
}
/* Now see if the RHS node is an INDIRECT_REF using NAME. If so,
@@ -827,7 +835,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
true, GSI_NEW_STMT);
gimple_assign_set_rhs1 (use_stmt, new_rhs);
tidy_after_forward_propagate_addr (use_stmt);
- return true;
+ return res;
}
/* If the defining rhs comes from an indirect reference, then do not
convert into a VIEW_CONVERT_EXPR. */
@@ -841,7 +849,7 @@ forward_propagate_addr_expr_1 (tree name, tree def_rhs,
*rhsp = new_rhs;
fold_stmt_inplace (use_stmt);
tidy_after_forward_propagate_addr (use_stmt);
- return true;
+ return res;
}
}
@@ -943,19 +951,17 @@ forward_propagate_addr_expr (tree name, tree rhs)
{
gimple_stmt_iterator gsi = gsi_for_stmt (use_stmt);
- push_stmt_changes (&use_stmt);
result = forward_propagate_addr_expr_1 (name, rhs, &gsi,
single_use_p);
/* If the use has moved to a different statement adjust
- the update machinery. */
+ the update machinery for the old statement too. */
if (use_stmt != gsi_stmt (gsi))
{
- pop_stmt_changes (&use_stmt);
- use_stmt = gsi_stmt (gsi);
update_stmt (use_stmt);
+ use_stmt = gsi_stmt (gsi);
}
- else
- pop_stmt_changes (&use_stmt);
+
+ update_stmt (use_stmt);
}
all &= result;
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-im.c b/gcc/tree-ssa-loop-im.c
index c9d23583587..3cdabd6bbc5 100644
--- a/gcc/tree-ssa-loop-im.c
+++ b/gcc/tree-ssa-loop-im.c
@@ -1794,6 +1794,10 @@ gen_lsm_tmp_name (tree ref)
lsm_tmp_name_add ("R");
break;
+ case INTEGER_CST:
+ /* Nothing. */
+ break;
+
default:
gcc_unreachable ();
}
diff --git a/gcc/tree-ssa-loop-ivopts.c b/gcc/tree-ssa-loop-ivopts.c
index 37865e20701..b7047e12bc9 100644
--- a/gcc/tree-ssa-loop-ivopts.c
+++ b/gcc/tree-ssa-loop-ivopts.c
@@ -5304,8 +5304,6 @@ rewrite_use_compare (struct ivopts_data *data,
static void
rewrite_use (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand)
{
- push_stmt_changes (&use->stmt);
-
switch (use->type)
{
case USE_NONLINEAR_EXPR:
@@ -5323,8 +5321,8 @@ rewrite_use (struct ivopts_data *data, struct iv_use *use, struct iv_cand *cand)
default:
gcc_unreachable ();
}
-
- pop_stmt_changes (&use->stmt);
+
+ update_stmt (use->stmt);
}
/* Rewrite the uses using the selected induction variables. */
diff --git a/gcc/tree-ssa-loop-niter.c b/gcc/tree-ssa-loop-niter.c
index 3892a43e213..18fd6b26e4a 100644
--- a/gcc/tree-ssa-loop-niter.c
+++ b/gcc/tree-ssa-loop-niter.c
@@ -534,7 +534,7 @@ inverse (tree x, tree mask)
}
/* Derives the upper bound BND on the number of executions of loop with exit
- condition S * i <> C, assuming that the loop is not infinite. If
+ condition S * i <> C, assuming that this exit is taken. If
NO_OVERFLOW is true, then the control variable of the loop does not
overflow. If NO_OVERFLOW is true or BNDS.below >= 0, then BNDS.up
contains the upper bound on the value of C. */
@@ -574,7 +574,7 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
/* Determines number of iterations of loop whose ending condition
is IV <> FINAL. TYPE is the type of the iv. The number of
- iterations is stored to NITER. NEVER_INFINITE is true if
+ iterations is stored to NITER. EXIT_MUST_BE_TAKEN is true if
we know that the exit must be taken eventually, i.e., that the IV
ever reaches the value FINAL (we derived this earlier, and possibly set
NITER->assumptions to make sure this is the case). BNDS contains the
@@ -582,7 +582,7 @@ number_of_iterations_ne_max (mpz_t bnd, bool no_overflow, tree c, tree s,
static bool
number_of_iterations_ne (tree type, affine_iv *iv, tree final,
- struct tree_niter_desc *niter, bool never_infinite,
+ struct tree_niter_desc *niter, bool exit_must_be_taken,
bounds *bnds)
{
tree niter_type = unsigned_type_for (type);
@@ -639,9 +639,9 @@ number_of_iterations_ne (tree type, affine_iv *iv, tree final,
build_int_cst (niter_type, 1), bits);
s = fold_binary_to_constant (RSHIFT_EXPR, niter_type, s, bits);
- if (!never_infinite)
+ if (!exit_must_be_taken)
{
- /* If we cannot assume that the loop is not infinite, record the
+ /* If we cannot assume that the exit is taken eventually, record the
assumptions for divisibility of c. */
assumption = fold_build2 (FLOOR_MOD_EXPR, niter_type, c, d);
assumption = fold_build2 (EQ_EXPR, boolean_type_node,
@@ -664,20 +664,21 @@ number_of_iterations_ne (tree type, affine_iv *iv, tree final,
of the final value does not overflow are recorded in NITER. If we
find the final value, we adjust DELTA and return TRUE. Otherwise
we return false. BNDS bounds the value of IV1->base - IV0->base,
- and will be updated by the same amount as DELTA. */
+ and will be updated by the same amount as DELTA. EXIT_MUST_BE_TAKEN is
+ true if we know that the exit must be taken eventually. */
static bool
number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
struct tree_niter_desc *niter,
tree *delta, tree step,
- bounds *bnds)
+ bool exit_must_be_taken, bounds *bnds)
{
tree niter_type = TREE_TYPE (step);
tree mod = fold_build2 (FLOOR_MOD_EXPR, niter_type, *delta, step);
tree tmod;
mpz_t mmod;
tree assumption = boolean_true_node, bound, noloop;
- bool ret = false;
+ bool ret = false, fv_comp_no_overflow;
tree type1 = type;
if (POINTER_TYPE_P (type))
type1 = sizetype;
@@ -692,17 +693,31 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
mpz_set_double_int (mmod, tree_to_double_int (mod), true);
mpz_neg (mmod, mmod);
+ /* If the induction variable does not overflow and the exit is taken,
+ then the computation of the final value does not overflow. This is
+ also obviously the case if the new final value is equal to the
+ current one. Finally, we postulate this for pointer type variables,
+ as the code cannot rely on the object to that the pointer points being
+ placed at the end of the address space (and more pragmatically,
+ TYPE_{MIN,MAX}_VALUE is not defined for pointers). */
+ if (integer_zerop (mod) || POINTER_TYPE_P (type))
+ fv_comp_no_overflow = true;
+ else if (!exit_must_be_taken)
+ fv_comp_no_overflow = false;
+ else
+ fv_comp_no_overflow =
+ (iv0->no_overflow && integer_nonzerop (iv0->step))
+ || (iv1->no_overflow && integer_nonzerop (iv1->step));
+
if (integer_nonzerop (iv0->step))
{
/* The final value of the iv is iv1->base + MOD, assuming that this
computation does not overflow, and that
iv0->base <= iv1->base + MOD. */
- if (!iv0->no_overflow && !integer_zerop (mod))
+ if (!fv_comp_no_overflow)
{
bound = fold_build2 (MINUS_EXPR, type1,
TYPE_MAX_VALUE (type1), tmod);
- if (POINTER_TYPE_P (type))
- bound = fold_convert (type, bound);
assumption = fold_build2 (LE_EXPR, boolean_type_node,
iv1->base, bound);
if (integer_zerop (assumption))
@@ -726,12 +741,10 @@ number_of_iterations_lt_to_ne (tree type, affine_iv *iv0, affine_iv *iv1,
/* The final value of the iv is iv0->base - MOD, assuming that this
computation does not overflow, and that
iv0->base - MOD <= iv1->base. */
- if (!iv1->no_overflow && !integer_zerop (mod))
+ if (!fv_comp_no_overflow)
{
bound = fold_build2 (PLUS_EXPR, type1,
TYPE_MIN_VALUE (type1), tmod);
- if (POINTER_TYPE_P (type))
- bound = fold_convert (type, bound);
assumption = fold_build2 (GE_EXPR, boolean_type_node,
iv0->base, bound);
if (integer_zerop (assumption))
@@ -969,13 +982,13 @@ assert_loop_rolls_lt (tree type, affine_iv *iv0, affine_iv *iv1,
/* Determines number of iterations of loop whose ending condition
is IV0 < IV1. TYPE is the type of the iv. The number of
iterations is stored to NITER. BNDS bounds the difference
- IV1->base - IV0->base. */
+ IV1->base - IV0->base. EXIT_MUST_BE_TAKEN is true if we know
+ that the exit must be taken eventually. */
static bool
number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
struct tree_niter_desc *niter,
- bool never_infinite ATTRIBUTE_UNUSED,
- bounds *bnds)
+ bool exit_must_be_taken, bounds *bnds)
{
tree niter_type = unsigned_type_for (type);
tree delta, step, s;
@@ -1034,7 +1047,7 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
transform the condition to != comparison. In particular, this will be
the case if DELTA is constant. */
if (number_of_iterations_lt_to_ne (type, iv0, iv1, niter, &delta, step,
- bnds))
+ exit_must_be_taken, bnds))
{
affine_iv zps;
@@ -1076,14 +1089,14 @@ number_of_iterations_lt (tree type, affine_iv *iv0, affine_iv *iv1,
/* Determines number of iterations of loop whose ending condition
is IV0 <= IV1. TYPE is the type of the iv. The number of
- iterations is stored to NITER. NEVER_INFINITE is true if
+ iterations is stored to NITER. EXIT_MUST_BE_TAKEN is true if
we know that this condition must eventually become false (we derived this
earlier, and possibly set NITER->assumptions to make sure this
is the case). BNDS bounds the difference IV1->base - IV0->base. */
static bool
number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
- struct tree_niter_desc *niter, bool never_infinite,
+ struct tree_niter_desc *niter, bool exit_must_be_taken,
bounds *bnds)
{
tree assumption;
@@ -1094,9 +1107,13 @@ number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
/* Say that IV0 is the control variable. Then IV0 <= IV1 iff
IV0 < IV1 + 1, assuming that IV1 is not equal to the greatest
value of the type. This we must know anyway, since if it is
- equal to this value, the loop rolls forever. */
+ equal to this value, the loop rolls forever. We do not check
+ this condition for pointer type ivs, as the code cannot rely on
+ the object to that the pointer points being placed at the end of
+ the address space (and more pragmatically, TYPE_{MIN,MAX}_VALUE is
+ not defined for pointers). */
- if (!never_infinite)
+ if (!exit_must_be_taken && !POINTER_TYPE_P (type))
{
if (integer_nonzerop (iv0->step))
assumption = fold_build2 (NE_EXPR, boolean_type_node,
@@ -1131,7 +1148,8 @@ number_of_iterations_le (tree type, affine_iv *iv0, affine_iv *iv1,
bounds_add (bnds, double_int_one, type1);
- return number_of_iterations_lt (type, iv0, iv1, niter, never_infinite, bnds);
+ return number_of_iterations_lt (type, iv0, iv1, niter, exit_must_be_taken,
+ bnds);
}
/* Dumps description of affine induction variable IV to FILE. */
@@ -1177,7 +1195,7 @@ number_of_iterations_cond (struct loop *loop,
affine_iv *iv1, struct tree_niter_desc *niter,
bool only_exit)
{
- bool never_infinite, ret;
+ bool exit_must_be_taken = false, ret;
bounds bnds;
/* The meaning of these assumptions is this:
@@ -1202,42 +1220,27 @@ number_of_iterations_cond (struct loop *loop,
code = swap_tree_comparison (code);
}
- if (!only_exit)
- {
- /* If this is not the only possible exit from the loop, the information
- that the induction variables cannot overflow as derived from
- signedness analysis cannot be relied upon. We use them e.g. in the
- following way: given loop for (i = 0; i <= n; i++), if i is
- signed, it cannot overflow, thus this loop is equivalent to
- for (i = 0; i < n + 1; i++); however, if n == MAX, but the loop
- is exited in some other way before i overflows, this transformation
- is incorrect (the new loop exits immediately). */
- iv0->no_overflow = false;
- iv1->no_overflow = false;
- }
-
if (POINTER_TYPE_P (type))
{
/* Comparison of pointers is undefined unless both iv0 and iv1 point
to the same object. If they do, the control variable cannot wrap
(as wrap around the bounds of memory will never return a pointer
that would be guaranteed to point to the same object, even if we
- avoid undefined behavior by casting to size_t and back). The
- restrictions on pointer arithmetics and comparisons of pointers
- ensure that using the no-overflow assumptions is correct in this
- case even if ONLY_EXIT is false. */
+ avoid undefined behavior by casting to size_t and back). */
iv0->no_overflow = true;
iv1->no_overflow = true;
}
- /* If the control induction variable does not overflow, the loop obviously
- cannot be infinite. */
- if (!integer_zerop (iv0->step) && iv0->no_overflow)
- never_infinite = true;
- else if (!integer_zerop (iv1->step) && iv1->no_overflow)
- never_infinite = true;
- else
- never_infinite = false;
+ /* If the control induction variable does not overflow and the only exit
+ from the loop is the one that we analyze, we know it must be taken
+ eventually. */
+ if (only_exit)
+ {
+ if (!integer_zerop (iv0->step) && iv0->no_overflow)
+ exit_must_be_taken = true;
+ else if (!integer_zerop (iv1->step) && iv1->no_overflow)
+ exit_must_be_taken = true;
+ }
/* We can handle the case when neither of the sides of the comparison is
invariant, provided that the test is NE_EXPR. This rarely occurs in
@@ -1308,16 +1311,16 @@ number_of_iterations_cond (struct loop *loop,
case NE_EXPR:
gcc_assert (integer_zerop (iv1->step));
ret = number_of_iterations_ne (type, iv0, iv1->base, niter,
- never_infinite, &bnds);
+ exit_must_be_taken, &bnds);
break;
case LT_EXPR:
- ret = number_of_iterations_lt (type, iv0, iv1, niter, never_infinite,
+ ret = number_of_iterations_lt (type, iv0, iv1, niter, exit_must_be_taken,
&bnds);
break;
case LE_EXPR:
- ret = number_of_iterations_le (type, iv0, iv1, niter, never_infinite,
+ ret = number_of_iterations_le (type, iv0, iv1, niter, exit_must_be_taken,
&bnds);
break;
diff --git a/gcc/tree-ssa-operands.c b/gcc/tree-ssa-operands.c
index 7d588f8eb96..4a8aee7c20c 100644
--- a/gcc/tree-ssa-operands.c
+++ b/gcc/tree-ssa-operands.c
@@ -147,12 +147,6 @@ static void get_expr_operands (gimple, tree *, int);
/* Number of functions with initialized ssa_operands. */
static int n_initialized = 0;
-/* Stack of statements to change. Every call to
- push_stmt_changes pushes the stmt onto the stack. Calls to
- pop_stmt_changes pop a stmt off of the stack and compute the set
- of changes for the popped statement. */
-static VEC(gimple_p,heap) *scb_stack;
-
/* Return the DECL_UID of the base variable of T. */
static inline unsigned
@@ -231,7 +225,6 @@ init_ssa_operands (void)
build_vuse = NULL_TREE;
build_vdef = NULL_TREE;
bitmap_obstack_initialize (&operands_bitmap_obstack);
- scb_stack = VEC_alloc (gimple_p, heap, 20);
}
gcc_assert (gimple_ssa_operands (cfun)->operand_memory == NULL);
@@ -257,11 +250,6 @@ fini_ssa_operands (void)
VEC_free (tree, heap, build_uses);
build_vdef = NULL_TREE;
build_vuse = NULL_TREE;
-
- /* The change buffer stack had better be empty. */
- gcc_assert (VEC_length (gimple_p, scb_stack) == 0);
- VEC_free (gimple_p, heap, scb_stack);
- scb_stack = NULL;
}
gimple_ssa_operands (cfun)->free_defs = NULL;
@@ -1009,9 +997,6 @@ get_expr_operands (gimple stmt, tree *expr_p, int flags)
return;
}
- case CHANGE_DYNAMIC_TYPE_EXPR:
- gcc_unreachable ();
-
case FUNCTION_DECL:
case LABEL_DECL:
case CONST_DECL:
@@ -1332,62 +1317,6 @@ debug_immediate_uses_for (tree var)
}
-/* Push *STMT_P on the SCB_STACK. This function is deprecated, do not
- introduce new uses of it. */
-
-void
-push_stmt_changes (gimple *stmt_p)
-{
- gimple stmt = *stmt_p;
-
- /* It makes no sense to keep track of PHI nodes. */
- if (gimple_code (stmt) == GIMPLE_PHI)
- return;
-
- VEC_safe_push (gimple_p, heap, scb_stack, stmt_p);
-}
-
-/* Pop the top stmt from SCB_STACK and act on the differences between
- what was recorded by push_stmt_changes and the current state of
- the statement. This function is deprecated, do not introduce
- new uses of it. */
-
-void
-pop_stmt_changes (gimple *stmt_p)
-{
- gimple *stmt2_p, stmt = *stmt_p;
-
- /* It makes no sense to keep track of PHI nodes. */
- if (gimple_code (stmt) == GIMPLE_PHI)
- return;
-
- stmt2_p = VEC_pop (gimple_p, scb_stack);
- gcc_assert (stmt_p == stmt2_p);
-
- /* Force an operand re-scan on the statement and mark any newly
- exposed variables. This also will mark the virtual operand
- for renaming if necessary. */
- update_stmt (stmt);
-}
-
-/* Discard the topmost stmt from SCB_STACK. This is useful
- when the caller realized that it did not actually modified the
- statement. It avoids the expensive operand re-scan.
- This function is deprecated, do not introduce new uses of it. */
-
-void
-discard_stmt_changes (gimple *stmt_p)
-{
- gimple *stmt2_p, stmt = *stmt_p;
-
- /* It makes no sense to keep track of PHI nodes. */
- if (gimple_code (stmt) == GIMPLE_PHI)
- return;
-
- stmt2_p = VEC_pop (gimple_p, scb_stack);
- gcc_assert (stmt_p == stmt2_p);
-}
-
/* Unlink STMTs virtual definition from the IL by propagating its use. */
void
diff --git a/gcc/tree-ssa-operands.h b/gcc/tree-ssa-operands.h
index 691db93bc4c..5a8e02696d4 100644
--- a/gcc/tree-ssa-operands.h
+++ b/gcc/tree-ssa-operands.h
@@ -114,10 +114,6 @@ extern void debug_decl_set (bitmap);
extern bool ssa_operands_active (void);
-extern void push_stmt_changes (gimple *);
-extern void pop_stmt_changes (gimple *);
-extern void discard_stmt_changes (gimple *);
-
extern void unlink_stmt_vdef (gimple);
enum ssa_op_iter_type {
diff --git a/gcc/tree-ssa-pre.c b/gcc/tree-ssa-pre.c
index b8d0f1b84a1..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;
@@ -2647,6 +2634,36 @@ create_component_ref_by_pieces_1 (basic_block block, vn_reference_t ref,
return folded;
}
break;
+ case TARGET_MEM_REF:
+ {
+ vn_reference_op_t nextop = VEC_index (vn_reference_op_s, ref->operands,
+ *operand);
+ pre_expr op0expr;
+ tree genop0 = NULL_TREE;
+ tree baseop = create_component_ref_by_pieces_1 (block, ref, operand,
+ stmts, domstmt);
+ if (!baseop)
+ return NULL_TREE;
+ if (currop->op0)
+ {
+ op0expr = get_or_alloc_expr_for (currop->op0);
+ genop0 = find_or_generate_expression (block, op0expr,
+ stmts, domstmt);
+ if (!genop0)
+ return NULL_TREE;
+ }
+ if (DECL_P (baseop))
+ return build6 (TARGET_MEM_REF, currop->type,
+ baseop, NULL_TREE,
+ genop0, currop->op1, currop->op2,
+ unshare_expr (nextop->op1));
+ else
+ return build6 (TARGET_MEM_REF, currop->type,
+ NULL_TREE, baseop,
+ genop0, currop->op1, currop->op2,
+ unshare_expr (nextop->op1));
+ }
+ break;
case ADDR_EXPR:
if (currop->op0)
{
@@ -2902,8 +2919,8 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
gimple_seq *stmts, gimple domstmt, tree type)
{
tree temp, name;
- tree folded, newexpr;
- gimple_seq forced_stmts;
+ tree folded;
+ gimple_seq forced_stmts = NULL;
unsigned int value_id;
gimple_stmt_iterator gsi;
tree exprtype = type ? type : get_expr_type (expr);
@@ -2975,13 +2992,16 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
default:
return NULL_TREE;
}
- folded = fold_convert (exprtype, folded);
+
+ if (!useless_type_conversion_p (exprtype, TREE_TYPE (folded)))
+ folded = fold_convert (exprtype, folded);
+
/* Force the generated expression to be a sequence of GIMPLE
statements.
We have to call unshare_expr because force_gimple_operand may
modify the tree we pass to it. */
- newexpr = force_gimple_operand (unshare_expr (folded), &forced_stmts,
- false, NULL);
+ folded = force_gimple_operand (unshare_expr (folded), &forced_stmts,
+ false, NULL);
/* If we have any intermediate expressions to the value sets, add them
to the value sets and chain them in the instruction stream. */
@@ -3025,7 +3045,7 @@ create_expression_by_pieces (basic_block block, pre_expr expr,
|| TREE_CODE (exprtype) == VECTOR_TYPE)
DECL_GIMPLE_REG_P (temp) = 1;
- newstmt = gimple_build_assign (temp, newexpr);
+ newstmt = gimple_build_assign (temp, folded);
name = make_ssa_name (temp, newstmt);
gimple_assign_set_lhs (newstmt, name);
gimple_set_plf (newstmt, NECESSARY, false);
@@ -3760,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-propagate.c b/gcc/tree-ssa-propagate.c
index 3e8d1219c80..a3a87cbf7c3 100644
--- a/gcc/tree-ssa-propagate.c
+++ b/gcc/tree-ssa-propagate.c
@@ -1109,9 +1109,6 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
continue;
}
- /* Record the state of the statement before replacements. */
- push_stmt_changes (gsi_stmt_ptr (&i));
-
/* Replace the statement with its folded version and mark it
folded. */
did_replace = false;
@@ -1172,14 +1169,9 @@ substitute_and_fold (prop_value_t *prop_value, bool use_ranges_p)
}
/* Determine what needs to be done to update the SSA form. */
- pop_stmt_changes (gsi_stmt_ptr (&i));
+ update_stmt (stmt);
something_changed = true;
}
- else
- {
- /* The statement was not modified, discard the change buffer. */
- discard_stmt_changes (gsi_stmt_ptr (&i));
- }
if (dump_file && (dump_flags & TDF_DETAILS))
{
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index aef2d956a89..763c8451798 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -488,20 +488,26 @@ copy_reference_ops_from_ref (tree ref, VEC(vn_reference_op_s, heap) **result)
if (TREE_CODE (ref) == TARGET_MEM_REF)
{
vn_reference_op_s temp;
+ tree base;
+
+ base = TMR_SYMBOL (ref) ? TMR_SYMBOL (ref) : TMR_BASE (ref);
+ if (!base)
+ base = build_int_cst (ptr_type_node, 0);
memset (&temp, 0, sizeof (temp));
/* We do not care for spurious type qualifications. */
temp.type = TYPE_MAIN_VARIANT (TREE_TYPE (ref));
temp.opcode = TREE_CODE (ref);
- temp.op0 = TMR_SYMBOL (ref) ? TMR_SYMBOL (ref) : TMR_BASE (ref);
- temp.op1 = TMR_INDEX (ref);
+ temp.op0 = TMR_INDEX (ref);
+ temp.op1 = TMR_STEP (ref);
+ temp.op2 = TMR_OFFSET (ref);
VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
memset (&temp, 0, sizeof (temp));
temp.type = NULL_TREE;
- temp.opcode = TREE_CODE (ref);
- temp.op0 = TMR_STEP (ref);
- temp.op1 = TMR_OFFSET (ref);
+ temp.opcode = TREE_CODE (base);
+ temp.op0 = base;
+ temp.op1 = TMR_ORIGINAL (ref);
VEC_safe_push (vn_reference_op_s, heap, *result, &temp);
return;
}
@@ -537,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 = TYPE_SIZE (TREE_TYPE (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:
@@ -606,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);
@@ -636,23 +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:
- *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:
@@ -661,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
@@ -911,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;
@@ -934,13 +1026,169 @@ vn_reference_lookup_2 (tree op ATTRIBUTE_UNUSED, tree vuse, void *vr_)
return NULL;
}
+/* Callback for walk_non_aliased_vuses. Tries to perform a lookup
+ from the statement defining VUSE and if not successful tries to
+ translate *REFP and VR_ through an aggregate copy at the defintion
+ of VUSE. */
+
+static void *
+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 base;
+ HOST_WIDE_INT 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. */
+ if (maxsize == -1)
+ return (void *)-1;
+
+ /* def_stmt may-defs *ref. See if we can derive a value for *ref
+ from that defintion.
+ 1) Memset. */
+ 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
+ && DECL_FUNCTION_CODE (fndecl) == BUILT_IN_MEMSET
+ && integer_zerop (gimple_call_arg (def_stmt, 1))
+ && host_integerp (gimple_call_arg (def_stmt, 2), 1)
+ && TREE_CODE (gimple_call_arg (def_stmt, 0)) == ADDR_EXPR)
+ {
+ tree ref2 = TREE_OPERAND (gimple_call_arg (def_stmt, 0), 0);
+ tree base2;
+ HOST_WIDE_INT offset2, size2, maxsize2;
+ base2 = get_ref_base_and_extent (ref2, &offset2, &size2, &maxsize2);
+ size2 = TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2)) * 8;
+ if ((unsigned HOST_WIDE_INT)size2 / 8
+ == TREE_INT_CST_LOW (gimple_call_arg (def_stmt, 2))
+ && operand_equal_p (base, base2, 0)
+ && offset2 <= offset
+ && offset2 + size2 >= offset + maxsize)
+ {
+ 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 (vr->type)
+ && gimple_assign_single_p (def_stmt)
+ && gimple_assign_rhs_code (def_stmt) == CONSTRUCTOR
+ && CONSTRUCTOR_NELTS (gimple_assign_rhs1 (def_stmt)) == 0)
+ {
+ tree base2;
+ HOST_WIDE_INT offset2, size2, maxsize2;
+ base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
+ &offset2, &size2, &maxsize2);
+ if (operand_equal_p (base, base2, 0)
+ && offset2 <= offset
+ && offset2 + size2 >= offset + maxsize)
+ {
+ 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
+ the copy kills ref. */
+ else if (gimple_assign_single_p (def_stmt)
+ && (DECL_P (gimple_assign_rhs1 (def_stmt))
+ || INDIRECT_REF_P (gimple_assign_rhs1 (def_stmt))
+ || handled_component_p (gimple_assign_rhs1 (def_stmt))))
+ {
+ tree base2;
+ HOST_WIDE_INT offset2, size2, maxsize2;
+ 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),
+ &offset2, &size2, &maxsize2);
+ if (!operand_equal_p (base, base2, 0)
+ || offset2 > offset
+ || offset2 + size2 < offset + maxsize)
+ return (void *)-1;
+
+ /* Find the common base of ref and the lhs. */
+ copy_reference_ops_from_ref (gimple_assign_lhs (def_stmt), &lhs);
+ i = VEC_length (vn_reference_op_s, vr->operands) - 1;
+ j = VEC_length (vn_reference_op_s, lhs) - 1;
+ while (j >= 0
+ && vn_reference_op_eq (VEC_index (vn_reference_op_s,
+ vr->operands, i),
+ VEC_index (vn_reference_op_s, lhs, j)))
+ {
+ i--;
+ j--;
+ }
+ /* i now points to the first additional op.
+ ??? LHS may not be completely contained in VR, one or more
+ VIEW_CONVERT_EXPRs could be in its way. We could at least
+ try handling outermost VIEW_CONVERT_EXPRs. */
+ if (j != -1)
+ return (void *)-1;
+ VEC_free (vn_reference_op_s, heap, lhs);
+
+ /* Now re-write REF to be based on the rhs of the assignment. */
+ copy_reference_ops_from_ref (gimple_assign_rhs1 (def_stmt), &rhs);
+ /* We need to pre-pend vr->operands[0..i] to rhs. */
+ if (i + 1 + VEC_length (vn_reference_op_s, rhs)
+ > VEC_length (vn_reference_op_s, vr->operands))
+ {
+ VEC (vn_reference_op_s, heap) *old = vr->operands;
+ VEC_safe_grow (vn_reference_op_s, heap, vr->operands,
+ i + 1 + VEC_length (vn_reference_op_s, rhs));
+ if (old == shared_lookup_references
+ && vr->operands != old)
+ shared_lookup_references = NULL;
+ }
+ else
+ VEC_truncate (vn_reference_op_s, vr->operands,
+ i + 1 + VEC_length (vn_reference_op_s, rhs));
+ for (j = 0; VEC_iterate (vn_reference_op_s, rhs, j, vro); ++j)
+ 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);
+
+ /* 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;
+ }
+
+ /* Bail out and stop walking. */
+ return (void *)-1;
+}
+
/* Lookup a reference operation by it's parts, in the current hash table.
Returns the resulting value number if it exists in the hash table,
NULL_TREE otherwise. VNRESULT will be filled in with the actual
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)
{
@@ -950,9 +1198,19 @@ vn_reference_lookup_pieces (tree vuse,
if (!vnresult)
vnresult = &tmp;
*vnresult = NULL;
-
+
vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
- vr1.operands = valueize_refs (operands);
+ VEC_truncate (vn_reference_op_s, shared_lookup_references, 0);
+ VEC_safe_grow (vn_reference_op_s, heap, shared_lookup_references,
+ VEC_length (vn_reference_op_s, operands));
+ memcpy (VEC_address (vn_reference_op_s, shared_lookup_references),
+ VEC_address (vn_reference_op_s, operands),
+ sizeof (vn_reference_op_s)
+ * 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);
@@ -960,12 +1218,14 @@ vn_reference_lookup_pieces (tree vuse,
&& maywalk
&& vr1.vuse)
{
- tree ref = get_ref_from_reference_ops (operands);
- if (!ref)
- return NULL_TREE;
- *vnresult =
- (vn_reference_t)walk_non_aliased_vuses (ref, vr1.vuse,
- vn_reference_lookup_2, &vr1);
+ ao_ref r;
+ if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands))
+ *vnresult =
+ (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
+ vn_reference_lookup_2,
+ vn_reference_lookup_3, &vr1);
+ if (vr1.operands != operands)
+ VEC_free (vn_reference_op_s, heap, vr1.operands);
}
if (*vnresult)
@@ -984,22 +1244,30 @@ tree
vn_reference_lookup (tree op, tree vuse, bool maywalk,
vn_reference_t *vnresult)
{
+ VEC (vn_reference_op_s, heap) *operands;
struct vn_reference_s vr1;
if (vnresult)
*vnresult = NULL;
vr1.vuse = vuse ? SSA_VAL (vuse) : NULL_TREE;
- vr1.operands = valueize_shared_reference_ops_from_ref (op);
+ 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_lookup_2, &vr1);
+ (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
+ vn_reference_lookup_2,
+ vn_reference_lookup_3, &vr1);
+ if (vr1.operands != operands)
+ VEC_free (vn_reference_op_s, heap, vr1.operands);
if (wvnresult)
{
if (vnresult)
@@ -1030,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;
@@ -1057,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)
@@ -1069,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);
@@ -1662,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)
@@ -1679,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 a27afbf3c88..ea47ec61d36 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -226,10 +226,6 @@ struct variable_info
/* True if this is a heap variable. */
unsigned int is_heap_var:1;
- /* True if we may not use TBAA to prune references to this
- variable. This is used for C++ placement new. */
- unsigned int no_tbaa_pruning : 1;
-
/* True if this field may contain pointers. */
unsigned int may_have_pointers : 1;
@@ -360,7 +356,6 @@ static varinfo_t
new_var_info (tree t, unsigned int id, const char *name)
{
varinfo_t ret = (varinfo_t) pool_alloc (variable_info_pool);
- tree var;
ret->id = id;
ret->name = name;
@@ -371,12 +366,6 @@ new_var_info (tree t, unsigned int id, const char *name)
ret->is_unknown_size_var = false;
ret->is_full_var = false;
ret->may_have_pointers = true;
- var = t;
- if (TREE_CODE (var) == SSA_NAME)
- var = SSA_NAME_VAR (var);
- ret->no_tbaa_pruning = (DECL_P (var)
- && POINTER_TYPE_P (TREE_TYPE (var))
- && DECL_NO_TBAA_P (var));
ret->solution = BITMAP_ALLOC (&pta_obstack);
ret->oldsolution = BITMAP_ALLOC (&oldpta_obstack);
ret->next = NULL;
@@ -1425,9 +1414,6 @@ unify_nodes (constraint_graph_t graph, unsigned int to, unsigned int from,
merge_graph_nodes (graph, to, from);
merge_node_constraints (graph, to, from);
- if (get_varinfo (from)->no_tbaa_pruning)
- get_varinfo (to)->no_tbaa_pruning = true;
-
/* Mark TO as changed if FROM was changed. If TO was already marked
as changed, decrease the changed count. */
@@ -3425,7 +3411,7 @@ handle_lhs_call (tree lhs, int flags, VEC(ce_s, heap) *rhsc)
static void
handle_const_call (gimple stmt, VEC(ce_s, heap) **results)
{
- struct constraint_expr rhsc, tmpc;
+ struct constraint_expr rhsc, tmpc = {SCALAR, 0, 0};
tree tmpvar = NULL_TREE;
unsigned int k;
@@ -3725,14 +3711,6 @@ find_func_aliases (gimple origt)
}
}
}
- else if (gimple_code (t) == GIMPLE_CHANGE_DYNAMIC_TYPE)
- {
- unsigned int j;
-
- get_constraint_for (gimple_cdt_location (t), &lhsc);
- for (j = 0; VEC_iterate (ce_s, lhsc, j, c); ++j)
- get_varinfo (c->var)->no_tbaa_pruning = true;
- }
stmt_escape_type = is_escape_site (t);
if (stmt_escape_type == ESCAPE_STORED_IN_GLOBAL)
@@ -4444,10 +4422,7 @@ dump_solution_for_var (FILE *file, unsigned int var)
{
fprintf (file, "%s ", get_varinfo (i)->name);
}
- fprintf (file, "}");
- if (vi->no_tbaa_pruning)
- fprintf (file, " no-tbaa-pruning");
- fprintf (file, "\n");
+ fprintf (file, "}\n");
}
}
@@ -4628,19 +4603,13 @@ shared_bitmap_add (bitmap pt_vars)
}
-/* Set bits in INTO corresponding to the variable uids in solution set FROM.
- If MEM_ALIAS_SET is not zero, we also use type based alias analysis to
- prune the points-to sets with this alias-set.
- Returns the number of pruned variables and updates the vars_contains_global
- member of *PT . */
+/* Set bits in INTO corresponding to the variable uids in solution set FROM. */
-static unsigned
-set_uids_in_ptset (bitmap into, bitmap from,
- alias_set_type mem_alias_set, struct pt_solution *pt)
+static void
+set_uids_in_ptset (bitmap into, bitmap from, struct pt_solution *pt)
{
unsigned int i;
bitmap_iterator bi;
- unsigned pruned = 0;
EXECUTE_IF_SET_IN_BITMAP (from, 0, i, bi)
{
@@ -4655,22 +4624,6 @@ set_uids_in_ptset (bitmap into, bitmap from,
|| TREE_CODE (vi->decl) == PARM_DECL
|| TREE_CODE (vi->decl) == RESULT_DECL)
{
- /* Don't type prune artificial vars or points-to sets
- for pointers that have not been dereferenced or with
- type-based pruning disabled. */
- if (!vi->is_artificial_var
- && !vi->no_tbaa_pruning
- && mem_alias_set != 0)
- {
- alias_set_type var_alias_set = get_alias_set (vi->decl);
- if (mem_alias_set != var_alias_set
- && !alias_set_subset_of (mem_alias_set, var_alias_set))
- {
- ++pruned;
- continue;
- }
- }
-
/* Add the decl to the points-to set. Note that the points-to
set contains global variables. */
bitmap_set_bit (into, DECL_UID (vi->decl));
@@ -4678,113 +4631,21 @@ set_uids_in_ptset (bitmap into, bitmap from,
pt->vars_contains_global = true;
}
}
-
- return pruned;
}
static bool have_alias_info = false;
-/* Emit a note for the pointer initialization point DEF. */
-
-static void
-emit_pointer_definition (tree ptr, bitmap visited)
-{
- gimple def = SSA_NAME_DEF_STMT (ptr);
- if (gimple_code (def) == GIMPLE_PHI)
- {
- use_operand_p argp;
- ssa_op_iter oi;
-
- FOR_EACH_PHI_ARG (argp, def, oi, SSA_OP_USE)
- {
- tree arg = USE_FROM_PTR (argp);
- if (TREE_CODE (arg) == SSA_NAME)
- {
- if (bitmap_set_bit (visited, SSA_NAME_VERSION (arg)))
- emit_pointer_definition (arg, visited);
- }
- else
- inform (0, "initialized from %qE", arg);
- }
- }
- else if (!gimple_nop_p (def))
- inform (gimple_location (def), "initialized from here");
-}
-
-/* Emit a strict aliasing warning for dereferencing the pointer PTR. */
+/* Compute the points-to solution *PT for the variable VI. */
static void
-emit_alias_warning (tree ptr)
+find_what_var_points_to (varinfo_t vi, struct pt_solution *pt)
{
- gimple use;
- imm_use_iterator ui;
- bool warned = false;
-
- FOR_EACH_IMM_USE_STMT (use, ui, ptr)
- {
- tree deref = NULL_TREE;
-
- if (gimple_has_lhs (use))
- {
- tree lhs = get_base_address (gimple_get_lhs (use));
- if (lhs
- && INDIRECT_REF_P (lhs)
- && TREE_OPERAND (lhs, 0) == ptr)
- deref = lhs;
- }
- if (gimple_assign_single_p (use))
- {
- tree rhs = get_base_address (gimple_assign_rhs1 (use));
- if (rhs
- && INDIRECT_REF_P (rhs)
- && TREE_OPERAND (rhs, 0) == ptr)
- deref = rhs;
- }
- else if (is_gimple_call (use))
- {
- unsigned i;
- for (i = 0; i < gimple_call_num_args (use); ++i)
- {
- tree op = get_base_address (gimple_call_arg (use, i));
- if (op
- && INDIRECT_REF_P (op)
- && TREE_OPERAND (op, 0) == ptr)
- deref = op;
- }
- }
- if (deref
- && !TREE_NO_WARNING (deref))
- {
- TREE_NO_WARNING (deref) = 1;
- warned |= warning_at (gimple_location (use), OPT_Wstrict_aliasing,
- "dereferencing pointer %qD does break "
- "strict-aliasing rules", SSA_NAME_VAR (ptr));
- }
- }
- if (warned)
- {
- bitmap visited = BITMAP_ALLOC (NULL);
- emit_pointer_definition (ptr, visited);
- BITMAP_FREE (visited);
- }
-}
-
-/* Compute the points-to solution *PT for the variable VI.
- Prunes the points-to set based on TBAA rules if DO_TBAA_PRUNING
- is true. Returns the number of TBAA pruned variables from the
- points-to set. */
-
-static unsigned int
-find_what_var_points_to (varinfo_t vi, struct pt_solution *pt,
- bool do_tbaa_pruning)
-{
- unsigned int i, pruned;
+ unsigned int i;
bitmap_iterator bi;
bitmap finished_solution;
bitmap result;
tree ptr = vi->decl;
- alias_set_type mem_alias_set;
memset (pt, 0, sizeof (struct pt_solution));
@@ -4821,7 +4682,7 @@ find_what_var_points_to (varinfo_t vi, struct pt_solution *pt,
/* Instead of doing extra work, simply do not create
elaborate points-to information for pt_anything pointers. */
if (pt->anything)
- return 0;
+ return;
/* Share the final set of variables when possible. */
finished_solution = BITMAP_GGC_ALLOC ();
@@ -4830,15 +4691,7 @@ find_what_var_points_to (varinfo_t vi, struct pt_solution *pt,
if (TREE_CODE (ptr) == SSA_NAME)
ptr = SSA_NAME_VAR (ptr);
- /* If the pointer decl is marked that no TBAA is to be applied,
- do not do tbaa pruning. */
- if (!do_tbaa_pruning
- || DECL_NO_TBAA_P (ptr))
- mem_alias_set = 0;
- else
- mem_alias_set = get_deref_alias_set (ptr);
- pruned = set_uids_in_ptset (finished_solution, vi->solution,
- mem_alias_set, pt);
+ set_uids_in_ptset (finished_solution, vi->solution, pt);
result = shared_bitmap_lookup (finished_solution);
if (!result)
{
@@ -4850,18 +4703,14 @@ find_what_var_points_to (varinfo_t vi, struct pt_solution *pt,
pt->vars = result;
bitmap_clear (finished_solution);
}
-
- return pruned;
}
-/* Given a pointer variable P, fill in its points-to set. Apply
- type-based pruning if IS_DEREFERENCED is true. */
+/* Given a pointer variable P, fill in its points-to set. */
static void
-find_what_p_points_to (tree p, bool is_dereferenced)
+find_what_p_points_to (tree p)
{
struct ptr_info_def *pi;
- unsigned int pruned;
tree lookup_p = p;
varinfo_t vi;
@@ -4877,23 +4726,7 @@ find_what_p_points_to (tree p, bool is_dereferenced)
return;
pi = get_ptr_info (p);
- pruned = find_what_var_points_to (vi, &pi->pt, is_dereferenced);
-
- if (!(pi->pt.anything || pi->pt.nonlocal || pi->pt.escaped)
- && bitmap_empty_p (pi->pt.vars)
- && pruned > 0
- && is_dereferenced
- && warn_strict_aliasing > 0
- && !SSA_NAME_IS_DEFAULT_DEF (p))
- {
- if (dump_file && dump_flags & TDF_DETAILS)
- {
- fprintf (dump_file, "alias warning for ");
- print_generic_expr (dump_file, p, 0);
- fprintf (dump_file, "\n");
- }
- emit_alias_warning (p);
- }
+ find_what_var_points_to (vi, &pi->pt);
}
@@ -5372,139 +5205,6 @@ remove_preds_and_fake_succs (constraint_graph_t graph)
bitmap_obstack_release (&predbitmap_obstack);
}
-/* Compute the set of variables we can't TBAA prune. */
-
-static void
-compute_tbaa_pruning (void)
-{
- unsigned int size = VEC_length (varinfo_t, varmap);
- unsigned int i;
- bool any;
-
- changed_count = 0;
- changed = sbitmap_alloc (size);
- sbitmap_zero (changed);
-
- /* Mark all initial no_tbaa_pruning nodes as changed. */
- any = false;
- for (i = 0; i < size; ++i)
- {
- varinfo_t ivi = get_varinfo (i);
-
- if (find (i) == i && ivi->no_tbaa_pruning)
- {
- any = true;
- if ((graph->succs[i] && !bitmap_empty_p (graph->succs[i]))
- || VEC_length (constraint_t, graph->complex[i]) > 0)
- {
- SET_BIT (changed, i);
- ++changed_count;
- }
- }
- }
-
- while (changed_count > 0)
- {
- struct topo_info *ti = init_topo_info ();
- ++stats.iterations;
-
- compute_topo_order (graph, ti);
-
- while (VEC_length (unsigned, ti->topo_order) != 0)
- {
- bitmap_iterator bi;
-
- i = VEC_pop (unsigned, ti->topo_order);
-
- /* If this variable is not a representative, skip it. */
- if (find (i) != i)
- continue;
-
- /* If the node has changed, we need to process the complex
- constraints and outgoing edges again. */
- if (TEST_BIT (changed, i))
- {
- unsigned int j;
- constraint_t c;
- VEC(constraint_t,heap) *complex = graph->complex[i];
-
- RESET_BIT (changed, i);
- --changed_count;
-
- /* Process the complex copy constraints. */
- for (j = 0; VEC_iterate (constraint_t, complex, j, c); ++j)
- {
- if (c->lhs.type == SCALAR && c->rhs.type == SCALAR)
- {
- varinfo_t lhsvi = get_varinfo (find (c->lhs.var));
-
- if (!lhsvi->no_tbaa_pruning)
- {
- lhsvi->no_tbaa_pruning = true;
- if (!TEST_BIT (changed, lhsvi->id))
- {
- SET_BIT (changed, lhsvi->id);
- ++changed_count;
- }
- }
- }
- }
-
- /* Propagate to all successors. */
- EXECUTE_IF_IN_NONNULL_BITMAP (graph->succs[i], 0, j, bi)
- {
- unsigned int to = find (j);
- varinfo_t tovi = get_varinfo (to);
-
- /* Don't propagate to ourselves. */
- if (to == i)
- continue;
-
- if (!tovi->no_tbaa_pruning)
- {
- tovi->no_tbaa_pruning = true;
- if (!TEST_BIT (changed, to))
- {
- SET_BIT (changed, to);
- ++changed_count;
- }
- }
- }
- }
- }
-
- free_topo_info (ti);
- }
-
- sbitmap_free (changed);
-
- if (any)
- {
- for (i = 0; i < size; ++i)
- {
- varinfo_t ivi = get_varinfo (i);
- varinfo_t ivip = get_varinfo (find (i));
-
- if (ivip->no_tbaa_pruning)
- {
- tree var = ivi->decl;
-
- if (TREE_CODE (var) == SSA_NAME)
- var = SSA_NAME_VAR (var);
-
- if (POINTER_TYPE_P (TREE_TYPE (var)))
- {
- DECL_NO_TBAA_P (var) = 1;
-
- /* Tell the RTL layer that this pointer can alias
- anything. */
- DECL_POINTER_ALIAS_SET (var) = 0;
- }
- }
- }
- }
-}
-
/* Initialize the heapvar for statement mapping. */
static void
@@ -5534,7 +5234,6 @@ compute_points_to_sets (void)
struct scc_info *si;
basic_block bb;
unsigned i;
- sbitmap dereferenced_ptrs;
timevar_push (TV_TREE_PTA);
@@ -5543,11 +5242,6 @@ compute_points_to_sets (void)
intra_create_variable_infos ();
- /* A bitmap of SSA_NAME pointers that are dereferenced. This is
- used to track which points-to sets may be TBAA pruned. */
- dereferenced_ptrs = sbitmap_alloc (num_ssa_names);
- sbitmap_zero (dereferenced_ptrs);
-
/* Now walk all statements and derive aliases. */
FOR_EACH_BB (bb)
{
@@ -5564,31 +5258,11 @@ compute_points_to_sets (void)
for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
{
gimple stmt = gsi_stmt (gsi);
- use_operand_p use_p;
- ssa_op_iter iter;
-
- /* Mark dereferenced pointers. This is used by TBAA pruning
- of the points-to sets and the alias warning machinery. */
- FOR_EACH_SSA_USE_OPERAND (use_p, stmt, iter, SSA_OP_USE)
- {
- unsigned num_uses, num_loads, num_stores;
- tree op = USE_FROM_PTR (use_p);
-
- if (!POINTER_TYPE_P (TREE_TYPE (op)))
- continue;
-
- /* Determine whether OP is a dereferenced pointer. */
- count_uses_and_derefs (op, stmt,
- &num_uses, &num_loads, &num_stores);
- if (num_loads + num_stores > 0)
- SET_BIT (dereferenced_ptrs, SSA_NAME_VERSION (op));
- }
find_func_aliases (stmt);
}
}
-
if (dump_file)
{
fprintf (dump_file, "Points-to analysis\n\nConstraints:\n\n");
@@ -5642,15 +5316,13 @@ compute_points_to_sets (void)
solve_graph (graph);
- compute_tbaa_pruning ();
-
if (dump_file)
dump_sa_points_to_info (dump_file);
/* Compute the points-to sets for ESCAPED and CALLUSED used for
call-clobber analysis. */
- find_what_var_points_to (var_escaped, &cfun->gimple_df->escaped, false);
- find_what_var_points_to (var_callused, &cfun->gimple_df->callused, false);
+ find_what_var_points_to (var_escaped, &cfun->gimple_df->escaped);
+ find_what_var_points_to (var_callused, &cfun->gimple_df->callused);
/* Make sure the ESCAPED solution (which is used as placeholder in
other solutions) does not reference itself. This simplifies
@@ -5663,9 +5335,8 @@ compute_points_to_sets (void)
tree ptr = ssa_name (i);
if (ptr
&& POINTER_TYPE_P (TREE_TYPE (ptr)))
- find_what_p_points_to (ptr, TEST_BIT (dereferenced_ptrs, i));
+ find_what_p_points_to (ptr);
}
- sbitmap_free (dereferenced_ptrs);
timevar_pop (TV_TREE_PTA);
@@ -5765,6 +5436,28 @@ struct gimple_opt_pass pass_build_alias =
}
};
+/* A dummy pass to cause points-to information to be computed via
+ TODO_rebuild_alias. */
+
+struct gimple_opt_pass pass_build_ealias =
+{
+ {
+ GIMPLE_PASS,
+ "ealias", /* name */
+ gate_tree_pta, /* gate */
+ NULL, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_NONE, /* tv_id */
+ PROP_cfg | PROP_ssa, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_rebuild_alias | TODO_dump_func /* todo_flags_finish */
+ }
+};
+
/* Return true if we should execute IPA PTA. */
static bool
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 443ecd04088..0116ddf723f 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -363,7 +363,7 @@ vect_check_interleaving (struct data_reference *dra,
and DRB is accessed before DRA. */
diff_mod_size = (init_a - init_b) % type_size_a;
- if ((init_a - init_b) > step)
+ if (step && (init_a - init_b) > step)
return false;
if (diff_mod_size == 0)
@@ -385,7 +385,7 @@ vect_check_interleaving (struct data_reference *dra,
interleaving, and DRA is accessed before DRB. */
diff_mod_size = (init_b - init_a) % type_size_a;
- if ((init_b - init_a) > step)
+ if (step && (init_b - init_a) > step)
return false;
if (diff_mod_size == 0)
@@ -479,6 +479,7 @@ vect_mark_for_runtime_alias_test (ddr_p ddr, loop_vec_info loop_vinfo)
return true;
}
+
/* Function vect_analyze_data_ref_dependence.
Return TRUE if there (might) exist a dependence between a memory-reference
@@ -490,8 +491,8 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
loop_vec_info loop_vinfo)
{
unsigned int i;
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- int vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ struct loop *loop = NULL;
+ int vectorization_factor = 0;
struct data_reference *dra = DDR_A (ddr);
struct data_reference *drb = DDR_B (ddr);
stmt_vec_info stmtinfo_a = vinfo_for_stmt (DR_STMT (dra));
@@ -508,23 +509,68 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
return false;
}
- if ((DR_IS_READ (dra) && DR_IS_READ (drb)) || dra == drb)
+ if (loop_vinfo)
+ {
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
+ vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ }
+
+ if ((DR_IS_READ (dra) && DR_IS_READ (drb) && loop_vinfo) || dra == drb)
return false;
if (DDR_ARE_DEPENDENT (ddr) == chrec_dont_know)
{
+ if (loop_vinfo)
+ {
+ if (vect_print_dump_info (REPORT_DR_DETAILS))
+ {
+ fprintf (vect_dump, "versioning for alias required: "
+ "can't determine dependence between ");
+ print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
+ fprintf (vect_dump, " and ");
+ print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
+ }
+
+ /* Add to list of ddrs that need to be tested at run-time. */
+ return !vect_mark_for_runtime_alias_test (ddr, loop_vinfo);
+ }
+
+ /* When vectorizing a basic block unknown depnedence can still mean
+ strided access. */
+ if (vect_check_interleaving (dra, drb))
+ return false;
+
if (vect_print_dump_info (REPORT_DR_DETAILS))
{
- fprintf (vect_dump,
- "versioning for alias required: can't determine dependence between ");
+ fprintf (vect_dump, "can't determine dependence between ");
print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
fprintf (vect_dump, " and ");
print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
}
- /* Add to list of ddrs that need to be tested at run-time. */
- return !vect_mark_for_runtime_alias_test (ddr, loop_vinfo);
+
+ return true;
}
+ /* Versioning for alias is not yet supported for basic block SLP, and
+ dependence distance is unapplicable, hence, in case of known data
+ dependence, basic block vectorization is impossible for now. */
+ if (!loop_vinfo)
+ {
+ if (dra != drb && vect_check_interleaving (dra, drb))
+ return false;
+
+ if (vect_print_dump_info (REPORT_DR_DETAILS))
+ {
+ fprintf (vect_dump, "determined dependence between ");
+ print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
+ fprintf (vect_dump, " and ");
+ print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
+ }
+
+ return true;
+ }
+
+ /* Loop-based vectorization and known data dependence. */
if (DDR_NUM_DIST_VECTS (ddr) == 0)
{
if (vect_print_dump_info (REPORT_DR_DETAILS))
@@ -589,9 +635,8 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
{
- fprintf (vect_dump,
- "not vectorized, possible dependence "
- "between data-refs ");
+ fprintf (vect_dump, "not vectorized, possible dependence "
+ "between data-refs ");
print_generic_expr (vect_dump, DR_REF (dra), TDF_SLIM);
fprintf (vect_dump, " and ");
print_generic_expr (vect_dump, DR_REF (drb), TDF_SLIM);
@@ -609,15 +654,21 @@ vect_analyze_data_ref_dependence (struct data_dependence_relation *ddr,
exist any data dependences between them. */
bool
-vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo)
+vect_analyze_data_ref_dependences (loop_vec_info loop_vinfo,
+ bb_vec_info bb_vinfo)
{
unsigned int i;
- VEC (ddr_p, heap) * ddrs = LOOP_VINFO_DDRS (loop_vinfo);
+ VEC (ddr_p, heap) *ddrs = NULL;
struct data_dependence_relation *ddr;
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vect_analyze_dependences ===");
+ if (loop_vinfo)
+ ddrs = LOOP_VINFO_DDRS (loop_vinfo);
+ else
+ ddrs = BB_VINFO_DDRS (bb_vinfo);
+
for (i = 0; VEC_iterate (ddr_p, ddrs, i, ddr); i++)
if (vect_analyze_data_ref_dependence (ddr, loop_vinfo))
return false;
@@ -644,7 +695,7 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
gimple stmt = DR_STMT (dr);
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ struct loop *loop = NULL;
tree ref = DR_REF (dr);
tree vectype;
tree base, base_addr;
@@ -655,6 +706,9 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "vect_compute_data_ref_alignment:");
+ if (loop_vinfo)
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
+
/* Initialize misalignment to unknown. */
SET_DR_MISALIGNMENT (dr, -1);
@@ -669,7 +723,7 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
stays the same throughout the execution of the inner-loop, which is why
we have to check that the stride of the dataref in the inner-loop evenly
divides by the vector size. */
- if (nested_in_vect_loop_p (loop, stmt))
+ if (loop && nested_in_vect_loop_p (loop, stmt))
{
tree step = DR_STEP (dr);
HOST_WIDE_INT dr_step = TREE_INT_CST_LOW (step);
@@ -773,12 +827,18 @@ vect_compute_data_ref_alignment (struct data_reference *dr)
Return FALSE if a data reference is found that cannot be vectorized. */
static bool
-vect_compute_data_refs_alignment (loop_vec_info loop_vinfo)
+vect_compute_data_refs_alignment (loop_vec_info loop_vinfo,
+ bb_vec_info bb_vinfo)
{
- VEC (data_reference_p, heap) *datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
+ VEC (data_reference_p, heap) *datarefs;
struct data_reference *dr;
unsigned int i;
+ if (loop_vinfo)
+ datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
+ else
+ datarefs = BB_VINFO_DATAREFS (bb_vinfo);
+
for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
if (!vect_compute_data_ref_alignment (dr))
return false;
@@ -850,14 +910,19 @@ vect_update_misalignment_for_peel (struct data_reference *dr,
Return TRUE if all data references in the loop can be
handled with respect to alignment. */
-static bool
-vect_verify_datarefs_alignment (loop_vec_info loop_vinfo)
+bool
+vect_verify_datarefs_alignment (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
{
- VEC (data_reference_p, heap) *datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
+ VEC (data_reference_p, heap) *datarefs;
struct data_reference *dr;
enum dr_alignment_support supportable_dr_alignment;
unsigned int i;
+ if (loop_vinfo)
+ datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
+ else
+ datarefs = BB_VINFO_DATAREFS (bb_vinfo);
+
for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
{
gimple stmt = DR_STMT (dr);
@@ -1223,7 +1288,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "Peeling for alignment will be applied.");
- stat = vect_verify_datarefs_alignment (loop_vinfo);
+ stat = vect_verify_datarefs_alignment (loop_vinfo, NULL);
gcc_assert (stat);
return stat;
}
@@ -1331,7 +1396,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
/* Peeling and versioning can't be done together at this time. */
gcc_assert (! (do_peeling && do_versioning));
- stat = vect_verify_datarefs_alignment (loop_vinfo);
+ stat = vect_verify_datarefs_alignment (loop_vinfo, NULL);
gcc_assert (stat);
return stat;
}
@@ -1339,7 +1404,7 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
/* This point is reached if neither peeling nor versioning is being done. */
gcc_assert (! (do_peeling || do_versioning));
- stat = vect_verify_datarefs_alignment (loop_vinfo);
+ stat = vect_verify_datarefs_alignment (loop_vinfo, NULL);
return stat;
}
@@ -1350,12 +1415,13 @@ vect_enhance_data_refs_alignment (loop_vec_info loop_vinfo)
Return FALSE if a data reference is found that cannot be vectorized. */
bool
-vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo)
+vect_analyze_data_refs_alignment (loop_vec_info loop_vinfo,
+ bb_vec_info bb_vinfo)
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vect_analyze_data_refs_alignment ===");
- if (!vect_compute_data_refs_alignment (loop_vinfo))
+ if (!vect_compute_data_refs_alignment (loop_vinfo, bb_vinfo))
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
fprintf (vect_dump,
@@ -1381,6 +1447,7 @@ vect_analyze_group_access (struct data_reference *dr)
gimple stmt = DR_STMT (dr);
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
HOST_WIDE_INT dr_step = TREE_INT_CST_LOW (step);
HOST_WIDE_INT stride;
bool slp_impossible = false;
@@ -1406,8 +1473,7 @@ vect_analyze_group_access (struct data_reference *dr)
DR_GROUP_SIZE (vinfo_for_stmt (stmt)) = stride;
if (vect_print_dump_info (REPORT_DR_DETAILS))
{
- fprintf (vect_dump, "Detected single element interleaving %d ",
- DR_GROUP_SIZE (vinfo_for_stmt (stmt)));
+ fprintf (vect_dump, "Detected single element interleaving ");
print_generic_expr (vect_dump, DR_REF (dr), TDF_SLIM);
fprintf (vect_dump, " step ");
print_generic_expr (vect_dump, step, TDF_SLIM);
@@ -1508,8 +1574,8 @@ vect_analyze_group_access (struct data_reference *dr)
the type to get COUNT_IN_BYTES. */
count_in_bytes = type_size * count;
- /* Check that the size of the interleaving (including gaps) is not greater
- than STEP. */
+ /* Check that the size of the interleaving (including gaps) is not
+ greater than STEP. */
if (dr_step && dr_step < count_in_bytes + gaps * type_size)
{
if (vect_print_dump_info (REPORT_DETAILS))
@@ -1522,7 +1588,7 @@ vect_analyze_group_access (struct data_reference *dr)
/* Check that the size of the interleaving is equal to STEP for stores,
i.e., that there are no gaps. */
- if (dr_step != count_in_bytes)
+ if (dr_step && dr_step != count_in_bytes)
{
if (DR_IS_READ (dr))
{
@@ -1541,7 +1607,7 @@ vect_analyze_group_access (struct data_reference *dr)
}
/* Check that STEP is a multiple of type size. */
- if ((dr_step % type_size) != 0)
+ if (dr_step && (dr_step % type_size) != 0)
{
if (vect_print_dump_info (REPORT_DETAILS))
{
@@ -1566,6 +1632,10 @@ vect_analyze_group_access (struct data_reference *dr)
if (slp_impossible)
return false;
}
+
+ if (stride == 0)
+ stride = count;
+
DR_GROUP_SIZE (vinfo_for_stmt (stmt)) = stride;
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "Detected interleaving of size %d", (int)stride);
@@ -1573,7 +1643,14 @@ vect_analyze_group_access (struct data_reference *dr)
/* SLP: create an SLP data structure for every interleaving group of
stores for further analysis in vect_analyse_slp. */
if (!DR_IS_READ (dr) && !slp_impossible)
- VEC_safe_push (gimple, heap, LOOP_VINFO_STRIDED_STORES (loop_vinfo), stmt);
+ {
+ if (loop_vinfo)
+ VEC_safe_push (gimple, heap, LOOP_VINFO_STRIDED_STORES (loop_vinfo),
+ stmt);
+ if (bb_vinfo)
+ VEC_safe_push (gimple, heap, BB_VINFO_STRIDED_STORES (bb_vinfo),
+ stmt);
+ }
}
return true;
@@ -1592,21 +1669,24 @@ vect_analyze_data_ref_access (struct data_reference *dr)
gimple stmt = DR_STMT (dr);
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ struct loop *loop = NULL;
HOST_WIDE_INT dr_step = TREE_INT_CST_LOW (step);
- if (!step)
+ if (loop_vinfo)
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
+
+ if (loop_vinfo && !step)
{
if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "bad data-ref access");
+ fprintf (vect_dump, "bad data-ref access in loop");
return false;
}
- /* Don't allow invariant accesses. */
- if (dr_step == 0)
+ /* Don't allow invariant accesses in loops. */
+ if (loop_vinfo && dr_step == 0)
return false;
- if (nested_in_vect_loop_p (loop, stmt))
+ if (loop && nested_in_vect_loop_p (loop, stmt))
{
/* Interleaved accesses are not yet supported within outer-loop
vectorization for references in the inner-loop. */
@@ -1635,7 +1715,7 @@ vect_analyze_data_ref_access (struct data_reference *dr)
return true;
}
- if (nested_in_vect_loop_p (loop, stmt))
+ if (loop && nested_in_vect_loop_p (loop, stmt))
{
if (vect_print_dump_info (REPORT_ALIGNMENT))
fprintf (vect_dump, "strided access in outer loop.");
@@ -1657,15 +1737,20 @@ vect_analyze_data_ref_access (struct data_reference *dr)
FORNOW: handle only arrays and pointer accesses. */
bool
-vect_analyze_data_ref_accesses (loop_vec_info loop_vinfo)
+vect_analyze_data_ref_accesses (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
{
unsigned int i;
- VEC (data_reference_p, heap) *datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
+ VEC (data_reference_p, heap) *datarefs;
struct data_reference *dr;
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vect_analyze_data_ref_accesses ===");
+ if (loop_vinfo)
+ datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
+ else
+ datarefs = BB_VINFO_DATAREFS (bb_vinfo);
+
for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
if (!vect_analyze_data_ref_access (dr))
{
@@ -1752,12 +1837,13 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
/* Function vect_analyze_data_refs.
- Find all the data references in the loop.
+ Find all the data references in the loop or basic block.
The general structure of the analysis of data refs in the vectorizer is as
follows:
- 1- vect_analyze_data_refs(loop): call compute_data_dependences_for_loop to
- find and analyze all data-refs in the loop and their dependences.
+ 1- vect_analyze_data_refs(loop/bb): call
+ compute_data_dependences_for_loop/bb to find and analyze all data-refs
+ in the loop/bb and their dependences.
2- vect_analyze_dependences(): apply dependence testing using ddrs.
3- vect_analyze_drs_alignment(): check that ref_stmt.alignment is ok.
4- vect_analyze_drs_access(): check that ref_stmt.step is ok.
@@ -1765,9 +1851,10 @@ vect_prune_runtime_alias_test_list (loop_vec_info loop_vinfo)
*/
bool
-vect_analyze_data_refs (loop_vec_info loop_vinfo)
+vect_analyze_data_refs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
{
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ struct loop *loop = NULL;
+ basic_block bb = NULL;
unsigned int i;
VEC (data_reference_p, heap) *datarefs;
struct data_reference *dr;
@@ -1775,14 +1862,26 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== vect_analyze_data_refs ===\n");
-
- compute_data_dependences_for_loop (loop, true,
- &LOOP_VINFO_DATAREFS (loop_vinfo),
- &LOOP_VINFO_DDRS (loop_vinfo));
+
+ if (loop_vinfo)
+ {
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
+ compute_data_dependences_for_loop (loop, true,
+ &LOOP_VINFO_DATAREFS (loop_vinfo),
+ &LOOP_VINFO_DDRS (loop_vinfo));
+ datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
+ }
+ else
+ {
+ bb = BB_VINFO_BB (bb_vinfo);
+ compute_data_dependences_for_bb (bb, true,
+ &BB_VINFO_DATAREFS (bb_vinfo),
+ &BB_VINFO_DDRS (bb_vinfo));
+ datarefs = BB_VINFO_DATAREFS (bb_vinfo);
+ }
/* Go through the data-refs, check that the analysis succeeded. Update pointer
from stmt_vec_info struct to DR and vectype. */
- datarefs = LOOP_VINFO_DATAREFS (loop_vinfo);
for (i = 0; VEC_iterate (data_reference_p, datarefs, i, dr); i++)
{
@@ -1834,7 +1933,7 @@ vect_analyze_data_refs (loop_vec_info loop_vinfo)
inner-most enclosing loop). We do that by building a reference to the
first location accessed by the inner-loop, and analyze it relative to
the outer-loop. */
- if (nested_in_vect_loop_p (loop, stmt))
+ if (loop && nested_in_vect_loop_p (loop, stmt))
{
tree outer_step, outer_base, outer_init;
HOST_WIDE_INT pbitsize, pbitpos;
@@ -2053,7 +2152,6 @@ vect_create_addr_base_for_vector_ref (gimple stmt,
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
- struct loop *containing_loop = (gimple_bb (stmt))->loop_father;
tree data_ref_base = unshare_expr (DR_BASE_ADDRESS (dr));
tree base_name;
tree data_ref_base_var;
@@ -2065,22 +2163,28 @@ vect_create_addr_base_for_vector_ref (gimple stmt,
tree init = unshare_expr (DR_INIT (dr));
tree vect_ptr_type;
tree step = TYPE_SIZE_UNIT (TREE_TYPE (DR_REF (dr)));
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- gcc_assert (loop);
- if (loop != containing_loop)
+ if (loop_vinfo && loop && loop != (gimple_bb (stmt))->loop_father)
{
- loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ struct loop *outer_loop = LOOP_VINFO_LOOP (loop_vinfo);
- gcc_assert (nested_in_vect_loop_p (loop, stmt));
+ gcc_assert (nested_in_vect_loop_p (outer_loop, stmt));
data_ref_base = unshare_expr (STMT_VINFO_DR_BASE_ADDRESS (stmt_info));
base_offset = unshare_expr (STMT_VINFO_DR_OFFSET (stmt_info));
init = unshare_expr (STMT_VINFO_DR_INIT (stmt_info));
}
- /* Create data_ref_base */
- base_name = build_fold_indirect_ref (data_ref_base);
+ if (loop_vinfo)
+ base_name = build_fold_indirect_ref (data_ref_base);
+ else
+ {
+ base_offset = ssize_int (0);
+ init = ssize_int (0);
+ base_name = build_fold_indirect_ref (unshare_expr (DR_REF (dr)));
+ }
+
data_ref_base_var = create_tmp_var (TREE_TYPE (data_ref_base), "batmp");
add_referenced_var (data_ref_base_var);
data_ref_base = force_gimple_operand (data_ref_base, &seq, true,
@@ -2110,15 +2214,24 @@ vect_create_addr_base_for_vector_ref (gimple stmt,
}
/* base + base_offset */
- addr_base = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (data_ref_base),
- data_ref_base, base_offset);
-
+ if (loop_vinfo)
+ addr_base = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (data_ref_base),
+ data_ref_base, base_offset);
+ else
+ {
+ if (TREE_CODE (DR_REF (dr)) == INDIRECT_REF)
+ addr_base = unshare_expr (TREE_OPERAND (DR_REF (dr), 0));
+ else
+ addr_base = build1 (ADDR_EXPR,
+ build_pointer_type (TREE_TYPE (DR_REF (dr))),
+ unshare_expr (DR_REF (dr)));
+ }
+
vect_ptr_type = build_pointer_type (STMT_VINFO_VECTYPE (stmt_info));
vec_stmt = fold_convert (vect_ptr_type, addr_base);
addr_expr = vect_get_new_vect_var (vect_ptr_type, vect_pointer_var,
get_name (base_name));
-
add_referenced_var (addr_expr);
vec_stmt = force_gimple_operand (vec_stmt, &seq, false, addr_expr);
gimple_seq_add_seq (new_stmt_list, seq);
@@ -2186,16 +2299,16 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
tree base_name;
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
- bool nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
- struct loop *containing_loop = (gimple_bb (stmt))->loop_father;
+ struct loop *loop = NULL;
+ bool nested_in_vect_loop = false;
+ struct loop *containing_loop = NULL;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
tree vect_ptr_type;
tree vect_ptr;
tree new_temp;
gimple vec_stmt;
gimple_seq new_stmt_list = NULL;
- edge pe;
+ edge pe = NULL;
basic_block new_bb;
tree vect_ptr_init;
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info);
@@ -2205,7 +2318,23 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
tree indx_before_incr, indx_after_incr;
gimple incr;
tree step;
-
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+ gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
+
+ if (loop_vinfo)
+ {
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
+ nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
+ containing_loop = (gimple_bb (stmt))->loop_father;
+ pe = loop_preheader_edge (loop);
+ }
+ else
+ {
+ gcc_assert (bb_vinfo);
+ only_init = true;
+ *ptr_incr = NULL;
+ }
+
/* Check the step (evolution) of the load in LOOP, and record
whether it's invariant. */
if (nested_in_vect_loop)
@@ -2305,11 +2434,15 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
new_temp = vect_create_addr_base_for_vector_ref (stmt, &new_stmt_list,
offset, loop);
- pe = loop_preheader_edge (loop);
if (new_stmt_list)
{
- new_bb = gsi_insert_seq_on_edge_immediate (pe, new_stmt_list);
- gcc_assert (!new_bb);
+ if (pe)
+ {
+ new_bb = gsi_insert_seq_on_edge_immediate (pe, new_stmt_list);
+ gcc_assert (!new_bb);
+ }
+ else
+ gsi_insert_seq_before (&gsi, new_stmt_list, GSI_SAME_STMT);
}
*initial_address = new_temp;
@@ -2319,16 +2452,21 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
fold_convert (vect_ptr_type, new_temp));
vect_ptr_init = make_ssa_name (vect_ptr, vec_stmt);
gimple_assign_set_lhs (vec_stmt, vect_ptr_init);
- new_bb = gsi_insert_on_edge_immediate (pe, vec_stmt);
- gcc_assert (!new_bb);
-
+ if (pe)
+ {
+ new_bb = gsi_insert_on_edge_immediate (pe, vec_stmt);
+ gcc_assert (!new_bb);
+ }
+ else
+ gsi_insert_before (&gsi, vec_stmt, GSI_SAME_STMT);
/** (4) Handle the updating of the vector-pointer inside the loop.
This is needed when ONLY_INIT is false, and also when AT_LOOP
is the inner-loop nested in LOOP (during outer-loop vectorization).
**/
- if (only_init && at_loop == loop) /* No update in loop is required. */
+ /* No update in loop is required. */
+ if (only_init && (!loop_vinfo || at_loop == loop))
{
/* Copy the points-to information if it exists. */
if (DR_PTR_INFO (dr))
@@ -2351,7 +2489,7 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
vect_ptr, loop, &incr_gsi, insert_after,
&indx_before_incr, &indx_after_incr);
incr = gsi_stmt (incr_gsi);
- set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo));
+ set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo, NULL));
/* Copy the points-to information if it exists. */
if (DR_PTR_INFO (dr))
@@ -2359,8 +2497,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;
@@ -2383,7 +2519,7 @@ vect_create_data_ref_ptr (gimple stmt, struct loop *at_loop,
containing_loop, &incr_gsi, insert_after, &indx_before_incr,
&indx_after_incr);
incr = gsi_stmt (incr_gsi);
- set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo));
+ set_vinfo_for_stmt (incr, new_stmt_vec_info (incr, loop_vinfo, NULL));
/* Copy the points-to information if it exists. */
if (DR_PTR_INFO (dr))
@@ -2391,8 +2527,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;
@@ -2463,7 +2597,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;
@@ -3237,13 +3370,21 @@ vect_supportable_dr_alignment (struct data_reference *dr)
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
enum machine_mode mode = TYPE_MODE (vectype);
- struct loop *vect_loop = LOOP_VINFO_LOOP (STMT_VINFO_LOOP_VINFO (stmt_info));
- bool nested_in_vect_loop = nested_in_vect_loop_p (vect_loop, stmt);
bool invariant_in_outerloop = false;
+ loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ struct loop *vect_loop = NULL;
+ bool nested_in_vect_loop = false;
if (aligned_access_p (dr))
return dr_aligned;
+ if (!loop_vinfo)
+ /* FORNOW: Misaligned accesses are supported only in loops. */
+ return dr_unaligned_unsupported;
+
+ vect_loop = LOOP_VINFO_LOOP (loop_vinfo);
+ nested_in_vect_loop = nested_in_vect_loop_p (vect_loop, stmt);
+
if (nested_in_vect_loop)
{
tree outerloop_step = STMT_VINFO_DR_STEP (stmt_info);
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
index 6c239dbf6e9..33b0a9d5796 100644
--- a/gcc/tree-vect-loop.c
+++ b/gcc/tree-vect-loop.c
@@ -640,14 +640,14 @@ new_loop_vec_info (struct loop *loop)
{
gimple phi = gsi_stmt (si);
gimple_set_uid (phi, 0);
- set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, res));
+ set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, res, NULL));
}
for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
{
gimple stmt = gsi_stmt (si);
gimple_set_uid (stmt, 0);
- set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, res));
+ set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, res, NULL));
}
}
}
@@ -1153,7 +1153,7 @@ vect_analyze_loop_operations (loop_vec_info loop_vinfo)
gcc_assert (stmt_info);
- if (!vect_analyze_stmt (stmt, &need_to_vectorize))
+ if (!vect_analyze_stmt (stmt, &need_to_vectorize, NULL))
return false;
if (STMT_VINFO_RELEVANT_P (stmt_info) && !PURE_SLP_STMT (stmt_info))
@@ -1316,7 +1316,7 @@ vect_analyze_loop (struct loop *loop)
FORNOW: Handle only simple, array references, which
alignment can be forced, and aligned pointer-references. */
- ok = vect_analyze_data_refs (loop_vinfo);
+ ok = vect_analyze_data_refs (loop_vinfo, NULL);
if (!ok)
{
if (vect_print_dump_info (REPORT_DETAILS))
@@ -1346,7 +1346,7 @@ vect_analyze_loop (struct loop *loop)
/* Analyze the alignment of the data-refs in the loop.
Fail if a data reference is found that cannot be vectorized. */
- ok = vect_analyze_data_refs_alignment (loop_vinfo);
+ ok = vect_analyze_data_refs_alignment (loop_vinfo, NULL);
if (!ok)
{
if (vect_print_dump_info (REPORT_DETAILS))
@@ -1367,7 +1367,7 @@ vect_analyze_loop (struct loop *loop)
/* Analyze data dependences between the data-refs in the loop.
FORNOW: fail at the first data dependence that we encounter. */
- ok = vect_analyze_data_ref_dependences (loop_vinfo);
+ ok = vect_analyze_data_ref_dependences (loop_vinfo, NULL);
if (!ok)
{
if (vect_print_dump_info (REPORT_DETAILS))
@@ -1379,7 +1379,7 @@ vect_analyze_loop (struct loop *loop)
/* Analyze the access patterns of the data-refs in the loop (consecutive,
complex, etc.). FORNOW: Only handle consecutive access pattern. */
- ok = vect_analyze_data_ref_accesses (loop_vinfo);
+ ok = vect_analyze_data_ref_accesses (loop_vinfo, NULL);
if (!ok)
{
if (vect_print_dump_info (REPORT_DETAILS))
@@ -1402,7 +1402,7 @@ vect_analyze_loop (struct loop *loop)
}
/* Check the SLP opportunities in the loop, analyze and build SLP trees. */
- ok = vect_analyze_slp (loop_vinfo);
+ ok = vect_analyze_slp (loop_vinfo, NULL);
if (ok)
{
/* Decide which possible SLP instances to SLP. */
@@ -2354,7 +2354,7 @@ get_initial_def_for_induction (gimple iv_phi)
add_referenced_var (vec_dest);
induction_phi = create_phi_node (vec_dest, iv_loop->header);
set_vinfo_for_stmt (induction_phi,
- new_stmt_vec_info (induction_phi, loop_vinfo));
+ new_stmt_vec_info (induction_phi, loop_vinfo, NULL));
induc_def = PHI_RESULT (induction_phi);
/* Create the iv update inside the loop */
@@ -2363,7 +2363,8 @@ get_initial_def_for_induction (gimple iv_phi)
vec_def = make_ssa_name (vec_dest, new_stmt);
gimple_assign_set_lhs (new_stmt, vec_def);
gsi_insert_before (&si, new_stmt, GSI_SAME_STMT);
- set_vinfo_for_stmt (new_stmt, new_stmt_vec_info (new_stmt, loop_vinfo));
+ set_vinfo_for_stmt (new_stmt, new_stmt_vec_info (new_stmt, loop_vinfo,
+ NULL));
/* Set the arguments of the phi node: */
add_phi_arg (induction_phi, vec_init, pe);
@@ -2405,7 +2406,7 @@ get_initial_def_for_induction (gimple iv_phi)
gsi_insert_before (&si, new_stmt, GSI_SAME_STMT);
set_vinfo_for_stmt (new_stmt,
- new_stmt_vec_info (new_stmt, loop_vinfo));
+ new_stmt_vec_info (new_stmt, loop_vinfo, NULL));
STMT_VINFO_RELATED_STMT (prev_stmt_vinfo) = new_stmt;
prev_stmt_vinfo = vinfo_for_stmt (new_stmt);
}
@@ -2743,7 +2744,7 @@ vect_create_epilog_for_reduction (tree vect_def, gimple stmt,
for (j = 0; j < ncopies; j++)
{
phi = create_phi_node (SSA_NAME_VAR (vect_def), exit_bb);
- set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, loop_vinfo));
+ set_vinfo_for_stmt (phi, new_stmt_vec_info (phi, loop_vinfo, NULL));
if (j == 0)
new_phi = phi;
else
@@ -3021,7 +3022,8 @@ vect_finalize_reduction:
epilog_stmt = adjustment_def ? epilog_stmt : new_phi;
STMT_VINFO_VEC_STMT (stmt_vinfo) = epilog_stmt;
set_vinfo_for_stmt (epilog_stmt,
- new_stmt_vec_info (epilog_stmt, loop_vinfo));
+ new_stmt_vec_info (epilog_stmt, loop_vinfo,
+ NULL));
if (adjustment_def)
STMT_VINFO_RELATED_STMT (vinfo_for_stmt (epilog_stmt)) =
STMT_VINFO_RELATED_STMT (vinfo_for_stmt (new_phi));
@@ -3204,7 +3206,7 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
The last use is the reduction variable. */
for (i = 0; i < op_type-1; i++)
{
- is_simple_use = vect_is_simple_use (ops[i], loop_vinfo, &def_stmt,
+ is_simple_use = vect_is_simple_use (ops[i], loop_vinfo, NULL, &def_stmt,
&def, &dt);
gcc_assert (is_simple_use);
if (dt != vect_internal_def
@@ -3214,8 +3216,8 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
return false;
}
- is_simple_use = vect_is_simple_use (ops[i], loop_vinfo, &def_stmt, &def,
- &dt);
+ is_simple_use = vect_is_simple_use (ops[i], loop_vinfo, NULL, &def_stmt,
+ &def, &dt);
gcc_assert (is_simple_use);
gcc_assert (dt == vect_reduction_def);
gcc_assert (gimple_code (def_stmt) == GIMPLE_PHI);
@@ -3394,7 +3396,8 @@ vectorizable_reduction (gimple stmt, gimple_stmt_iterator *gsi,
{
/* Create the reduction-phi that defines the reduction-operand. */
new_phi = create_phi_node (vec_dest, loop->header);
- set_vinfo_for_stmt (new_phi, new_stmt_vec_info (new_phi, loop_vinfo));
+ set_vinfo_for_stmt (new_phi, new_stmt_vec_info (new_phi, loop_vinfo,
+ NULL));
}
/* Handle uses. */
@@ -3592,7 +3595,8 @@ vectorizable_live_operation (gimple stmt,
op = TREE_OPERAND (gimple_op (stmt, 1), i);
else
op = gimple_op (stmt, i + 1);
- if (op && !vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt))
+ if (op
+ && !vect_is_simple_use (op, loop_vinfo, NULL, &def_stmt, &def, &dt))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -3766,7 +3770,7 @@ vect_transform_loop (loop_vec_info loop_vinfo)
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "=== scheduling SLP instances ===");
- vect_schedule_slp (loop_vinfo);
+ vect_schedule_slp (loop_vinfo, NULL);
}
/* Hybrid SLP stmts must be vectorized in addition to SLP. */
diff --git a/gcc/tree-vect-patterns.c b/gcc/tree-vect-patterns.c
index febbd643680..a41f7b4bcdf 100644
--- a/gcc/tree-vect-patterns.c
+++ b/gcc/tree-vect-patterns.c
@@ -78,7 +78,7 @@ widened_name_p (tree name, gimple use_stmt, tree *half_type, gimple *def_stmt)
stmt_vinfo = vinfo_for_stmt (use_stmt);
loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
- if (!vect_is_simple_use (name, loop_vinfo, def_stmt, &def, &dt))
+ if (!vect_is_simple_use (name, loop_vinfo, NULL, def_stmt, &def, &dt))
return false;
if (dt != vect_internal_def
@@ -102,7 +102,8 @@ widened_name_p (tree name, gimple use_stmt, tree *half_type, gimple *def_stmt)
|| (TYPE_PRECISION (type) < (TYPE_PRECISION (*half_type) * 2)))
return false;
- if (!vect_is_simple_use (oprnd0, loop_vinfo, &dummy_gimple, &dummy, &dt))
+ if (!vect_is_simple_use (oprnd0, loop_vinfo, NULL, &dummy_gimple, &dummy,
+ &dt))
return false;
return true;
@@ -734,7 +735,7 @@ vect_pattern_recog_1 (
/* Mark the stmts that are involved in the pattern. */
gsi_insert_before (&si, pattern_stmt, GSI_SAME_STMT);
set_vinfo_for_stmt (pattern_stmt,
- new_stmt_vec_info (pattern_stmt, loop_vinfo));
+ new_stmt_vec_info (pattern_stmt, loop_vinfo, NULL));
pattern_stmt_info = vinfo_for_stmt (pattern_stmt);
STMT_VINFO_RELATED_STMT (pattern_stmt_info) = stmt;
diff --git a/gcc/tree-vect-slp.c b/gcc/tree-vect-slp.c
index eb1ca62a3a3..6c932109baf 100644
--- a/gcc/tree-vect-slp.c
+++ b/gcc/tree-vect-slp.c
@@ -38,6 +38,29 @@ along with GCC; see the file COPYING3. If not see
#include "optabs.h"
#include "tree-vectorizer.h"
+/* Extract the location of the basic block in the source code.
+ Return the basic block location if succeed and NULL if not. */
+
+LOC
+find_bb_location (basic_block bb)
+{
+ gimple stmt = NULL;
+ gimple_stmt_iterator si;
+
+ if (!bb)
+ return UNKNOWN_LOC;
+
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ stmt = gsi_stmt (si);
+ if (gimple_location (stmt) != UNKNOWN_LOC)
+ return gimple_location (stmt);
+ }
+
+ return UNKNOWN_LOC;
+}
+
+
/* Recursively free the memory allocated for the SLP tree rooted at NODE. */
static void
@@ -77,8 +100,9 @@ vect_free_slp_instance (slp_instance instance)
the SLP group (stored in FIRST_STMT_...). */
static bool
-vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, slp_tree slp_node,
- gimple stmt, VEC (gimple, heap) **def_stmts0,
+vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
+ slp_tree slp_node, gimple stmt,
+ VEC (gimple, heap) **def_stmts0,
VEC (gimple, heap) **def_stmts1,
enum vect_def_type *first_stmt_dt0,
enum vect_def_type *first_stmt_dt1,
@@ -96,7 +120,10 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, slp_tree slp_node,
stmt_vec_info stmt_info =
vinfo_for_stmt (VEC_index (gimple, SLP_TREE_SCALAR_STMTS (slp_node), 0));
enum gimple_rhs_class rhs_class;
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ struct loop *loop = NULL;
+
+ if (loop_vinfo)
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
rhs_class = get_gimple_rhs_class (gimple_assign_rhs_code (stmt));
number_of_oprnds = gimple_num_ops (stmt) - 1; /* RHS only */
@@ -105,7 +132,8 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, slp_tree slp_node,
{
oprnd = gimple_op (stmt, i + 1);
- if (!vect_is_simple_use (oprnd, loop_vinfo, &def_stmt, &def, &dt[i])
+ if (!vect_is_simple_use (oprnd, loop_vinfo, bb_vinfo, &def_stmt, &def,
+ &dt[i])
|| (!def_stmt && dt[i] != vect_constant_def))
{
if (vect_print_dump_info (REPORT_SLP))
@@ -117,10 +145,10 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, slp_tree slp_node,
return false;
}
- /* Check if DEF_STMT is a part of a pattern and get the def stmt from
- the pattern. Check that all the stmts of the node are in the
+ /* Check if DEF_STMT is a part of a pattern in LOOP and get the def stmt
+ from the pattern. Check that all the stmts of the node are in the
pattern. */
- if (def_stmt && gimple_bb (def_stmt)
+ if (loop && def_stmt && gimple_bb (def_stmt)
&& flow_bb_inside_loop_p (loop, gimple_bb (def_stmt))
&& vinfo_for_stmt (def_stmt)
&& STMT_VINFO_IN_PATTERN_P (vinfo_for_stmt (def_stmt)))
@@ -271,12 +299,13 @@ vect_get_and_check_slp_defs (loop_vec_info loop_vinfo, slp_tree slp_node,
TRUE. */
static bool
-vect_build_slp_tree (loop_vec_info loop_vinfo, slp_tree *node,
- unsigned int group_size,
- int *inside_cost, int *outside_cost,
- int ncopies_for_cost, unsigned int *max_nunits,
+vect_build_slp_tree (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
+ slp_tree *node, unsigned int group_size,
+ int *inside_cost, int *outside_cost,
+ int ncopies_for_cost, unsigned int *max_nunits,
VEC (int, heap) **load_permutation,
- VEC (slp_tree, heap) **loads)
+ VEC (slp_tree, heap) **loads,
+ unsigned int vectorization_factor)
{
VEC (gimple, heap) *def_stmts0 = VEC_alloc (gimple, heap, group_size);
VEC (gimple, heap) *def_stmts1 = VEC_alloc (gimple, heap, group_size);
@@ -290,7 +319,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, slp_tree *node,
tree lhs;
bool stop_recursion = false, need_same_oprnds = false;
tree vectype, scalar_type, first_op1 = NULL_TREE;
- unsigned int vectorization_factor = 0, ncopies;
+ unsigned int ncopies;
optab optab;
int icode;
enum machine_mode optab_op2_mode;
@@ -336,13 +365,18 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, slp_tree *node,
}
return false;
}
-
- gcc_assert (LOOP_VINFO_VECT_FACTOR (loop_vinfo));
- vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+
ncopies = vectorization_factor / TYPE_VECTOR_SUBPARTS (vectype);
- if (ncopies > 1 && vect_print_dump_info (REPORT_SLP))
- fprintf (vect_dump, "SLP with multiple types ");
+ if (ncopies != 1)
+ {
+ if (vect_print_dump_info (REPORT_SLP))
+ fprintf (vect_dump, "SLP with multiple types ");
+ /* FORNOW: multiple types are unsupported in BB SLP. */
+ if (bb_vinfo)
+ return false;
+ }
+
/* In case of multiple types we need to detect the smallest type. */
if (*max_nunits < TYPE_VECTOR_SUBPARTS (vectype))
*max_nunits = TYPE_VECTOR_SUBPARTS (vectype);
@@ -438,8 +472,8 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, slp_tree *node,
if (REFERENCE_CLASS_P (lhs))
{
/* Store. */
- if (!vect_get_and_check_slp_defs (loop_vinfo, *node, stmt,
- &def_stmts0, &def_stmts1,
+ if (!vect_get_and_check_slp_defs (loop_vinfo, bb_vinfo, *node,
+ stmt, &def_stmts0, &def_stmts1,
&first_stmt_dt0,
&first_stmt_dt1,
&first_stmt_def0_type,
@@ -552,7 +586,7 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, slp_tree *node,
}
/* Find the def-stmts. */
- if (!vect_get_and_check_slp_defs (loop_vinfo, *node, stmt,
+ if (!vect_get_and_check_slp_defs (loop_vinfo, bb_vinfo, *node, stmt,
&def_stmts0, &def_stmts1,
&first_stmt_dt0, &first_stmt_dt1,
&first_stmt_def0_type,
@@ -590,9 +624,10 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, slp_tree *node,
SLP_TREE_RIGHT (left_node) = NULL;
SLP_TREE_OUTSIDE_OF_LOOP_COST (left_node) = 0;
SLP_TREE_INSIDE_OF_LOOP_COST (left_node) = 0;
- if (!vect_build_slp_tree (loop_vinfo, &left_node, group_size,
+ if (!vect_build_slp_tree (loop_vinfo, bb_vinfo, &left_node, group_size,
inside_cost, outside_cost, ncopies_for_cost,
- max_nunits, load_permutation, loads))
+ max_nunits, load_permutation, loads,
+ vectorization_factor))
return false;
SLP_TREE_LEFT (*node) = left_node;
@@ -607,9 +642,10 @@ vect_build_slp_tree (loop_vec_info loop_vinfo, slp_tree *node,
SLP_TREE_RIGHT (right_node) = NULL;
SLP_TREE_OUTSIDE_OF_LOOP_COST (right_node) = 0;
SLP_TREE_INSIDE_OF_LOOP_COST (right_node) = 0;
- if (!vect_build_slp_tree (loop_vinfo, &right_node, group_size,
+ if (!vect_build_slp_tree (loop_vinfo, bb_vinfo, &right_node, group_size,
inside_cost, outside_cost, ncopies_for_cost,
- max_nunits, load_permutation, loads))
+ max_nunits, load_permutation, loads,
+ vectorization_factor))
return false;
SLP_TREE_RIGHT (*node) = right_node;
@@ -664,6 +700,31 @@ vect_mark_slp_stmts (slp_tree node, enum slp_vect_type mark, int j)
}
+/* Mark the statements of the tree rooted at NODE as relevant (vect_used). */
+
+static void
+vect_mark_slp_stmts_relevant (slp_tree node)
+{
+ int i;
+ gimple stmt;
+ stmt_vec_info stmt_info;
+
+ if (!node)
+ return;
+
+ for (i = 0; VEC_iterate (gimple, SLP_TREE_SCALAR_STMTS (node), i, stmt); i++)
+ {
+ stmt_info = vinfo_for_stmt (stmt);
+ gcc_assert (!STMT_VINFO_RELEVANT (stmt_info)
+ || STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_scope);
+ STMT_VINFO_RELEVANT (stmt_info) = vect_used_in_scope;
+ }
+
+ vect_mark_slp_stmts_relevant (SLP_TREE_LEFT (node));
+ vect_mark_slp_stmts_relevant (SLP_TREE_RIGHT (node));
+}
+
+
/* Check if the permutation required by the SLP INSTANCE is supported.
Reorganize the SLP nodes stored in SLP_INSTANCE_LOADS if needed. */
@@ -736,7 +797,7 @@ vect_supported_load_permutation_p (slp_instance slp_instn, int group_size,
int i = 0, j, prev = -1, next, k;
bool supported;
- /* FORNOW: permutations are only supported for loop-aware SLP. */
+ /* FORNOW: permutations are only supported in SLP. */
if (!slp_instn)
return false;
@@ -809,7 +870,8 @@ vect_find_first_load_in_slp_instance (slp_instance instance)
Return FALSE if it's impossible to SLP any stmt in the loop. */
static bool
-vect_analyze_slp_instance (loop_vec_info loop_vinfo, gimple stmt)
+vect_analyze_slp_instance (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo,
+ gimple stmt)
{
slp_instance new_instance;
slp_tree node = XNEW (struct _slp_tree);
@@ -818,7 +880,6 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, gimple stmt)
tree vectype, scalar_type;
gimple next;
unsigned int vectorization_factor = 0, ncopies;
- bool slp_impossible = false;
int inside_cost = 0, outside_cost = 0, ncopies_for_cost;
unsigned int max_nunits = 0;
VEC (int, heap) *load_permutation;
@@ -838,9 +899,24 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, gimple stmt)
}
nunits = TYPE_VECTOR_SUBPARTS (vectype);
- vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ if (loop_vinfo)
+ vectorization_factor = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ else
+ /* No multitypes in BB SLP. */
+ vectorization_factor = nunits;
+
ncopies = vectorization_factor / nunits;
+ /* Calculate the unrolling factor. */
+ unrolling_factor = least_common_multiple (nunits, group_size) / group_size;
+ if (unrolling_factor != 1 && !loop_vinfo)
+ {
+ if (vect_print_dump_info (REPORT_SLP))
+ fprintf (vect_dump, "Build SLP failed: unrolling required in BB SLP");
+
+ return false;
+ }
+
/* Create a node (a root of the SLP tree) for the packed strided stores. */
SLP_TREE_SCALAR_STMTS (node) = VEC_alloc (gimple, heap, group_size);
next = stmt;
@@ -858,9 +934,6 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, gimple stmt)
SLP_TREE_OUTSIDE_OF_LOOP_COST (node) = 0;
SLP_TREE_INSIDE_OF_LOOP_COST (node) = 0;
- /* Calculate the unrolling factor. */
- unrolling_factor = least_common_multiple (nunits, group_size) / group_size;
-
/* Calculate the number of vector stmts to create based on the unrolling
factor (number of vectors is 1 if NUNITS >= GROUP_SIZE, and is
GROUP_SIZE / NUNITS otherwise. */
@@ -870,9 +943,10 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, gimple stmt)
loads = VEC_alloc (slp_tree, heap, group_size);
/* Build the tree for the SLP instance. */
- if (vect_build_slp_tree (loop_vinfo, &node, group_size, &inside_cost,
- &outside_cost, ncopies_for_cost, &max_nunits,
- &load_permutation, &loads))
+ if (vect_build_slp_tree (loop_vinfo, bb_vinfo, &node, group_size,
+ &inside_cost, &outside_cost, ncopies_for_cost,
+ &max_nunits, &load_permutation, &loads,
+ vectorization_factor))
{
/* Create a new SLP instance. */
new_instance = XNEW (struct _slp_instance);
@@ -883,7 +957,7 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, gimple stmt)
if (max_nunits > nunits)
unrolling_factor = least_common_multiple (max_nunits, group_size)
/ group_size;
-
+
SLP_INSTANCE_UNROLLING_FACTOR (new_instance) = unrolling_factor;
SLP_INSTANCE_OUTSIDE_OF_LOOP_COST (new_instance) = outside_cost;
SLP_INSTANCE_INSIDE_OF_LOOP_COST (new_instance) = inside_cost;
@@ -912,8 +986,14 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, gimple stmt)
else
VEC_free (int, heap, SLP_INSTANCE_LOAD_PERMUTATION (new_instance));
- VEC_safe_push (slp_instance, heap, LOOP_VINFO_SLP_INSTANCES (loop_vinfo),
- new_instance);
+ if (loop_vinfo)
+ VEC_safe_push (slp_instance, heap,
+ LOOP_VINFO_SLP_INSTANCES (loop_vinfo),
+ new_instance);
+ else
+ VEC_safe_push (slp_instance, heap, BB_VINFO_SLP_INSTANCES (bb_vinfo),
+ new_instance);
+
if (vect_print_dump_info (REPORT_SLP))
vect_print_slp_tree (node);
@@ -926,12 +1006,7 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, gimple stmt)
VEC_free (int, heap, load_permutation);
VEC_free (slp_tree, heap, loads);
- if (slp_impossible)
- return false;
-
- /* SLP failed for this instance, but it is still possible to SLP other stmts
- in the loop. */
- return true;
+ return false;
}
@@ -939,24 +1014,32 @@ vect_analyze_slp_instance (loop_vec_info loop_vinfo, gimple stmt)
trees of packed scalar stmts if SLP is possible. */
bool
-vect_analyze_slp (loop_vec_info loop_vinfo)
+vect_analyze_slp (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
{
unsigned int i;
- VEC (gimple, heap) *strided_stores = LOOP_VINFO_STRIDED_STORES (loop_vinfo);
+ VEC (gimple, heap) *strided_stores;
gimple store;
+ bool ok = false;
if (vect_print_dump_info (REPORT_SLP))
fprintf (vect_dump, "=== vect_analyze_slp ===");
+ if (loop_vinfo)
+ strided_stores = LOOP_VINFO_STRIDED_STORES (loop_vinfo);
+ else
+ strided_stores = BB_VINFO_STRIDED_STORES (bb_vinfo);
+
for (i = 0; VEC_iterate (gimple, strided_stores, i, store); i++)
- if (!vect_analyze_slp_instance (loop_vinfo, store))
- {
- /* SLP failed. No instance can be SLPed in the loop. */
- if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
- fprintf (vect_dump, "SLP failed.");
+ if (vect_analyze_slp_instance (loop_vinfo, bb_vinfo, store))
+ ok = true;
- return false;
- }
+ if (bb_vinfo && !ok)
+ {
+ if (vect_print_dump_info (REPORT_SLP))
+ fprintf (vect_dump, "Failed to SLP the basic block.");
+
+ return false;
+ }
return true;
}
@@ -1041,6 +1124,255 @@ vect_detect_hybrid_slp (loop_vec_info loop_vinfo)
vect_detect_hybrid_slp_stmts (SLP_INSTANCE_TREE (instance));
}
+
+/* Create and initialize a new bb_vec_info struct for BB, as well as
+ stmt_vec_info structs for all the stmts in it. */
+
+static bb_vec_info
+new_bb_vec_info (basic_block bb)
+{
+ bb_vec_info res = NULL;
+ gimple_stmt_iterator gsi;
+
+ res = (bb_vec_info) xcalloc (1, sizeof (struct _bb_vec_info));
+ BB_VINFO_BB (res) = bb;
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ {
+ gimple stmt = gsi_stmt (gsi);
+ gimple_set_uid (stmt, 0);
+ set_vinfo_for_stmt (stmt, new_stmt_vec_info (stmt, NULL, res));
+ }
+
+ BB_VINFO_STRIDED_STORES (res) = VEC_alloc (gimple, heap, 10);
+ BB_VINFO_SLP_INSTANCES (res) = VEC_alloc (slp_instance, heap, 2);
+
+ bb->aux = res;
+ return res;
+}
+
+
+/* Free BB_VINFO struct, as well as all the stmt_vec_info structs of all the
+ stmts in the basic block. */
+
+static void
+destroy_bb_vec_info (bb_vec_info bb_vinfo)
+{
+ basic_block bb;
+ gimple_stmt_iterator si;
+
+ if (!bb_vinfo)
+ return;
+
+ bb = BB_VINFO_BB (bb_vinfo);
+
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple stmt = gsi_stmt (si);
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+
+ if (stmt_info)
+ /* Free stmt_vec_info. */
+ free_stmt_vec_info (stmt);
+ }
+
+ VEC_free (gimple, heap, BB_VINFO_STRIDED_STORES (bb_vinfo));
+ VEC_free (slp_instance, heap, BB_VINFO_SLP_INSTANCES (bb_vinfo));
+ free (bb_vinfo);
+ bb->aux = NULL;
+}
+
+
+/* Analyze statements contained in SLP tree node after recursively analyzing
+ the subtree. Return TRUE if the operations are supported. */
+
+static bool
+vect_slp_analyze_node_operations (bb_vec_info bb_vinfo, slp_tree node)
+{
+ bool dummy;
+ int i;
+ gimple stmt;
+
+ if (!node)
+ return true;
+
+ if (!vect_slp_analyze_node_operations (bb_vinfo, SLP_TREE_LEFT (node))
+ || !vect_slp_analyze_node_operations (bb_vinfo, SLP_TREE_RIGHT (node)))
+ return false;
+
+ for (i = 0; VEC_iterate (gimple, SLP_TREE_SCALAR_STMTS (node), i, stmt); i++)
+ {
+ stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
+ gcc_assert (stmt_info);
+ gcc_assert (PURE_SLP_STMT (stmt_info));
+
+ if (!vect_analyze_stmt (stmt, &dummy, node))
+ return false;
+ }
+
+ return true;
+}
+
+
+/* Analyze statements in SLP instances of the basic block. Return TRUE if the
+ operations are supported. */
+
+static bool
+vect_slp_analyze_operations (bb_vec_info bb_vinfo)
+{
+ VEC (slp_instance, heap) *slp_instances = BB_VINFO_SLP_INSTANCES (bb_vinfo);
+ slp_instance instance;
+ int i;
+
+ for (i = 0; VEC_iterate (slp_instance, slp_instances, i, instance); )
+ {
+ if (!vect_slp_analyze_node_operations (bb_vinfo,
+ SLP_INSTANCE_TREE (instance)))
+ {
+ vect_free_slp_instance (instance);
+ VEC_ordered_remove (slp_instance, slp_instances, i);
+ }
+ else
+ i++;
+ }
+
+ if (!VEC_length (slp_instance, slp_instances))
+ return false;
+
+ return true;
+}
+
+
+/* Cheick if the basic block can be vectorized. */
+
+bb_vec_info
+vect_slp_analyze_bb (basic_block bb)
+{
+ bb_vec_info bb_vinfo;
+ VEC (ddr_p, heap) *ddrs;
+ VEC (slp_instance, heap) *slp_instances;
+ slp_instance instance;
+ int i, insns = 0;
+ gimple_stmt_iterator gsi;
+
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "===vect_slp_analyze_bb===\n");
+
+ for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
+ insns++;
+
+ if (insns > PARAM_VALUE (PARAM_SLP_MAX_INSNS_IN_BB))
+ {
+ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "not vectorized: too many instructions in basic "
+ "block.\n");
+
+ return NULL;
+ }
+
+ bb_vinfo = new_bb_vec_info (bb);
+ if (!bb_vinfo)
+ return NULL;
+
+ if (!vect_analyze_data_refs (NULL, bb_vinfo))
+ {
+ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "not vectorized: unhandled data-ref in basic "
+ "block.\n");
+
+ destroy_bb_vec_info (bb_vinfo);
+ return NULL;
+ }
+
+ ddrs = BB_VINFO_DDRS (bb_vinfo);
+ if (!VEC_length (ddr_p, ddrs))
+ {
+ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "not vectorized: not enough data-refs in basic "
+ "block.\n");
+
+ destroy_bb_vec_info (bb_vinfo);
+ return NULL;
+ }
+
+ if (!vect_analyze_data_refs_alignment (NULL, bb_vinfo))
+ {
+ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "not vectorized: bad data alignment in basic "
+ "block.\n");
+
+ destroy_bb_vec_info (bb_vinfo);
+ return NULL;
+ }
+
+ if (!vect_analyze_data_ref_dependences (NULL, bb_vinfo))
+ {
+ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "not vectorized: unhandled data dependence in basic"
+ " block.\n");
+
+ destroy_bb_vec_info (bb_vinfo);
+ return NULL;
+ }
+
+ if (!vect_analyze_data_ref_accesses (NULL, bb_vinfo))
+ {
+ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "not vectorized: unhandled data access in basic "
+ "block.\n");
+
+ destroy_bb_vec_info (bb_vinfo);
+ return NULL;
+ }
+
+ if (!vect_verify_datarefs_alignment (NULL, bb_vinfo))
+ {
+ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "not vectorized: unsupported alignment in basic "
+ "block.\n");
+
+ destroy_bb_vec_info (bb_vinfo);
+ return NULL;
+ }
+
+ /* Check the SLP opportunities in the basic block, analyze and build SLP
+ trees. */
+ if (!vect_analyze_slp (NULL, bb_vinfo))
+ {
+ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "not vectorized: failed to find SLP opportunities "
+ "in basic block.\n");
+
+ destroy_bb_vec_info (bb_vinfo);
+ return NULL;
+ }
+
+ slp_instances = BB_VINFO_SLP_INSTANCES (bb_vinfo);
+
+ /* Mark all the statements that we want to vectorize as pure SLP and
+ relevant. */
+ for (i = 0; VEC_iterate (slp_instance, slp_instances, i, instance); i++)
+ {
+ vect_mark_slp_stmts (SLP_INSTANCE_TREE (instance), pure_slp, -1);
+ vect_mark_slp_stmts_relevant (SLP_INSTANCE_TREE (instance));
+ }
+
+ if (!vect_slp_analyze_operations (bb_vinfo))
+ {
+ if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "not vectorized: bad operation in basic block.\n");
+
+ destroy_bb_vec_info (bb_vinfo);
+ return NULL;
+ }
+
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "BB will be vectorized using SLP\n");
+
+ return bb_vinfo;
+}
+
+
/* SLP costs are calculated according to SLP instance unrolling factor (i.e.,
the number of created vector stmts depends on the unrolling factor). However,
the actual number of vector stmts for every SLP node depends on VF which is
@@ -1064,6 +1396,7 @@ vect_update_slp_costs_according_to_vf (loop_vec_info loop_vinfo)
/ SLP_INSTANCE_UNROLLING_FACTOR (instance);
}
+
/* For constant and loop invariant defs of SLP_NODE this function returns
(vector) defs (VEC_OPRNDS) that will be used in the vectorized stmts.
OP_NUM determines if we gather defs for operand 0 or operand 1 of the scalar
@@ -1284,6 +1617,7 @@ vect_get_slp_defs (slp_tree slp_node, VEC (tree,heap) **vec_oprnds0,
vect_get_constant_vectors (slp_node, vec_oprnds1, 1, number_of_vects);
}
+
/* Create NCOPIES permutation statements using the mask MASK_BYTES (by
building a vector of type MASK_TYPE from it) and two input vectors placed in
DR_CHAIN at FIRST_VEC_INDX and SECOND_VEC_INDX for the first copy and
@@ -1588,7 +1922,7 @@ vect_transform_slp_perm_load (gimple stmt, VEC (tree, heap) *dr_chain,
static bool
vect_schedule_slp_instance (slp_tree node, slp_instance instance,
- unsigned int vectorization_factor)
+ unsigned int vectorization_factor)
{
gimple stmt;
bool strided_store, is_store;
@@ -1658,7 +1992,7 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
si = gsi_for_stmt (SLP_INSTANCE_FIRST_LOAD_STMT (instance));
else
si = gsi_for_stmt (stmt);
-
+
is_store = vect_transform_stmt (stmt, &si, &strided_store, node, instance);
if (is_store)
{
@@ -1680,20 +2014,29 @@ vect_schedule_slp_instance (slp_tree node, slp_instance instance,
bool
-vect_schedule_slp (loop_vec_info loop_vinfo)
+vect_schedule_slp (loop_vec_info loop_vinfo, bb_vec_info bb_vinfo)
{
- VEC (slp_instance, heap) *slp_instances =
- LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
+ VEC (slp_instance, heap) *slp_instances;
slp_instance instance;
- unsigned int i;
+ unsigned int i, vf;
bool is_store = false;
+ if (loop_vinfo)
+ {
+ slp_instances = LOOP_VINFO_SLP_INSTANCES (loop_vinfo);
+ vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ }
+ else
+ {
+ slp_instances = BB_VINFO_SLP_INSTANCES (bb_vinfo);
+ vf = 1;
+ }
+
for (i = 0; VEC_iterate (slp_instance, slp_instances, i, instance); i++)
{
/* Schedule the tree of INSTANCE. */
is_store = vect_schedule_slp_instance (SLP_INSTANCE_TREE (instance),
- instance, LOOP_VINFO_VECT_FACTOR (loop_vinfo));
-
+ instance, vf);
if (vect_print_dump_info (REPORT_VECTORIZED_LOCATIONS)
|| vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
fprintf (vect_dump, "vectorizing stmts using SLP.");
@@ -1701,3 +2044,52 @@ vect_schedule_slp (loop_vec_info loop_vinfo)
return is_store;
}
+
+
+/* Vectorize the basic block. */
+
+void
+vect_slp_transform_bb (basic_block bb)
+{
+ bb_vec_info bb_vinfo = vec_info_for_bb (bb);
+ gimple_stmt_iterator si;
+
+ gcc_assert (bb_vinfo);
+
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "SLPing BB\n");
+
+ for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si))
+ {
+ gimple stmt = gsi_stmt (si);
+ stmt_vec_info stmt_info;
+
+ if (vect_print_dump_info (REPORT_DETAILS))
+ {
+ fprintf (vect_dump, "------>SLPing statement: ");
+ print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
+ }
+
+ stmt_info = vinfo_for_stmt (stmt);
+ gcc_assert (stmt_info);
+
+ /* Schedule all the SLP instances when the first SLP stmt is reached. */
+ if (STMT_SLP_TYPE (stmt_info))
+ {
+ vect_schedule_slp (NULL, bb_vinfo);
+ break;
+ }
+ }
+
+ mark_sym_for_renaming (gimple_vop (cfun));
+ /* 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? */
+ update_ssa (TODO_update_ssa);
+
+ if (vect_print_dump_info (REPORT_DETAILS))
+ fprintf (vect_dump, "BB VECTORIZED\n");
+
+ destroy_bb_vec_info (bb_vinfo);
+}
+
diff --git a/gcc/tree-vect-stmts.c b/gcc/tree-vect-stmts.c
index 06d51e2d318..5ca8d942e18 100644
--- a/gcc/tree-vect-stmts.c
+++ b/gcc/tree-vect-stmts.c
@@ -248,7 +248,7 @@ process_use (gimple stmt, tree use, loop_vec_info loop_vinfo, bool live_p,
if (!exist_non_indexing_operands_for_use_p (use, stmt))
return true;
- if (!vect_is_simple_use (use, loop_vinfo, &def_stmt, &def, &dt))
+ if (!vect_is_simple_use (use, loop_vinfo, NULL, &def_stmt, &def, &dt))
{
if (vect_print_dump_info (REPORT_UNVECTORIZED_LOCATIONS))
fprintf (vect_dump, "not vectorized: unsupported use in stmt.");
@@ -336,7 +336,7 @@ process_use (gimple stmt, tree use, loop_vec_info loop_vinfo, bool live_p,
{
case vect_unused_in_scope:
relevant = (STMT_VINFO_DEF_TYPE (stmt_vinfo) == vect_reduction_def) ?
- vect_used_in_outer_by_reduction : vect_unused_in_scope;
+ vect_used_in_outer_by_reduction : vect_unused_in_scope;
break;
case vect_used_in_outer_by_reduction:
@@ -813,13 +813,29 @@ vect_init_vector (gimple stmt, tree vector_var, tree vector_type,
else
{
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_vinfo);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
-
- if (nested_in_vect_loop_p (loop, stmt))
- loop = loop->inner;
- pe = loop_preheader_edge (loop);
- new_bb = gsi_insert_on_edge_immediate (pe, init_stmt);
- gcc_assert (!new_bb);
+
+ if (loop_vinfo)
+ {
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+
+ if (nested_in_vect_loop_p (loop, stmt))
+ loop = loop->inner;
+
+ pe = loop_preheader_edge (loop);
+ new_bb = gsi_insert_on_edge_immediate (pe, init_stmt);
+ gcc_assert (!new_bb);
+ }
+ else
+ {
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_vinfo);
+ basic_block bb;
+ gimple_stmt_iterator gsi_bb_start;
+
+ gcc_assert (bb_vinfo);
+ bb = BB_VINFO_BB (bb_vinfo);
+ gsi_bb_start = gsi_after_labels (bb);
+ gsi_insert_before (&gsi_bb_start, init_stmt, GSI_SAME_STMT);
+ }
}
if (vect_print_dump_info (REPORT_DETAILS))
@@ -832,6 +848,7 @@ vect_init_vector (gimple stmt, tree vector_var, tree vector_type,
return vec_oprnd;
}
+
/* Function vect_get_vec_def_for_operand.
OP is an operand in STMT. This function returns a (vector) def that will be
@@ -869,7 +886,8 @@ vect_get_vec_def_for_operand (tree op, gimple stmt, tree *scalar_def)
print_generic_expr (vect_dump, op, TDF_SLIM);
}
- is_simple_use = vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt);
+ is_simple_use = vect_is_simple_use (op, loop_vinfo, NULL, &def_stmt, &def,
+ &dt);
gcc_assert (is_simple_use);
if (vect_print_dump_info (REPORT_DETAILS))
{
@@ -1122,12 +1140,14 @@ vect_finish_stmt_generation (gimple stmt, gimple vec_stmt,
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
gcc_assert (gimple_code (stmt) != GIMPLE_LABEL);
gsi_insert_before (gsi, vec_stmt, GSI_SAME_STMT);
- set_vinfo_for_stmt (vec_stmt, new_stmt_vec_info (vec_stmt, loop_vinfo));
+ set_vinfo_for_stmt (vec_stmt, new_stmt_vec_info (vec_stmt, loop_vinfo,
+ bb_vinfo));
if (vect_print_dump_info (REPORT_DETAILS))
{
@@ -1191,6 +1211,9 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
enum { NARROW, NONE, WIDEN } modifier;
size_t i, nargs;
+ /* FORNOW: unsupported in basic block SLP. */
+ gcc_assert (loop_vinfo);
+
if (!STMT_VINFO_RELEVANT_P (stmt_info))
return false;
@@ -1232,7 +1255,7 @@ vectorizable_call (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt)
}
rhs_type = TREE_TYPE (op);
- if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt[i]))
+ if (!vect_is_simple_use (op, loop_vinfo, NULL, &def_stmt, &def, &dt[i]))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -1509,6 +1532,9 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
/* Is STMT a vectorizable conversion? */
+ /* FORNOW: unsupported in basic block SLP. */
+ gcc_assert (loop_vinfo);
+
if (!STMT_VINFO_RELEVANT_P (stmt_info))
return false;
@@ -1575,7 +1601,7 @@ vectorizable_conversion (gimple stmt, gimple_stmt_iterator *gsi,
gcc_assert (ncopies >= 1);
/* Check the operands of the operation. */
- if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt[0]))
+ if (!vect_is_simple_use (op0, loop_vinfo, NULL, &def_stmt, &def, &dt[0]))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -1759,6 +1785,7 @@ vectorizable_assignment (gimple stmt, gimple_stmt_iterator *gsi,
int i;
VEC(tree,heap) *vec_oprnds = NULL;
tree vop;
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
/* Multiple types in SLP are handled by creating the appropriate number of
vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
@@ -1772,7 +1799,7 @@ vectorizable_assignment (gimple stmt, gimple_stmt_iterator *gsi,
if (ncopies > 1)
return false; /* FORNOW */
- if (!STMT_VINFO_RELEVANT_P (stmt_info))
+ if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
return false;
if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
@@ -1792,7 +1819,7 @@ vectorizable_assignment (gimple stmt, gimple_stmt_iterator *gsi,
else
return false;
- if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt[0]))
+ if (!vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt[0]))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -1875,6 +1902,14 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
unsigned int k;
bool shift_p = false;
bool scalar_shift_arg = false;
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+ int vf;
+
+ if (loop_vinfo)
+ vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ else
+ /* FORNOW: multiple types are not supported in basic block SLP. */
+ vf = nunits_in;
/* Multiple types in SLP are handled by creating the appropriate number of
vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
@@ -1886,7 +1921,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
gcc_assert (ncopies >= 1);
- if (!STMT_VINFO_RELEVANT_P (stmt_info))
+ if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
return false;
if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
@@ -1924,7 +1959,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
}
op0 = gimple_assign_rhs1 (stmt);
- if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt[0]))
+ if (!vect_is_simple_use (op0, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt[0]))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -1934,7 +1969,8 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
if (op_type == binary_op)
{
op1 = gimple_assign_rhs2 (stmt);
- if (!vect_is_simple_use (op1, loop_vinfo, &def_stmt, &def, &dt[1]))
+ if (!vect_is_simple_use (op1, loop_vinfo, bb_vinfo, &def_stmt, &def,
+ &dt[1]))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -2016,8 +2052,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
fprintf (vect_dump, "op not supported by target.");
/* Check only during analysis. */
if (GET_MODE_SIZE (vec_mode) != UNITS_PER_WORD
- || (LOOP_VINFO_VECT_FACTOR (loop_vinfo)
- < vect_min_worthwhile_factor (code)
+ || (vf < vect_min_worthwhile_factor (code)
&& !vec_stmt))
return false;
if (vect_print_dump_info (REPORT_DETAILS))
@@ -2026,8 +2061,7 @@ vectorizable_operation (gimple stmt, gimple_stmt_iterator *gsi,
/* Worthwhile without SIMD support? Check only during analysis. */
if (!VECTOR_MODE_P (TYPE_MODE (vectype))
- && LOOP_VINFO_VECT_FACTOR (loop_vinfo)
- < vect_min_worthwhile_factor (code)
+ && vf < vect_min_worthwhile_factor (code)
&& !vec_stmt)
{
if (vect_print_dump_info (REPORT_DETAILS))
@@ -2333,6 +2367,9 @@ vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
VEC (tree, heap) *vec_dsts = NULL, *interm_types = NULL, *tmp_vec_dsts = NULL;
tree last_oprnd, intermediate_type;
+ /* FORNOW: not supported by basic block SLP vectorization. */
+ gcc_assert (loop_vinfo);
+
if (!STMT_VINFO_RELEVANT_P (stmt_info))
return false;
@@ -2371,7 +2408,6 @@ vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
ncopies = 1;
else
ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits_out;
-
gcc_assert (ncopies >= 1);
if (! ((INTEGRAL_TYPE_P (TREE_TYPE (scalar_dest))
@@ -2382,7 +2418,7 @@ vectorizable_type_demotion (gimple stmt, gimple_stmt_iterator *gsi,
return false;
/* Check the operands of the operation. */
- if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt[0]))
+ if (!vect_is_simple_use (op0, loop_vinfo, NULL, &def_stmt, &def, &dt[0]))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -2562,7 +2598,7 @@ vect_create_vectorized_promotion_stmts (VEC (tree, heap) **vec_oprnds0,
prev_stmt_info);
}
}
-
+
/* Function vectorizable_type_promotion
@@ -2600,6 +2636,9 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
VEC (tree, heap) *vec_oprnds0 = NULL, *vec_oprnds1 = NULL;
VEC (tree, heap) *vec_dsts = NULL, *interm_types = NULL, *tmp_vec_dsts = NULL;
+ /* FORNOW: not supported by basic block SLP vectorization. */
+ gcc_assert (loop_vinfo);
+
if (!STMT_VINFO_RELEVANT_P (stmt_info))
return false;
@@ -2650,7 +2689,7 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
return false;
/* Check the operands of the operation. */
- if (!vect_is_simple_use (op0, loop_vinfo, &def_stmt, &def, &dt[0]))
+ if (!vect_is_simple_use (op0, loop_vinfo, NULL, &def_stmt, &def, &dt[0]))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -2661,7 +2700,7 @@ vectorizable_type_promotion (gimple stmt, gimple_stmt_iterator *gsi,
if (op_type == binary_op)
{
op1 = gimple_assign_rhs2 (stmt);
- if (!vect_is_simple_use (op1, loop_vinfo, &def_stmt, &def, &dt[1]))
+ if (!vect_is_simple_use (op1, loop_vinfo, NULL, &def_stmt, &def, &dt[1]))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -2806,7 +2845,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr = NULL;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ struct loop *loop = NULL;
enum machine_mode vec_mode;
tree dummy;
enum dr_alignment_support alignment_support_scheme;
@@ -2827,6 +2866,10 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
bool slp = (slp_node != NULL);
stmt_vec_info first_stmt_vinfo;
unsigned int vec_num;
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+
+ if (loop_vinfo)
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
/* Multiple types in SLP are handled by creating the appropriate number of
vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
@@ -2839,14 +2882,14 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
gcc_assert (ncopies >= 1);
/* FORNOW. This restriction should be relaxed. */
- if (nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
+ if (loop && nested_in_vect_loop_p (loop, stmt) && ncopies > 1)
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "multiple types in nested loop.");
return false;
}
- if (!STMT_VINFO_RELEVANT_P (stmt_info))
+ if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
return false;
if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
@@ -2865,7 +2908,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
gcc_assert (gimple_assign_single_p (stmt));
op = gimple_assign_rhs1 (stmt);
- if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt))
+ if (!vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt, &def, &dt))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -2907,7 +2950,8 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
{
gcc_assert (gimple_assign_single_p (next_stmt));
op = gimple_assign_rhs1 (next_stmt);
- if (!vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt))
+ if (!vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt,
+ &def, &dt))
{
if (vect_print_dump_info (REPORT_DETAILS))
fprintf (vect_dump, "use not simple.");
@@ -2935,7 +2979,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
DR_GROUP_STORE_COUNT (vinfo_for_stmt (first_stmt))++;
/* FORNOW */
- gcc_assert (!nested_in_vect_loop_p (loop, stmt));
+ gcc_assert (!loop || !nested_in_vect_loop_p (loop, stmt));
/* We vectorize all the stmts of the interleaving group when we
reach the last stmt in the group. */
@@ -3063,7 +3107,7 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
dataref_ptr = vect_create_data_ref_ptr (first_stmt, NULL, NULL_TREE,
&dummy, &ptr_incr, false,
&inv_p);
- gcc_assert (!inv_p);
+ gcc_assert (bb_vinfo || !inv_p);
}
else
{
@@ -3077,7 +3121,8 @@ vectorizable_store (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
for (i = 0; i < group_size; i++)
{
op = VEC_index (tree, oprnds, i);
- vect_is_simple_use (op, loop_vinfo, &def_stmt, &def, &dt);
+ vect_is_simple_use (op, loop_vinfo, bb_vinfo, &def_stmt, &def,
+ &dt);
vec_oprnd = vect_get_vec_def_for_stmt_copy (dt, op);
VEC_replace(tree, dr_chain, i, vec_oprnd);
VEC_replace(tree, oprnds, i, vec_oprnd);
@@ -3162,9 +3207,9 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
stmt_vec_info prev_stmt_info;
loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ struct loop *loop = NULL;
struct loop *containing_loop = (gimple_bb (stmt))->loop_father;
- bool nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
+ bool nested_in_vect_loop = false;
struct data_reference *dr = STMT_VINFO_DATA_REF (stmt_info), *first_dr;
tree vectype = STMT_VINFO_VECTYPE (stmt_info);
tree new_temp;
@@ -3192,6 +3237,18 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
bool slp = (slp_node != NULL);
bool slp_perm = false;
enum tree_code code;
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+ int vf;
+
+ if (loop_vinfo)
+ {
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
+ nested_in_vect_loop = nested_in_vect_loop_p (loop, stmt);
+ vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
+ }
+ else
+ /* FORNOW: multiple types are not supported in basic block SLP. */
+ vf = nunits;
/* Multiple types in SLP are handled by creating the appropriate number of
vectorized stmts for each SLP node. Hence, NCOPIES is always 1 in
@@ -3211,10 +3268,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
return false;
}
- if (slp && SLP_INSTANCE_LOAD_PERMUTATION (slp_node_instance))
- slp_perm = true;
-
- if (!STMT_VINFO_RELEVANT_P (stmt_info))
+ if (!STMT_VINFO_RELEVANT_P (stmt_info) && !bb_vinfo)
return false;
if (STMT_VINFO_DEF_TYPE (stmt_info) != vect_internal_def)
@@ -3300,7 +3354,9 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
{
strided_load = false;
vec_num = SLP_TREE_NUMBER_OF_VEC_STMTS (slp_node);
- }
+ if (SLP_INSTANCE_LOAD_PERMUTATION (slp_node_instance))
+ slp_perm = true;
+ }
else
vec_num = group_size;
@@ -3419,7 +3475,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
This can only occur when vectorizing memory accesses in the inner-loop
nested within an outer-loop that is being vectorized. */
- if (nested_in_vect_loop_p (loop, stmt)
+ if (loop && nested_in_vect_loop_p (loop, stmt)
&& (TREE_INT_CST_LOW (DR_STEP (dr))
% GET_MODE_SIZE (TYPE_MODE (vectype)) != 0))
{
@@ -3551,7 +3607,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
}
/* 4. Handle invariant-load. */
- if (inv_p)
+ if (inv_p && !bb_vinfo)
{
gcc_assert (!strided_load);
gcc_assert (nested_in_vect_loop_p (loop, stmt));
@@ -3598,8 +3654,7 @@ vectorizable_load (gimple stmt, gimple_stmt_iterator *gsi, gimple *vec_stmt,
if (slp_perm)
{
- if (!vect_transform_slp_perm_load (stmt, dr_chain, gsi,
- LOOP_VINFO_VECT_FACTOR (loop_vinfo),
+ if (!vect_transform_slp_perm_load (stmt, dr_chain, gsi, vf,
slp_node_instance, false))
{
VEC_free (tree, heap, dr_chain);
@@ -3659,7 +3714,8 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
if (TREE_CODE (lhs) == SSA_NAME)
{
gimple lhs_def_stmt = SSA_NAME_DEF_STMT (lhs);
- if (!vect_is_simple_use (lhs, loop_vinfo, &lhs_def_stmt, &def, &dt))
+ if (!vect_is_simple_use (lhs, loop_vinfo, NULL, &lhs_def_stmt, &def,
+ &dt))
return false;
}
else if (TREE_CODE (lhs) != INTEGER_CST && TREE_CODE (lhs) != REAL_CST
@@ -3669,7 +3725,8 @@ vect_is_simple_cond (tree cond, loop_vec_info loop_vinfo)
if (TREE_CODE (rhs) == SSA_NAME)
{
gimple rhs_def_stmt = SSA_NAME_DEF_STMT (rhs);
- if (!vect_is_simple_use (rhs, loop_vinfo, &rhs_def_stmt, &def, &dt))
+ if (!vect_is_simple_use (rhs, loop_vinfo, NULL, &rhs_def_stmt, &def,
+ &dt))
return false;
}
else if (TREE_CODE (rhs) != INTEGER_CST && TREE_CODE (rhs) != REAL_CST
@@ -3709,6 +3766,9 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
int ncopies = LOOP_VINFO_VECT_FACTOR (loop_vinfo) / nunits;
enum tree_code code;
+ /* FORNOW: unsupported in basic block SLP. */
+ gcc_assert (loop_vinfo);
+
gcc_assert (ncopies >= 1);
if (ncopies > 1)
return false; /* FORNOW */
@@ -3757,7 +3817,7 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
if (TREE_CODE (then_clause) == SSA_NAME)
{
gimple then_def_stmt = SSA_NAME_DEF_STMT (then_clause);
- if (!vect_is_simple_use (then_clause, loop_vinfo,
+ if (!vect_is_simple_use (then_clause, loop_vinfo, NULL,
&then_def_stmt, &def, &dt))
return false;
}
@@ -3769,7 +3829,7 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
if (TREE_CODE (else_clause) == SSA_NAME)
{
gimple else_def_stmt = SSA_NAME_DEF_STMT (else_clause);
- if (!vect_is_simple_use (else_clause, loop_vinfo,
+ if (!vect_is_simple_use (else_clause, loop_vinfo, NULL,
&else_def_stmt, &def, &dt))
return false;
}
@@ -3819,11 +3879,14 @@ vectorizable_condition (gimple stmt, gimple_stmt_iterator *gsi,
/* Make sure the statement is vectorizable. */
bool
-vect_analyze_stmt (gimple stmt, bool *need_to_vectorize)
+vect_analyze_stmt (gimple stmt, bool *need_to_vectorize, slp_tree node)
{
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
- enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info);
+ bb_vec_info bb_vinfo = STMT_VINFO_BB_VINFO (stmt_info);
+ enum vect_relevant relevance = STMT_VINFO_RELEVANT (stmt_info);
bool ok;
+ HOST_WIDE_INT dummy;
+ tree scalar_type, vectype;
if (vect_print_dump_info (REPORT_DETAILS))
{
@@ -3831,15 +3894,15 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize)
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
- /* Skip stmts that do not need to be vectorized. In loops this is expected
+ /* Skip stmts that do not need to be vectorized. In loops this is expected
to include:
- the COND_EXPR which is the loop exit condition
- any LABEL_EXPRs in the loop
- - computations that are used only for array indexing or loop control.
+ - computations that are used only for array indexing or loop control.
In basic blocks we only analyze statements that are a part of some SLP
instance, therefore, all the statements are relevant. */
- if (!STMT_VINFO_RELEVANT_P (stmt_info)
+ if (!STMT_VINFO_RELEVANT_P (stmt_info)
&& !STMT_VINFO_LIVE_P (stmt_info))
{
if (vect_print_dump_info (REPORT_DETAILS))
@@ -3854,9 +3917,9 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize)
break;
case vect_reduction_def:
- gcc_assert (relevance == vect_used_in_outer
+ gcc_assert (!bb_vinfo && (relevance == vect_used_in_outer
|| relevance == vect_used_in_outer_by_reduction
- || relevance == vect_unused_in_scope);
+ || relevance == vect_unused_in_scope));
break;
case vect_induction_def:
@@ -3867,6 +3930,37 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize)
gcc_unreachable ();
}
+ if (bb_vinfo)
+ {
+ gcc_assert (PURE_SLP_STMT (stmt_info));
+
+ scalar_type = vect_get_smallest_scalar_type (stmt, &dummy, &dummy);
+ if (vect_print_dump_info (REPORT_DETAILS))
+ {
+ fprintf (vect_dump, "get vectype for scalar type: ");
+ print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
+ }
+
+ vectype = get_vectype_for_scalar_type (scalar_type);
+ if (!vectype)
+ {
+ if (vect_print_dump_info (REPORT_DETAILS))
+ {
+ fprintf (vect_dump, "not SLPed: unsupported data-type ");
+ print_generic_expr (vect_dump, scalar_type, TDF_SLIM);
+ }
+ return false;
+ }
+
+ if (vect_print_dump_info (REPORT_DETAILS))
+ {
+ fprintf (vect_dump, "vectype: ");
+ print_generic_expr (vect_dump, vectype, TDF_SLIM);
+ }
+
+ STMT_VINFO_VECTYPE (stmt_info) = vectype;
+ }
+
if (STMT_VINFO_RELEVANT_P (stmt_info))
{
gcc_assert (!VECTOR_MODE_P (TYPE_MODE (gimple_expr_type (stmt))));
@@ -3875,8 +3969,9 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize)
}
ok = true;
- if (STMT_VINFO_RELEVANT_P (stmt_info)
- || STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def)
+ if (!bb_vinfo
+ && (STMT_VINFO_RELEVANT_P (stmt_info)
+ || STMT_VINFO_DEF_TYPE (stmt_info) == vect_reduction_def))
ok = (vectorizable_type_promotion (stmt, NULL, NULL, NULL)
|| vectorizable_type_demotion (stmt, NULL, NULL, NULL)
|| vectorizable_conversion (stmt, NULL, NULL, NULL)
@@ -3887,6 +3982,14 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize)
|| vectorizable_store (stmt, NULL, NULL, NULL)
|| vectorizable_condition (stmt, NULL, NULL)
|| vectorizable_reduction (stmt, NULL, NULL));
+ else
+ {
+ if (bb_vinfo)
+ ok = (vectorizable_operation (stmt, NULL, NULL, node)
+ || vectorizable_assignment (stmt, NULL, NULL, node)
+ || vectorizable_load (stmt, NULL, NULL, node, NULL)
+ || vectorizable_store (stmt, NULL, NULL, node));
+ }
if (!ok)
{
@@ -3896,10 +3999,13 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize)
fprintf (vect_dump, "supported: ");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
-
+
return false;
}
+ if (bb_vinfo)
+ return true;
+
/* Stmts that are (also) "live" (i.e. - that are used out of the loop)
need extra handling, except for vectorizable reductions. */
if (STMT_VINFO_LIVE_P (stmt_info)
@@ -3914,16 +4020,16 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize)
fprintf (vect_dump, "supported: ");
print_gimple_stmt (vect_dump, stmt, 0, TDF_SLIM);
}
-
+
return false;
}
if (!PURE_SLP_STMT (stmt_info))
{
- /* Groups of strided accesses whose size is not a power of 2 are not
- vectorizable yet using loop-vectorization. Therefore, if this stmt
- feeds non-SLP-able stmts (i.e., this stmt has to be both SLPed and
- loop-based vectorized), the loop cannot be vectorized. */
+ /* Groups of strided accesses whose size is not a power of 2 are not
+ vectorizable yet using loop-vectorization. Therefore, if this stmt
+ feeds non-SLP-able stmts (i.e., this stmt has to be both SLPed and
+ loop-based vectorized), the loop cannot be vectorized. */
if (STMT_VINFO_STRIDED_ACCESS (stmt_info)
&& exact_log2 (DR_GROUP_SIZE (vinfo_for_stmt (
DR_GROUP_FIRST_DR (stmt_info)))) == -1)
@@ -3938,7 +4044,7 @@ vect_analyze_stmt (gimple stmt, bool *need_to_vectorize)
return false;
}
}
-
+
return true;
}
@@ -3957,8 +4063,6 @@ vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi,
stmt_vec_info stmt_info = vinfo_for_stmt (stmt);
gimple orig_stmt_in_pattern;
bool done;
- loop_vec_info loop_vinfo = STMT_VINFO_LOOP_VINFO (stmt_info);
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
switch (STMT_VINFO_TYPE (stmt_info))
{
@@ -4045,19 +4149,23 @@ vect_transform_stmt (gimple stmt, gimple_stmt_iterator *gsi,
/* Handle inner-loop stmts whose DEF is used in the loop-nest that
is being vectorized, but outside the immediately enclosing loop. */
if (vec_stmt
- && nested_in_vect_loop_p (loop, stmt)
+ && STMT_VINFO_LOOP_VINFO (stmt_info)
+ && nested_in_vect_loop_p (LOOP_VINFO_LOOP (
+ STMT_VINFO_LOOP_VINFO (stmt_info)), stmt)
&& STMT_VINFO_TYPE (stmt_info) != reduc_vec_info_type
&& (STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_outer
- || STMT_VINFO_RELEVANT (stmt_info) == vect_used_in_outer_by_reduction))
+ || STMT_VINFO_RELEVANT (stmt_info) ==
+ vect_used_in_outer_by_reduction))
{
- struct loop *innerloop = loop->inner;
+ struct loop *innerloop = LOOP_VINFO_LOOP (
+ STMT_VINFO_LOOP_VINFO (stmt_info))->inner;
imm_use_iterator imm_iter;
use_operand_p use_p;
tree scalar_dest;
gimple exit_phi;
if (vect_print_dump_info (REPORT_DETAILS))
- fprintf (vect_dump, "Record the vdef for outer-loop vectorization.");
+ fprintf (vect_dump, "Record the vdef for outer-loop vectorization.");
/* Find the relevant loop-exit phi-node, and reord the vec_stmt there
(to be used when vectorizing outer-loop stmts that use the DEF of
@@ -4137,7 +4245,8 @@ vect_remove_stores (gimple first_stmt)
Create and initialize a new stmt_vec_info struct for STMT. */
stmt_vec_info
-new_stmt_vec_info (gimple stmt, loop_vec_info loop_vinfo)
+new_stmt_vec_info (gimple stmt, loop_vec_info loop_vinfo,
+ bb_vec_info bb_vinfo)
{
stmt_vec_info res;
res = (stmt_vec_info) xcalloc (1, sizeof (struct _stmt_vec_info));
@@ -4145,6 +4254,7 @@ new_stmt_vec_info (gimple stmt, loop_vec_info loop_vinfo)
STMT_VINFO_TYPE (res) = undef_vec_info_type;
STMT_VINFO_STMT (res) = stmt;
STMT_VINFO_LOOP_VINFO (res) = loop_vinfo;
+ STMT_VINFO_BB_VINFO (res) = bb_vinfo;
STMT_VINFO_RELEVANT (res) = vect_unused_in_scope;
STMT_VINFO_LIVE_P (res) = false;
STMT_VINFO_VECTYPE (res) = NULL;
@@ -4267,23 +4377,30 @@ get_vectype_for_scalar_type (tree scalar_type)
/* Function vect_is_simple_use.
Input:
- LOOP - the loop that is being vectorized.
- OPERAND - operand of a stmt in LOOP.
+ LOOP_VINFO - the vect info of the loop that is being vectorized.
+ BB_VINFO - the vect info of the basic block that is being vectorized.
+ OPERAND - operand of a stmt in the loop or bb.
DEF - the defining stmt in case OPERAND is an SSA_NAME.
Returns whether a stmt with OPERAND can be vectorized.
- Supportable operands are constants, loop invariants, and operands that are
- defined by the current iteration of the loop. Unsupportable operands are
- those that are defined by a previous iteration of the loop (as is the case
- in reduction/induction computations). */
+ For loops, supportable operands are constants, loop invariants, and operands
+ that are defined by the current iteration of the loop. Unsupportable
+ operands are those that are defined by a previous iteration of the loop (as
+ is the case in reduction/induction computations).
+ For basic blocks, supportable operands are constants and bb invariants.
+ For now, operands defined outside the basic block are not supported. */
bool
-vect_is_simple_use (tree operand, loop_vec_info loop_vinfo, gimple *def_stmt,
+vect_is_simple_use (tree operand, loop_vec_info loop_vinfo,
+ bb_vec_info bb_vinfo, gimple *def_stmt,
tree *def, enum vect_def_type *dt)
{
basic_block bb;
stmt_vec_info stmt_vinfo;
- struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+ struct loop *loop = NULL;
+
+ if (loop_vinfo)
+ loop = LOOP_VINFO_LOOP (loop_vinfo);
*def_stmt = NULL;
*def = NULL_TREE;
@@ -4299,6 +4416,7 @@ vect_is_simple_use (tree operand, loop_vec_info loop_vinfo, gimple *def_stmt,
*dt = vect_constant_def;
return true;
}
+
if (is_gimple_min_invariant (operand))
{
*def = operand;
@@ -4312,6 +4430,7 @@ vect_is_simple_use (tree operand, loop_vec_info loop_vinfo, gimple *def_stmt,
fprintf (vect_dump, "non-associatable copy.");
operand = TREE_OPERAND (operand, 0);
}
+
if (TREE_CODE (operand) != SSA_NAME)
{
if (vect_print_dump_info (REPORT_DETAILS))
@@ -4343,7 +4462,10 @@ vect_is_simple_use (tree operand, loop_vec_info loop_vinfo, gimple *def_stmt,
}
bb = gimple_bb (*def_stmt);
- if (!flow_bb_inside_loop_p (loop, bb))
+
+ if ((loop && !flow_bb_inside_loop_p (loop, bb))
+ || (!loop && bb != BB_VINFO_BB (bb_vinfo))
+ || (!loop && gimple_code (*def_stmt) == GIMPLE_PHI))
*dt = vect_external_def;
else
{
diff --git a/gcc/tree-vectorizer.c b/gcc/tree-vectorizer.c
index b4985475d78..4ab8547dee2 100644
--- a/gcc/tree-vectorizer.c
+++ b/gcc/tree-vectorizer.c
@@ -68,6 +68,7 @@ along with GCC; see the file COPYING3. If not see
#include "cfglayout.h"
#include "tree-vectorizer.h"
#include "tree-pass.h"
+#include "timevar.h"
/* vect_dump will be set to stderr or dump_file if exist. */
FILE *vect_dump;
@@ -75,8 +76,9 @@ FILE *vect_dump;
/* vect_verbosity_level set to an invalid value
to mark that it's uninitialized. */
static enum verbosity_levels vect_verbosity_level = MAX_VERBOSITY_LEVEL;
+static enum verbosity_levels user_vect_verbosity_level = MAX_VERBOSITY_LEVEL;
-/* Loop location. */
+/* Loop or bb location. */
LOC vect_location;
/* Bitmap of virtual variables to be renamed. */
@@ -99,9 +101,10 @@ vect_set_verbosity_level (const char *val)
vl = atoi (val);
if (vl < MAX_VERBOSITY_LEVEL)
- vect_verbosity_level = (enum verbosity_levels) vl;
+ user_vect_verbosity_level = (enum verbosity_levels) vl;
else
- vect_verbosity_level = (enum verbosity_levels) (MAX_VERBOSITY_LEVEL - 1);
+ user_vect_verbosity_level
+ = (enum verbosity_levels) (MAX_VERBOSITY_LEVEL - 1);
}
@@ -115,17 +118,33 @@ vect_set_verbosity_level (const char *val)
print to stderr, otherwise print to the dump file. */
static void
-vect_set_dump_settings (void)
+vect_set_dump_settings (bool slp)
{
vect_dump = dump_file;
/* Check if the verbosity level was defined by the user: */
- if (vect_verbosity_level != MAX_VERBOSITY_LEVEL)
+ if (user_vect_verbosity_level != MAX_VERBOSITY_LEVEL)
{
- /* If there is no dump file, print to stderr. */
- if (!dump_file)
- vect_dump = stderr;
- return;
+ vect_verbosity_level = user_vect_verbosity_level;
+ /* Ignore user defined verbosity if dump flags require higher level of
+ verbosity. */
+ if (dump_file)
+ {
+ if (((dump_flags & TDF_DETAILS)
+ && vect_verbosity_level >= REPORT_DETAILS)
+ || ((dump_flags & TDF_STATS)
+ && vect_verbosity_level >= REPORT_UNVECTORIZED_LOCATIONS))
+ return;
+ }
+ else
+ {
+ /* If there is no dump file, print to stderr in case of loop
+ vectorization. */
+ if (!slp)
+ vect_dump = stderr;
+
+ return;
+ }
}
/* User didn't specify verbosity level: */
@@ -185,7 +204,7 @@ vectorize_loops (void)
return 0;
/* Fix the verbosity level if not defined explicitly by the user. */
- vect_set_dump_settings ();
+ vect_set_dump_settings (false);
/* Allocate the bitmap that records which virtual variables
need to be renamed. */
@@ -245,6 +264,68 @@ vectorize_loops (void)
}
+/* Entry point to basic block SLP phase. */
+
+static unsigned int
+execute_vect_slp (void)
+{
+ basic_block bb;
+
+ /* Fix the verbosity level if not defined explicitly by the user. */
+ vect_set_dump_settings (true);
+
+ init_stmt_vec_info_vec ();
+
+ FOR_EACH_BB (bb)
+ {
+ vect_location = find_bb_location (bb);
+
+ if (vect_slp_analyze_bb (bb))
+ {
+ vect_slp_transform_bb (bb);
+
+ if (vect_print_dump_info (REPORT_VECTORIZED_LOCATIONS))
+ fprintf (vect_dump, "basic block vectorized using SLP\n");
+ }
+ }
+
+ free_stmt_vec_info_vec ();
+ return 0;
+}
+
+static bool
+gate_vect_slp (void)
+{
+ /* Apply SLP either if the vectorizer is on and the user didn't specify
+ whether to run SLP or not, or if the SLP flag was set by the user. */
+ return ((flag_tree_vectorize != 0 && flag_tree_slp_vectorize != 0)
+ || flag_tree_slp_vectorize == 1);
+}
+
+struct gimple_opt_pass pass_slp_vectorize =
+{
+ {
+ GIMPLE_PASS,
+ "slp", /* name */
+ gate_vect_slp, /* gate */
+ execute_vect_slp, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_TREE_SLP_VECTORIZATION, /* tv_id */
+ PROP_ssa | PROP_cfg, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_ggc_collect
+ | TODO_verify_ssa
+ | TODO_dump_func
+ | TODO_update_ssa
+ | TODO_verify_stmts /* todo_flags_finish */
+ }
+};
+
+
/* Increase alignment of global arrays to improve vectorization potential.
TODO:
- Consider also structs that have an array field.
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 2422f4416e1..bf2917008b1 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -281,6 +281,36 @@ nested_in_vect_loop_p (struct loop *loop, gimple stmt)
&& (loop->inner == (gimple_bb (stmt))->loop_father));
}
+typedef struct _bb_vec_info {
+
+ basic_block bb;
+ /* All interleaving chains of stores in the basic block, represented by the
+ first stmt in the chain. */
+ VEC(gimple, heap) *strided_stores;
+
+ /* All SLP instances in the basic block. This is a subset of the set of
+ STRIDED_STORES of the basic block. */
+ VEC(slp_instance, heap) *slp_instances;
+
+ /* All data references in the basic block. */
+ VEC (data_reference_p, heap) *datarefs;
+
+ /* All data dependences in the basic block. */
+ VEC (ddr_p, heap) *ddrs;
+} *bb_vec_info;
+
+#define BB_VINFO_BB(B) (B)->bb
+#define BB_VINFO_STRIDED_STORES(B) (B)->strided_stores
+#define BB_VINFO_SLP_INSTANCES(B) (B)->slp_instances
+#define BB_VINFO_DATAREFS(B) (B)->datarefs
+#define BB_VINFO_DDRS(B) (B)->ddrs
+
+static inline bb_vec_info
+vec_info_for_bb (basic_block bb)
+{
+ return (bb_vec_info) bb->aux;
+}
+
/*-----------------------------------------------------------------*/
/* Info on vectorized defs. */
/*-----------------------------------------------------------------*/
@@ -437,12 +467,16 @@ typedef struct _stmt_vec_info {
/* Whether the stmt is SLPed, loop-based vectorized, or both. */
enum slp_vect_type slp_type;
+
+ /* The bb_vec_info with respect to which STMT is vectorized. */
+ bb_vec_info bb_vinfo;
} *stmt_vec_info;
/* Access Functions. */
#define STMT_VINFO_TYPE(S) (S)->type
#define STMT_VINFO_STMT(S) (S)->stmt
#define STMT_VINFO_LOOP_VINFO(S) (S)->loop_vinfo
+#define STMT_VINFO_BB_VINFO(S) (S)->bb_vinfo
#define STMT_VINFO_RELEVANT(S) (S)->relevant
#define STMT_VINFO_LIVE_P(S) (S)->live
#define STMT_VINFO_VECTYPE(S) (S)->vectype
@@ -707,15 +741,15 @@ extern void slpeel_make_loop_iterate_ntimes (struct loop *, tree);
extern bool slpeel_can_duplicate_loop_p (const struct loop *, const_edge);
extern void vect_loop_versioning (loop_vec_info, bool, tree *, gimple_seq *);
extern void vect_do_peeling_for_loop_bound (loop_vec_info, tree *,
- tree, gimple_seq);
+ tree, gimple_seq);
extern void vect_do_peeling_for_alignment (loop_vec_info);
extern LOC find_loop_location (struct loop *);
extern bool vect_can_advance_ivs_p (loop_vec_info);
/* In tree-vect-stmts.c. */
extern tree get_vectype_for_scalar_type (tree);
-extern bool vect_is_simple_use (tree, loop_vec_info, gimple *, tree *,
- enum vect_def_type *);
+extern bool vect_is_simple_use (tree, loop_vec_info, bb_vec_info, gimple *,
+ tree *, enum vect_def_type *);
extern bool supportable_widening_operation (enum tree_code, gimple, tree,
tree *, tree *, enum tree_code *,
enum tree_code *, int *,
@@ -723,7 +757,8 @@ extern bool supportable_widening_operation (enum tree_code, gimple, tree,
extern bool supportable_narrowing_operation (enum tree_code, const_gimple,
tree, enum tree_code *, int *,
VEC (tree, heap) **);
-extern stmt_vec_info new_stmt_vec_info (gimple stmt, loop_vec_info);
+extern stmt_vec_info new_stmt_vec_info (gimple stmt, loop_vec_info,
+ bb_vec_info);
extern void free_stmt_vec_info (gimple stmt);
extern tree vectorizable_function (gimple, tree, tree);
extern void vect_model_simple_cost (stmt_vec_info, int, enum vect_def_type *,
@@ -742,7 +777,7 @@ extern tree vect_get_vec_def_for_stmt_copy (enum vect_def_type, tree);
extern bool vect_transform_stmt (gimple, gimple_stmt_iterator *,
bool *, slp_tree, slp_instance);
extern void vect_remove_stores (gimple);
-extern bool vect_analyze_stmt (gimple, bool *);
+extern bool vect_analyze_stmt (gimple, bool *, slp_tree);
/* In tree-vect-data-refs.c. */
extern bool vect_can_force_dr_alignment_p (const_tree, unsigned int);
@@ -750,14 +785,15 @@ extern enum dr_alignment_support vect_supportable_dr_alignment
(struct data_reference *);
extern tree vect_get_smallest_scalar_type (gimple, HOST_WIDE_INT *,
HOST_WIDE_INT *);
-extern bool vect_analyze_data_ref_dependences (loop_vec_info);
+extern bool vect_analyze_data_ref_dependences (loop_vec_info, bb_vec_info);
extern bool vect_enhance_data_refs_alignment (loop_vec_info);
-extern bool vect_analyze_data_refs_alignment (loop_vec_info);
-extern bool vect_analyze_data_ref_accesses (loop_vec_info);
+extern bool vect_analyze_data_refs_alignment (loop_vec_info, bb_vec_info);
+extern bool vect_verify_datarefs_alignment (loop_vec_info, bb_vec_info);
+extern bool vect_analyze_data_ref_accesses (loop_vec_info, bb_vec_info);
extern bool vect_prune_runtime_alias_test_list (loop_vec_info);
-extern bool vect_analyze_data_refs (loop_vec_info);
+extern bool vect_analyze_data_refs (loop_vec_info, bb_vec_info);
extern tree vect_create_data_ref_ptr (gimple, struct loop *, tree, tree *,
- gimple *, bool, bool *);
+ gimple *, bool, bool *);
extern tree bump_vector_ptr (tree, gimple, gimple_stmt_iterator *, gimple, tree);
extern tree vect_create_destination_var (tree, tree);
extern bool vect_strided_store_supported (tree);
@@ -799,13 +835,16 @@ extern void vect_free_slp_instance (slp_instance);
extern bool vect_transform_slp_perm_load (gimple, VEC (tree, heap) *,
gimple_stmt_iterator *, int,
slp_instance, bool);
-extern bool vect_schedule_slp (loop_vec_info);
+extern bool vect_schedule_slp (loop_vec_info, bb_vec_info);
extern void vect_update_slp_costs_according_to_vf (loop_vec_info);
-extern bool vect_analyze_slp (loop_vec_info);
+extern bool vect_analyze_slp (loop_vec_info, bb_vec_info);
extern void vect_make_slp_decision (loop_vec_info);
extern void vect_detect_hybrid_slp (loop_vec_info);
extern void vect_get_slp_defs (slp_tree, VEC (tree,heap) **,
VEC (tree,heap) **);
+extern LOC find_bb_location (basic_block);
+extern bb_vec_info vect_slp_analyze_bb (basic_block);
+extern void vect_slp_transform_bb (basic_block);
/* In tree-vect-patterns.c. */
/* Pattern recognition functions.
diff --git a/gcc/tree.c b/gcc/tree.c
index 069b1356943..82d2010d45d 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -1827,6 +1827,23 @@ build_tree_list_stat (tree parm, tree value MEM_STAT_DECL)
return t;
}
+/* Build a chain of TREE_LIST nodes from a vector. */
+
+tree
+build_tree_list_vec_stat (const VEC(tree,gc) *vec MEM_STAT_DECL)
+{
+ tree ret = NULL_TREE;
+ tree *pp = &ret;
+ unsigned int i;
+ tree t;
+ for (i = 0; VEC_iterate (tree, vec, i, t); ++i)
+ {
+ *pp = build_tree_list_stat (NULL, t PASS_MEM_STAT);
+ pp = &TREE_CHAIN (*pp);
+ }
+ return ret;
+}
+
/* Return a newly created TREE_LIST node whose
purpose and value fields are PURPOSE and VALUE
and whose TREE_CHAIN is CHAIN. */
@@ -1870,6 +1887,22 @@ ctor_to_list (tree ctor)
return list;
}
+
+/* Return the values of the elements of a CONSTRUCTOR as a vector of
+ trees. */
+
+VEC(tree,gc) *
+ctor_to_vec (tree ctor)
+{
+ VEC(tree, gc) *vec = VEC_alloc (tree, gc, CONSTRUCTOR_NELTS (ctor));
+ unsigned int ix;
+ tree val;
+
+ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (ctor), ix, val)
+ VEC_quick_push (tree, vec, val);
+
+ return vec;
+}
/* Return the size nominally occupied by an object of type TYPE
when it resides in memory. The value is measured in units of bytes,
@@ -3483,6 +3516,23 @@ build_nt_call_list (tree fn, tree arglist)
CALL_EXPR_ARG (t, i) = TREE_VALUE (arglist);
return t;
}
+
+/* Similar to build_nt, but for creating a CALL_EXPR object with a
+ tree VEC. */
+
+tree
+build_nt_call_vec (tree fn, VEC(tree,gc) *args)
+{
+ tree ret, t;
+ unsigned int ix;
+
+ ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3);
+ CALL_EXPR_FN (ret) = fn;
+ CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
+ for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix)
+ CALL_EXPR_ARG (ret, ix) = t;
+ return ret;
+}
/* Create a DECL_... node of code CODE, name NAME and data type TYPE.
We do NOT enter this node in any sort of symbol table.
@@ -4025,6 +4075,7 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
bool *no_add_attrs)
{
tree node = *pnode;
+ bool is_dllimport;
/* These attributes may apply to structure and union types being created,
but otherwise should pass to the declaration involved. */
@@ -4072,9 +4123,11 @@ handle_dll_attribute (tree * pnode, tree name, tree args, int flags,
return NULL_TREE;
}
+ is_dllimport = is_attribute_p ("dllimport", name);
+
/* Report error on dllimport ambiguities seen now before they cause
any damage. */
- else if (is_attribute_p ("dllimport", name))
+ if (is_dllimport)
{
/* Honor any target-specific overrides. */
if (!targetm.valid_dllimport_attribute_p (node))
@@ -4116,6 +4169,9 @@ 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))
+ /* An exported function, even if inline, must be emitted. */
+ DECL_EXTERNAL (node) = 0;
/* Report error if symbol is not accessible at global scope. */
if (!TREE_PUBLIC (node)
@@ -5366,11 +5422,13 @@ iterative_hash_expr (const_tree t, hashval_t val)
return val;
}
case FUNCTION_DECL:
- /* When referring to a built-in FUNCTION_DECL, use the
- __builtin__ form. Otherwise nodes that compare equal
- according to operand_equal_p might get different
- hash codes. */
- if (DECL_BUILT_IN (t) && built_in_decls[DECL_FUNCTION_CODE (t)])
+ /* When referring to a built-in FUNCTION_DECL, use the __builtin__ form.
+ Otherwise nodes that compare equal according to operand_equal_p might
+ get different hash codes. However, don't do this for machine specific
+ or front end builtins, since the function code is overloaded in those
+ cases. */
+ if (DECL_BUILT_IN_CLASS (t) == BUILT_IN_NORMAL
+ && built_in_decls[DECL_FUNCTION_CODE (t)])
{
t = built_in_decls[DECL_FUNCTION_CODE (t)];
code = TREE_CODE (t);
@@ -7388,7 +7446,8 @@ make_vector_type (tree innertype, int nunits, enum machine_mode mode)
{
tree index = build_int_cst (NULL_TREE, nunits - 1);
- tree array = build_array_type (innertype, build_index_type (index));
+ tree array = build_array_type (TYPE_MAIN_VARIANT (innertype),
+ build_index_type (index));
tree rt = make_node (RECORD_TYPE);
TYPE_FIELDS (rt) = build_decl (FIELD_DECL, get_identifier ("f"), array);
@@ -8240,7 +8299,7 @@ build_call_valist (tree return_type, tree fn, int nargs, va_list args)
which are specified as a tree array ARGS. */
tree
-build_call_array (tree return_type, tree fn, int nargs, tree *args)
+build_call_array (tree return_type, tree fn, int nargs, const tree *args)
{
tree t;
int i;
@@ -8255,6 +8314,24 @@ build_call_array (tree return_type, tree fn, int nargs, tree *args)
return t;
}
+/* Like build_call_array, but takes a VEC. */
+
+tree
+build_call_vec (tree return_type, tree fn, VEC(tree,gc) *args)
+{
+ tree ret, t;
+ unsigned int ix;
+
+ ret = build_vl_exp (CALL_EXPR, VEC_length (tree, args) + 3);
+ TREE_TYPE (ret) = return_type;
+ CALL_EXPR_FN (ret) = fn;
+ CALL_EXPR_STATIC_CHAIN (ret) = NULL_TREE;
+ for (ix = 0; VEC_iterate (tree, args, ix, t); ++ix)
+ CALL_EXPR_ARG (ret, ix) = t;
+ process_call_operands (ret);
+ return ret;
+}
+
/* Returns true if it is possible to prove that the index of
an array access REF (an ARRAY_REF expression) falls into the
@@ -8887,10 +8964,6 @@ walk_tree_1 (tree *tp, walk_tree_fn func, void *data,
WALK_SUBTREE_TAIL (TREE_OPERAND (*tp, len));
}
- case CHANGE_DYNAMIC_TYPE_EXPR:
- WALK_SUBTREE (CHANGE_DYNAMIC_TYPE_NEW_TYPE (*tp));
- WALK_SUBTREE_TAIL (CHANGE_DYNAMIC_TYPE_LOCATION (*tp));
-
case DECL_EXPR:
/* If this is a TYPE_DECL, walk into the fields of the type that it's
defining. We only want to walk into these fields of a type in this
diff --git a/gcc/tree.def b/gcc/tree.def
index 41a9e908cab..b4828ad9478 100644
--- a/gcc/tree.def
+++ b/gcc/tree.def
@@ -913,15 +913,6 @@ DEFTREECODE (CATCH_EXPR, "catch_expr", tcc_statement, 2)
expanding. */
DEFTREECODE (EH_FILTER_EXPR, "eh_filter_expr", tcc_statement, 2)
-/* Indicates a change in the dynamic type of a memory location. This
- has no value and generates no executable code. It is only used for
- type based alias analysis. This is generated by C++ placement new.
- CHANGE_DYNAMIC_TYPE_NEW_TYPE, the first operand, is the new type.
- CHANGE_DYNAMIC_TYPE_LOCATION, the second operand, is the location
- whose type is being changed. */
-DEFTREECODE (CHANGE_DYNAMIC_TYPE_EXPR, "change_dynamic_type_expr",
- tcc_statement, 2)
-
/* Node used for describing a property that is known at compile
time. */
DEFTREECODE (SCEV_KNOWN, "scev_known", tcc_expression, 0)
diff --git a/gcc/tree.h b/gcc/tree.h
index 66d4e25fe2d..0adf75d9530 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -1648,12 +1648,6 @@ extern void protected_set_expr_location (tree, location_t);
#define EH_FILTER_MUST_NOT_THROW(NODE) \
(EH_FILTER_EXPR_CHECK (NODE)->base.static_flag)
-/* CHANGE_DYNAMIC_TYPE_EXPR accessors. */
-#define CHANGE_DYNAMIC_TYPE_NEW_TYPE(NODE) \
- TREE_OPERAND (CHANGE_DYNAMIC_TYPE_EXPR_CHECK (NODE), 0)
-#define CHANGE_DYNAMIC_TYPE_LOCATION(NODE) \
- TREE_OPERAND (CHANGE_DYNAMIC_TYPE_EXPR_CHECK (NODE), 1)
-
/* OBJ_TYPE_REF accessors. */
#define OBJ_TYPE_REF_EXPR(NODE) TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 0)
#define OBJ_TYPE_REF_OBJECT(NODE) TREE_OPERAND (OBJ_TYPE_REF_CHECK (NODE), 1)
@@ -2605,11 +2599,6 @@ struct GTY(()) tree_decl_minimal {
#define DECL_GIMPLE_REG_P(DECL) \
DECL_COMMON_CHECK (DECL)->decl_common.gimple_reg_flag
-/* For a DECL with pointer type, this is set if Type Based Alias
- Analysis should not be applied to this DECL. */
-#define DECL_NO_TBAA_P(DECL) \
- DECL_COMMON_CHECK (DECL)->decl_common.no_tbaa_flag
-
struct GTY(()) tree_decl_common {
struct tree_decl_minimal common;
tree size;
@@ -2649,12 +2638,10 @@ struct GTY(()) tree_decl_common {
/* Logically, these two would go in a theoretical base shared by var and
parm decl. */
unsigned gimple_reg_flag : 1;
- /* In a DECL with pointer type, set if no TBAA should be done. */
- unsigned no_tbaa_flag : 1;
/* In VAR_DECL, PARM_DECL and RESULT_DECL, this is DECL_BY_REFERENCE. */
unsigned decl_by_reference_flag : 1;
/* Padding so that 'off_align' can be on a 32-bit boundary. */
- unsigned decl_common_unused : 1;
+ unsigned decl_common_unused : 2;
/* DECL_OFFSET_ALIGN, used only for FIELD_DECLs. */
unsigned int off_align : 8;
@@ -3833,6 +3820,7 @@ extern tree maybe_get_identifier (const char *);
extern tree build_nt (enum tree_code, ...);
extern tree build_nt_call_list (tree, tree);
+extern tree build_nt_call_vec (tree, VEC(tree,gc) *);
extern tree build0_stat (enum tree_code, tree MEM_STAT_DECL);
#define build0(c,t) build0_stat (c,t MEM_STAT_INFO)
@@ -3870,6 +3858,8 @@ extern tree build_one_cst (tree);
extern tree build_string (int, const char *);
extern tree build_tree_list_stat (tree, tree MEM_STAT_DECL);
#define build_tree_list(t,q) build_tree_list_stat(t,q MEM_STAT_INFO)
+extern tree build_tree_list_vec_stat (const VEC(tree,gc) * MEM_STAT_DECL);
+#define build_tree_list_vec(v) build_tree_list_vec_stat (v MEM_STAT_INFO)
extern tree build_decl_stat (enum tree_code, tree, tree MEM_STAT_DECL);
extern tree build_fn_decl (const char *, tree);
#define build_decl(c,t,q) build_decl_stat (c,t,q MEM_STAT_INFO)
@@ -3883,7 +3873,8 @@ extern tree build_vl_exp_stat (enum tree_code, int MEM_STAT_DECL);
extern tree build_call_list (tree, tree, tree);
extern tree build_call_nary (tree, tree, int, ...);
extern tree build_call_valist (tree, tree, int, va_list);
-extern tree build_call_array (tree, tree, int, tree*);
+extern tree build_call_array (tree, tree, int, const tree *);
+extern tree build_call_vec (tree, tree, VEC(tree,gc) *);
/* Construct various nodes representing data types. */
@@ -4310,6 +4301,10 @@ extern bool initializer_zerop (const_tree);
extern tree ctor_to_list (tree);
+/* Given a CONSTRUCTOR CTOR, return the element values as a vector. */
+
+extern VEC(tree,gc) *ctor_to_vec (tree);
+
/* Examine CTOR to discover:
* how many scalar fields are set to nonzero values,
and place it in *P_NZ_ELTS;
diff --git a/gcc/unwind-dw2-fde.c b/gcc/unwind-dw2-fde.c
index fcac25f7259..4aa9d82af8d 100644
--- a/gcc/unwind-dw2-fde.c
+++ b/gcc/unwind-dw2-fde.c
@@ -318,8 +318,9 @@ static int
fde_unencoded_compare (struct object *ob __attribute__((unused)),
const fde *x, const fde *y)
{
- const _Unwind_Ptr x_ptr = *(const _Unwind_Ptr *) x->pc_begin;
- const _Unwind_Ptr y_ptr = *(const _Unwind_Ptr *) y->pc_begin;
+ _Unwind_Ptr x_ptr, y_ptr;
+ memcpy (&x_ptr, x->pc_begin, sizeof (_Unwind_Ptr));
+ memcpy (&y_ptr, y->pc_begin, sizeof (_Unwind_Ptr));
if (x_ptr > y_ptr)
return 1;
@@ -674,7 +675,9 @@ add_fdes (struct object *ob, struct fde_accumulator *accu, const fde *this_fde)
if (encoding == DW_EH_PE_absptr)
{
- if (*(const _Unwind_Ptr *) this_fde->pc_begin == 0)
+ _Unwind_Ptr ptr;
+ memcpy (&ptr, this_fde->pc_begin, sizeof (_Unwind_Ptr));
+ if (ptr == 0)
continue;
}
else
@@ -792,8 +795,9 @@ linear_search_fdes (struct object *ob, const fde *this_fde, void *pc)
if (encoding == DW_EH_PE_absptr)
{
- pc_begin = ((const _Unwind_Ptr *) this_fde->pc_begin)[0];
- pc_range = ((const _Unwind_Ptr *) this_fde->pc_begin)[1];
+ const _Unwind_Ptr *pc_array = (const _Unwind_Ptr *) this_fde->pc_begin;
+ pc_begin = pc_array[0];
+ pc_range = pc_array[1];
if (pc_begin == 0)
continue;
}
@@ -840,8 +844,10 @@ binary_search_unencoded_fdes (struct object *ob, void *pc)
{
size_t i = (lo + hi) / 2;
const fde *const f = vec->array[i];
- const void *pc_begin = ((const void *const*) f->pc_begin)[0];
- const uaddr pc_range = ((const uaddr *) f->pc_begin)[1];
+ void *pc_begin;
+ uaddr pc_range;
+ memcpy (&pc_begin, (const void * const *) f->pc_begin, sizeof (void *));
+ memcpy (&pc_range, (const uaddr *) f->pc_begin + 1, sizeof (uaddr));
if (pc < pc_begin)
hi = i;
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